From 139773052b4b7393b2e94de03ea81f090a15d4e9 Mon Sep 17 00:00:00 2001 From: sharad-patil24 <100128124+sharad-patil24@users.noreply.github.com> Date: Mon, 21 Aug 2023 21:16:29 +0530 Subject: [PATCH] Newly Added files for Wifi SDK 3.0 Integration (#28752) * Newly Added files for Wifi SDK 3.0 Integration * Build issue * Google Address resolution fix * Removed ble_config since modify in PR 28558 * Add symbolic Link to ble_config * Corrected Symbolic link for ble_config.h --------- Co-authored-by: Jean-Francois Penven --- .../silabs/SiWx917/SiWx917/sl_wifi_if.c | 789 ++++++++++++++++++ .../silabs/SiWx917/SiWx917/sl_wlan_config.h | 113 +++ .../silabs/ldscripts/SiWx917-common.ld | 240 ++++++ src/platform/silabs/rs911x/ble_config.h | 1 + 4 files changed, 1143 insertions(+) create mode 100644 examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c create mode 100644 examples/platform/silabs/SiWx917/SiWx917/sl_wlan_config.h create mode 100644 examples/platform/silabs/ldscripts/SiWx917-common.ld create mode 120000 src/platform/silabs/rs911x/ble_config.h diff --git a/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c new file mode 100644 index 00000000000000..f54175ae9733da --- /dev/null +++ b/examples/platform/silabs/SiWx917/SiWx917/sl_wifi_if.c @@ -0,0 +1,789 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "silabs_utils.h" +#include "sl_status.h" + +#include "FreeRTOS.h" +#include "event_groups.h" +#include "sl_board_configuration.h" +#include "sl_net.h" +#include "sl_si91x_host_interface.h" +#include "sl_si91x_types.h" +#include "sl_wifi_callback_framework.h" +#include "sl_wifi_constants.h" +#include "sl_wifi_types.h" +#include "sl_wlan_config.h" +#include "task.h" +#include "wfx_host_events.h" + +#include "rsi_ble_config.h" + +#include "dhcp_client.h" +#include "lwip/nd6.h" +#include "sl_wifi.h" +#include "wfx_host_events.h" +#include "wfx_rsi.h" +#define ADV_SCAN_THRESHOLD -40 +#define ADV_RSSI_TOLERANCE_THRESHOLD 5 +#define ADV_ACTIVE_SCAN_DURATION 15 +#define ADV_PASSIVE_SCAN_DURATION 20 +#define ADV_MULTIPROBE 1 +#define ADV_SCAN_PERIODICITY 10 + +struct wfx_rsi wfx_rsi; + +/* Declare a variable to hold the data associated with the created event group. */ +StaticEventGroup_t rsiDriverEventGroup; + +bool hasNotifiedIPV6 = false; +#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) +bool hasNotifiedIPV4 = false; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ +bool hasNotifiedWifiConnectivity = false; + +/* Declare a flag to differentiate between after boot-up first IP connection or reconnection */ +bool is_wifi_disconnection_event = false; + +/* Declare a variable to hold connection time intervals */ +uint32_t retryInterval = WLAN_MIN_RETRY_TIMER_MS; +volatile bool scan_results_complete = false; +#define WIFI_SCAN_TIMEOUT 10000 // WiFi Scan interval + +extern osSemaphoreId_t sl_rs_ble_init_sem; + +/* + * This file implements the interface to the wifi sdk + */ + +wfx_wifi_scan_ext_t * temp_reset; + +volatile sl_status_t callback_status = SL_STATUS_OK; + +/****************************************************************** + * @fn int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t *ap) + * @brief + * Getting the AP details + * @param[in] ap: access point + * @return + * status + *********************************************************************/ +int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap) +{ + sl_status_t status = SL_STATUS_OK; + uint8_t rssi = 0; + ap->security = wfx_rsi.sec.security; + ap->chan = wfx_rsi.ap_chan; + memcpy(&ap->bssid[0], &wfx_rsi.ap_mac.octet[0], BSSID_MAX_STR_LEN); + sl_wifi_get_signal_strength(SL_WIFI_CLIENT_INTERFACE, &rssi); + ap->rssi = rssi; + + return status; +} + +/****************************************************************** + * @fn int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t *extra_info) + * @brief + * Getting the AP extra details + * @param[in] extra info: access point extra information + * @return + * status + *********************************************************************/ +int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info) +{ + sl_status_t status = SL_STATUS_OK; + sl_wifi_statistics_t test = { 0 }; + status = sl_wifi_get_statistics(SL_WIFI_CLIENT_INTERFACE, &test); + VERIFY_STATUS_AND_RETURN(status); + extra_info->beacon_lost_count = test.beacon_lost_count - temp_reset->beacon_lost_count; + extra_info->beacon_rx_count = test.beacon_rx_count - temp_reset->beacon_rx_count; + extra_info->mcast_rx_count = test.mcast_rx_count - temp_reset->mcast_rx_count; + extra_info->mcast_tx_count = test.mcast_tx_count - temp_reset->mcast_tx_count; + extra_info->ucast_rx_count = test.ucast_rx_count - temp_reset->ucast_rx_count; + extra_info->ucast_tx_count = test.ucast_tx_count - temp_reset->ucast_tx_count; + extra_info->overrun_count = test.overrun_count - temp_reset->overrun_count; + return status; +} + +/****************************************************************** + * @fn int32_t wfx_rsi_reset_count() + * @brief + * Getting the driver reset count + * @param[in] None + * @return + * status + *********************************************************************/ +int32_t wfx_rsi_reset_count() +{ + sl_wifi_statistics_t test = { 0 }; + sl_status_t status = SL_STATUS_OK; + status = sl_wifi_get_statistics(SL_WIFI_CLIENT_INTERFACE, &test); + VERIFY_STATUS_AND_RETURN(status); + temp_reset->beacon_lost_count = test.beacon_lost_count; + temp_reset->beacon_rx_count = test.beacon_rx_count; + temp_reset->mcast_rx_count = test.mcast_rx_count; + temp_reset->mcast_tx_count = test.mcast_tx_count; + temp_reset->ucast_rx_count = test.ucast_rx_count; + temp_reset->ucast_tx_count = test.ucast_tx_count; + temp_reset->overrun_count = test.overrun_count; + return status; +} + +/****************************************************************** + * @fn wfx_rsi_disconnect() + * @brief + * Getting the driver disconnect status + * @param[in] None + * @return + * status + *********************************************************************/ +int32_t wfx_rsi_disconnect() +{ + return sl_wifi_disconnect(SL_WIFI_CLIENT_INTERFACE); +} + +sl_status_t join_callback_handler(sl_wifi_event_t event, char * result, uint32_t result_length, void * arg) +{ + temp_reset = (wfx_wifi_scan_ext_t *) malloc(sizeof(wfx_wifi_scan_ext_t)); + memset(temp_reset, 0, sizeof(wfx_wifi_scan_ext_t)); + if (CHECK_IF_EVENT_FAILED(event)) + { + SILABS_LOG("F: Join Event received with %u bytes payload\n", result_length); + callback_status = *(sl_status_t *) result; + wfx_rsi.join_retries += 1; + wfx_rsi.dev_state &= ~(WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED); + wfx_retry_interval_handler(is_wifi_disconnection_event, wfx_rsi.join_retries++); + if (is_wifi_disconnection_event || wfx_rsi.join_retries <= WFX_RSI_CONFIG_MAX_JOIN) + { + xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN); + } + is_wifi_disconnection_event = true; + return SL_STATUS_FAIL; + } + /* + * Join was complete - Do the DHCP + */ + SILABS_LOG("Join Completed %c: Join Event received with %u bytes payload\n", *result, result_length); + xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_CONN); + wfx_rsi.join_retries = 0; + retryInterval = WLAN_MIN_RETRY_TIMER_MS; + if (is_wifi_disconnection_event) + is_wifi_disconnection_event = false; + callback_status = SL_STATUS_OK; + return SL_STATUS_OK; +} + +#if CHIP_DEVICE_CONFIG_ENABLE_SED +/****************************************************************** + * @fn wfx_rsi_power_save() + * @brief + * Setting the RS911x in DTIM sleep based mode + * + * @param[in] None + * @return + * None + *********************************************************************/ +int32_t wfx_rsi_power_save() +{ + int32_t status; + status = rsi_bt_power_save_profile(2, 0); + if (status != RSI_SUCCESS) + { + SILABS_LOG("BT Powersave Config Failed, Error Code : 0x%lX", status); + return status; + } + + sl_wifi_performance_profile_t wifi_profile = { ASSOCIATED_POWER_SAVE }; + status = sl_wifi_set_performance_profile(&wifi_profile); + if (status != RSI_SUCCESS) + { + SILABS_LOG("Powersave Config Failed, Error Code : 0x%lX", status); + return status; + } + SILABS_LOG("Powersave Config Success"); + return status; +} +#endif /* CHIP_DEVICE_CONFIG_ENABLE_SED */ + +/************************************************************************************* + * @fn static int32_t wfx_wifi_rsi_init(void) + * @brief + * Wifi initialization called from app main + * @param[in] None + * @return + * None + *****************************************************************************************/ +int32_t wfx_wifi_rsi_init(void) +{ + sl_status_t status; + status = sl_wifi_init(&config, default_wifi_event_handler); + if (status != SL_STATUS_OK) + { + SILABS_LOG("wfx_wifi_rsi_init failed %x", status); + return status; + } + return status; +} + +/************************************************************************************* + * @fn static int32_t wfx_rsi_init(void) + * @brief + * driver initialization + * @param[in] None + * @return + * None + *****************************************************************************************/ +static int32_t wfx_rsi_init(void) +{ + sl_status_t status; + status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, (sl_mac_address_t *) &wfx_rsi.sta_mac.octet[0]); + if (status != SL_STATUS_OK) + { + SILABS_LOG("sl_wifi_get_mac_address failed: %x", status); + return status; + } + + wfx_rsi.events = xEventGroupCreateStatic(&rsiDriverEventGroup); + wfx_rsi.dev_state |= WFX_RSI_ST_DEV_READY; + osSemaphoreRelease(sl_rs_ble_init_sem); + return status; +} + +/************************************************************************************* + * @fn sl_status_t scan_callback_handler + * @brief + * scan callback handler + * @param[in] msg + * @return + * sl_status_t + *****************************************************************************************/ +sl_status_t scan_callback_handler(sl_wifi_event_t event, sl_wifi_scan_result_t * scan_result, uint32_t result_length, void * arg) +{ + if (CHECK_IF_EVENT_FAILED(event)) + { + callback_status = *(sl_status_t *) scan_result; + scan_results_complete = true; +#if WIFI_ENABLE_SECURITY_WPA3_TRANSITION + wfx_rsi.sec.security = WFX_SEC_WPA3; +#else + wfx_rsi.sec.security = WFX_SEC_WPA2; +#endif /* WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ + return SL_STATUS_FAIL; + } + wfx_rsi.sec.security = WFX_SEC_UNSPECIFIED; + wfx_rsi.ap_chan = scan_result->scan_info[0].rf_channel; + memcpy(&wfx_rsi.ap_mac.octet[0], scan_result->scan_info[0].bssid[0], BSSID_MAX_STR_LEN); + switch (scan_result->scan_info[0].security_mode) + { + case SL_WIFI_OPEN: + wfx_rsi.sec.security = WFX_SEC_NONE; + break; + case SL_WIFI_WPA: + case SL_WIFI_WPA_ENTERPRISE: + wfx_rsi.sec.security = WFX_SEC_WPA; + break; + case SL_WIFI_WPA2: + case SL_WIFI_WPA2_ENTERPRISE: + wfx_rsi.sec.security = WFX_SEC_WPA2; + break; + case SL_WIFI_WEP: + wfx_rsi.sec.security = WFX_SEC_WEP; + break; + case SL_WIFI_WPA3_TRANSITION: +#if WIFI_ENABLE_SECURITY_WPA3_TRANSITION + case SL_WIFI_WPA3: + wfx_rsi.sec.security = WFX_SEC_WPA3; +#else + wfx_rsi.sec.security = WFX_SEC_WPA2; +#endif /* WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ + break; + default: + wfx_rsi.sec.security = WFX_SEC_UNSPECIFIED; + break; + } + scan_results_complete = true; + return SL_STATUS_OK; +} + +/************************************************************************************* + * @fn sl_status_t show_scan_results + * @brief + * driver shows scan results + * @param[in] msg + * @return + * sl_status_t + *****************************************************************************************/ +sl_status_t show_scan_results(sl_wifi_scan_result_t * scan_result) +{ + ARGS_CHECK_NULL_POINTER(scan_result); + int x; + wfx_wifi_scan_result_t ap; + if (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED) + { + for (x = 0; x < scan_result->scan_count; x++) + { + strcpy(&ap.ssid[0], (char *) &scan_result->scan_info[x].ssid); + uint8_t * bssid = (uint8_t *) &scan_result->scan_info[x].bssid; + if (wfx_rsi.scan_ssid) + { + SILABS_LOG("SCAN SSID: %s , ap scan: %s", wfx_rsi.scan_ssid, ap.ssid); + if (strcmp(wfx_rsi.scan_ssid, ap.ssid) == CMP_SUCCESS) + { + ap.security = scan_result->scan_info[x].security_mode; + ap.rssi = (-1) * scan_result->scan_info[x].rssi_val; + memcpy(&ap.bssid[0], &scan_result->scan_info[x].bssid[0], BSSID_MAX_STR_LEN); + (*wfx_rsi.scan_cb)(&ap); + } + } + else + { + ap.security = scan_result->scan_info[x].security_mode; + ap.rssi = (-1) * scan_result->scan_info[x].rssi_val; + memcpy(&ap.bssid[0], &scan_result->scan_info[x].bssid[0], BSSID_MAX_STR_LEN); + (*wfx_rsi.scan_cb)(&ap); + } + } + } + wfx_rsi.dev_state &= ~WFX_RSI_ST_SCANSTARTED; + (*wfx_rsi.scan_cb)((wfx_wifi_scan_result_t *) 0); + wfx_rsi.scan_cb = (void (*)(wfx_wifi_scan_result_t *)) 0; + if (wfx_rsi.scan_ssid) + { + vPortFree(wfx_rsi.scan_ssid); + wfx_rsi.scan_ssid = (char *) 0; + } + return SL_STATUS_OK; +} + +/************************************************************************************* + * @fn bg_scan_callback_handler + * @brief + * scan for wifi events in background + * @param[in] + * @return + * SL_STATUS_OK + *****************************************************************************************/ +sl_status_t bg_scan_callback_handler(sl_wifi_event_t event, sl_wifi_scan_result_t * result, uint32_t result_length, void * arg) +{ + callback_status = show_scan_results(result); + scan_results_complete = true; + return SL_STATUS_OK; +} +/*************************************************************************************** + * @fn static void wfx_rsi_save_ap_info() + * @brief + * Saving the details of the AP + * @param[in] None + * @return + * None + *******************************************************************************************/ +static void wfx_rsi_save_ap_info() // translation +{ + sl_status_t status = SL_STATUS_OK; + sl_wifi_scan_configuration_t wifi_scan_configuration = { 0 }; + wifi_scan_configuration = default_wifi_scan_configuration; + sl_wifi_ssid_t ssid_arg; + ssid_arg.length = strlen(wfx_rsi.sec.ssid); + memcpy(ssid_arg.value, (int8_t *) &wfx_rsi.sec.ssid[0], ssid_arg.length); + sl_wifi_set_scan_callback(scan_callback_handler, NULL); + status = sl_wifi_start_scan(SL_WIFI_CLIENT_2_4GHZ_INTERFACE, &ssid_arg, &wifi_scan_configuration); + if (SL_STATUS_IN_PROGRESS == status) + { + const uint32_t start = osKernelGetTickCount(); + while (!scan_results_complete && (osKernelGetTickCount() - start) <= WIFI_SCAN_TIMEOUT) + { + osThreadYield(); + } + status = scan_results_complete ? callback_status : SL_STATUS_TIMEOUT; + } + return status; +} + +/******************************************************************************************** + * @fn static void wfx_rsi_do_join(void) + * @brief + * Start an async Join command + * @return + * None + **********************************************************************************************/ +static void wfx_rsi_do_join(void) +{ + int32_t status; + sl_wifi_security_t connect_security_mode; + switch (wfx_rsi.sec.security) + { + case WFX_SEC_WEP: + connect_security_mode = SL_WIFI_WEP; + break; + case WFX_SEC_WPA: + case WFX_SEC_WPA2: + connect_security_mode = SL_WIFI_WPA_WPA2_MIXED; + break; + case WFX_SEC_WPA3: + connect_security_mode = SL_WIFI_WPA3; + break; + case WFX_SEC_NONE: + connect_security_mode = SL_WIFI_OPEN; + break; + default: + SILABS_LOG("%s: error: unknown security type."); + return; + } + + if (wfx_rsi.dev_state & (WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED)) + { + SILABS_LOG("%s: not joining - already in progress", __func__); + } + else + { + SILABS_LOG("%s: WLAN: connecting to %s==%s, sec=%d", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0], + wfx_rsi.sec.security); + + /* + * Join the network + */ + /* TODO - make the WFX_SECURITY_xxx - same as RSI_xxx + * Right now it's done by hand - we need something better + */ + wfx_rsi.dev_state |= WFX_RSI_ST_STA_CONNECTING; + + status = sl_wifi_set_join_callback(join_callback_handler, NULL); + if (SL_STATUS_OK != status) + { + SILABS_LOG(" Set Join Callback fail "); + return status; + } + + /* Try to connect Wifi with given Credentials + * untill there is a success or maximum number of tries allowed + */ + + /* Call rsi connect call with given ssid and password + * And check there is a success + */ + sl_wifi_credential_t cred = { 0 }; + cred.type = SL_WIFI_CRED_PSK; + memcpy(cred.psk.value, &wfx_rsi.sec.passkey[0], strlen(wfx_rsi.sec.passkey)); + sl_wifi_credential_id_t id = SL_NET_DEFAULT_WIFI_CLIENT_CREDENTIAL_ID; + status = sl_net_set_credential(id, SL_NET_WIFI_PSK, &wfx_rsi.sec.passkey[0], strlen(wfx_rsi.sec.passkey)); + if (SL_STATUS_OK != status) + { + return status; + } + + sl_wifi_client_configuration_t ap = { 0 }; + uint32_t timeout_ms = 0; + + ap.ssid.length = strlen(wfx_rsi.sec.ssid); + memcpy(ap.ssid.value, (int8_t *) &wfx_rsi.sec.ssid[0], ap.ssid.length); + ap.security = connect_security_mode; + ap.encryption = SL_WIFI_NO_ENCRYPTION; + ap.credential_id = id; + if ((status = sl_wifi_connect(SL_WIFI_CLIENT_INTERFACE, &ap, timeout_ms)) == SL_STATUS_IN_PROGRESS) + { + callback_status = SL_STATUS_IN_PROGRESS; + while (callback_status == SL_STATUS_IN_PROGRESS) + { + osThreadYield(); + } + status = callback_status; + } + else + { + if (is_wifi_disconnection_event || wfx_rsi.join_retries <= WFX_RSI_CONFIG_MAX_JOIN) + { + SILABS_LOG("%s: failed. retry: %d", __func__, wfx_rsi.join_retries); + SILABS_LOG("%s: starting JOIN to %s after %d tries\n", __func__, (char *) &wfx_rsi.sec.ssid[0], + wfx_rsi.join_retries); + wfx_rsi.join_retries += 1; + wfx_rsi.dev_state &= ~(WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED); + if (wfx_rsi.join_retries <= MAX_JOIN_RETRIES_COUNT) + { + xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN); + } + wfx_retry_interval_handler(is_wifi_disconnection_event, wfx_rsi.join_retries); + } + } + } +} + +/********************************************************************************* + * @fn void wfx_rsi_task(void *arg) + * @brief + * The main WLAN task - started by wfx_wifi_start () that interfaces with RSI. + * The rest of RSI stuff come in call-backs. + * The initialization has been already done. + * @param[in] arg: + * @return + * None + **********************************************************************************/ +/* ARGSUSED */ +void wfx_rsi_task(void * arg) +{ + EventBits_t flags; + TickType_t last_dhcp_poll, now; + struct netif * sta_netif; + (void) arg; + uint32_t rsi_status = wfx_rsi_init(); + if (rsi_status != RSI_SUCCESS) + { + SILABS_LOG("%s: error: wfx_rsi_init with status: %02x", __func__, rsi_status); + return; + } + wfx_lwip_start(); + last_dhcp_poll = xTaskGetTickCount(); + sta_netif = wfx_get_netif(SL_WFX_STA_INTERFACE); + wfx_started_notify(); + + SILABS_LOG("%s: starting event wait", __func__); + for (;;) + { + /* + * This is the main job of this task. + * Wait for commands from the ConnectivityManager + * Make state changes (based on call backs) + */ + flags = xEventGroupWaitBits(wfx_rsi.events, + WFX_EVT_STA_CONN | WFX_EVT_STA_DISCONN | WFX_EVT_STA_START_JOIN +#ifdef SL_WFX_CONFIG_SOFTAP + | WFX_EVT_AP_START | WFX_EVT_AP_STOP +#endif /* SL_WFX_CONFIG_SOFTAP */ +#ifdef SL_WFX_CONFIG_SCAN + | WFX_EVT_SCAN +#endif /* SL_WFX_CONFIG_SCAN */ + | 0, + pdTRUE, /* Clear the bits */ + pdFALSE, /* Wait for any bit */ + pdMS_TO_TICKS(250)); /* 250 mSec */ + + if (flags) + { + SILABS_LOG("%s: wait event encountered: %x", __func__, flags); + } + /* + * Let's handle DHCP polling here + */ + if (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED) + { + if ((now = xTaskGetTickCount()) > (last_dhcp_poll + pdMS_TO_TICKS(250))) + { +#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) + uint8_t dhcp_state = dhcpclient_poll(sta_netif); + if (dhcp_state == DHCP_ADDRESS_ASSIGNED && !hasNotifiedIPV4) + { + wfx_dhcp_got_ipv4((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); + hasNotifiedIPV4 = true; + if (!hasNotifiedWifiConnectivity) + { + wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac); + hasNotifiedWifiConnectivity = true; + } + } + else if (dhcp_state == DHCP_OFF) + { + wfx_ip_changed_notify(IP_STATUS_FAIL); + hasNotifiedIPV4 = false; + } +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + /* Checks if the assigned IPv6 address is preferred by evaluating + * the first block of IPv6 address ( block 0) + */ + if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6) + { + wfx_ipv6_notify(GET_IPV6_SUCCESS); + hasNotifiedIPV6 = true; + if (!hasNotifiedWifiConnectivity) + { + wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac); + hasNotifiedWifiConnectivity = true; + } + } + last_dhcp_poll = now; + } + } + if (flags & WFX_EVT_STA_START_JOIN) + { + // saving the AP related info + wfx_rsi_save_ap_info(); + // Joining to the network + wfx_rsi_do_join(); + } + if (flags & WFX_EVT_STA_CONN) + { + SILABS_LOG("%s: starting LwIP STA", __func__); + wfx_rsi.dev_state |= WFX_RSI_ST_STA_CONNECTED; + hasNotifiedWifiConnectivity = false; +#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) + hasNotifiedIPV4 = false; +#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 + hasNotifiedIPV6 = false; + wfx_lwip_set_sta_link_up(); + /* We need to get AP Mac - TODO */ + // Uncomment once the hook into MATTER is moved to IP connectivty instead + // of AP connectivity. wfx_connected_notify(0, &wfx_rsi.ap_mac); // This + // is independant of IP connectivity. + } + if (flags & WFX_EVT_STA_DISCONN) + { + wfx_rsi.dev_state &= + ~(WFX_RSI_ST_STA_READY | WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED | WFX_RSI_ST_STA_DHCP_DONE); + SILABS_LOG("%s: disconnect notify", __func__); + /* TODO: Implement disconnect notify */ + wfx_lwip_set_sta_link_down(); // Internally dhcpclient_poll(netif) -> + // wfx_ip_changed_notify(0) for IPV4 +#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) + wfx_ip_changed_notify(IP_STATUS_FAIL); + hasNotifiedIPV4 = false; +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + wfx_ipv6_notify(GET_IPV6_FAIL); + hasNotifiedIPV6 = false; + hasNotifiedWifiConnectivity = false; + } +#ifdef SL_WFX_CONFIG_SCAN + if (flags & WFX_EVT_SCAN) + { + if (!(wfx_rsi.dev_state & WFX_RSI_ST_SCANSTARTED)) + { + SILABS_LOG("%s: start SSID scan", __func__); + int x; + sl_wifi_scan_configuration_t wifi_scan_configuration = { 0 }; + wfx_wifi_scan_result_t ap; + // TODO: Add scan logic + sl_wifi_advanced_scan_configuration_t advanced_scan_configuration = { 0 }; + int32_t status; + advanced_scan_configuration.active_channel_time = ADV_ACTIVE_SCAN_DURATION; + advanced_scan_configuration.passive_channel_time = ADV_PASSIVE_SCAN_DURATION; + advanced_scan_configuration.trigger_level = ADV_SCAN_THRESHOLD; + advanced_scan_configuration.trigger_level_change = ADV_RSSI_TOLERANCE_THRESHOLD; + advanced_scan_configuration.enable_multi_probe = ADV_MULTIPROBE; + status = sl_wifi_set_advanced_scan_configuration(&advanced_scan_configuration); + VERIFY_STATUS_AND_RETURN(status); + /* Terminate with end of scan which is no ap sent back */ + wifi_scan_configuration.type = SL_WIFI_SCAN_TYPE_ADV_SCAN; + wifi_scan_configuration.periodic_scan_interval = ADV_SCAN_PERIODICITY; + + status = sl_wifi_set_scan_callback(bg_scan_callback_handler, NULL); + if (SL_STATUS_OK != status) + { + return status; + } + + status = sl_wifi_start_scan(SL_WIFI_CLIENT_2_4GHZ_INTERFACE, NULL, &wifi_scan_configuration); + if (SL_STATUS_IN_PROGRESS == status) + { + printf("Scanning...\r\n"); + const uint32_t start = osKernelGetTickCount(); + while (!scan_results_complete && (osKernelGetTickCount() - start) <= WIFI_SCAN_TIMEOUT) + { + osThreadYield(); + } + status = scan_results_complete ? callback_status : SL_STATUS_TIMEOUT; + } + } + } +#endif /* SL_WFX_CONFIG_SCAN */ +#ifdef SL_WFX_CONFIG_SOFTAP + /* TODO */ + if (flags & WFX_EVT_AP_START) + { + } + if (flags & WFX_EVT_AP_STOP) + { + } +#endif /* SL_WFX_CONFIG_SOFTAP */ + } +} + +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 +/******************************************************************************************** + * @fn void wfx_dhcp_got_ipv4(uint32_t ip) + * @brief + * Acquire the new ip address + * @param[in] ip: internet protocol + * @return + * None + **********************************************************************************************/ +void wfx_dhcp_got_ipv4(uint32_t ip) +{ + /* + * Acquire the new IP address + */ + wfx_rsi.ip4_addr[0] = (ip) &HEX_VALUE_FF; + wfx_rsi.ip4_addr[1] = (ip >> 8) & HEX_VALUE_FF; + wfx_rsi.ip4_addr[2] = (ip >> 16) & HEX_VALUE_FF; + wfx_rsi.ip4_addr[3] = (ip >> 24) & HEX_VALUE_FF; + SILABS_LOG("%s: DHCP OK: IP=%d.%d.%d.%d", __func__, wfx_rsi.ip4_addr[0], wfx_rsi.ip4_addr[1], wfx_rsi.ip4_addr[2], + wfx_rsi.ip4_addr[3]); + /* Notify the Connectivity Manager - via the app */ + wfx_rsi.dev_state |= WFX_RSI_ST_STA_DHCP_DONE; + wfx_ip_changed_notify(IP_STATUS_SUCCESS); + wfx_rsi.dev_state |= WFX_RSI_ST_STA_READY; +} +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + +/* + * WARNING - Taken from RSI and broken up + * This is my own RSI stuff for not copying code and allocating an extra + * level of indirection - when using LWIP buffers + * see also: int32_t rsi_wlan_send_data_xx(uint8_t *buffer, uint32_t length) + */ +/******************************************************************************************** + * @fn void *wfx_rsi_alloc_pkt() + * @brief + * Allocate packet to send data + * @param[in] None + * @return + * None + **********************************************************************************************/ +void * wfx_rsi_alloc_pkt(uint16_t data_length) +{ + sl_wifi_buffer_t * buffer; + sl_si91x_packet_t * packet; + sl_status_t status = SL_STATUS_OK; + + /* Confirm if packet is allocated */ + + status = sl_si91x_allocate_command_buffer(&buffer, (void **) &packet, sizeof(sl_si91x_packet_t) + data_length, + SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME); + if (packet == NULL) + { + return SL_STATUS_ALLOCATION_FAILED; + } + return (void *) packet; +} + +/******************************************************************************************** + * @fn void wfx_rsi_pkt_add_data(void *p, uint8_t *buf, uint16_t len, uint16_t off) + * @brief + * add the data into packet + * @param[in] p: + * @param[in] buf: + * @param[in] len: + * @param[in] off: + * @return + * None + **********************************************************************************************/ +void wfx_rsi_pkt_add_data(void * p, uint8_t * buf, uint16_t len, uint16_t off) +{ + sl_si91x_packet_t * pkt; + pkt = (sl_si91x_packet_t *) p; + memcpy(((char *) pkt->data) + off, buf, len); +} diff --git a/examples/platform/silabs/SiWx917/SiWx917/sl_wlan_config.h b/examples/platform/silabs/SiWx917/SiWx917/sl_wlan_config.h new file mode 100644 index 00000000000000..8bf4e1a4ce51ad --- /dev/null +++ b/examples/platform/silabs/SiWx917/SiWx917/sl_wlan_config.h @@ -0,0 +1,113 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RSI_CONFIG_H +#define RSI_CONFIG_H + +#include "ble_config.h" +#include "rsi_wisemcu_hardware_setup.h" +#include "rsi_wlan_defines.h" +#include "sl_wifi_device.h" + +//! Enable feature +#define RSI_ENABLE 1 +//! Disable feature +#define RSI_DISABLE 0 + +#define SI91X_LISTEN_INTERVAL 0 + +static const sl_wifi_device_configuration_t config = { + .boot_option = LOAD_NWP_FW, + .mac_address = NULL, + .band = SL_SI91X_WIFI_BAND_2_4GHZ, + .region_code = US, + .boot_config = { .oper_mode = SL_SI91X_CLIENT_MODE, + .coex_mode = SL_SI91X_WLAN_BLE_MODE, + .feature_bit_map = +#ifdef RSI_M4_INTERFACE + (SL_SI91X_FEAT_SECURITY_OPEN | SL_SI91X_FEAT_WPS_DISABLE), +#else + (SL_SI91X_FEAT_SECURITY_OPEN | SL_SI91X_FEAT_AGGREGATION), +#endif + .tcp_ip_feature_bit_map = (SL_SI91X_TCP_IP_FEAT_DHCPV4_CLIENT | SL_SI91X_TCP_IP_FEAT_DNS_CLIENT | + SL_SI91X_TCP_IP_FEAT_SSL | SL_SI91X_TCP_IP_FEAT_BYPASS +#ifdef ipv6_FEATURE_REQUIRED + | SL_SI91X_TCP_IP_FEAT_DHCPV6_CLIENT | SL_SI91X_TCP_IP_FEAT_IPV6 +#endif + | SL_SI91X_TCP_IP_FEAT_ICMP | SL_SI91X_TCP_IP_FEAT_EXTENSION_VALID), + .custom_feature_bit_map = (SL_SI91X_FEAT_CUSTOM_FEAT_EXTENTION_VALID | RSI_CUSTOM_FEATURE_BIT_MAP), + .ext_custom_feature_bit_map = ( +#ifdef CHIP_917 + (RSI_EXT_CUSTOM_FEATURE_BIT_MAP) +#else // defaults +#ifdef RSI_M4_INTERFACE + (SL_SI91X_EXT_FEAT_256K_MODE | RSI_EXT_CUSTOM_FEATURE_BIT_MAP) +#else + (SL_SI91X_EXT_FEAT_384K_MODE | RSI_EXT_CUSTOM_FEATURE_BIT_MAP) +#endif +#endif + | (SL_SI91X_EXT_FEAT_BT_CUSTOM_FEAT_ENABLE) +#if (defined A2DP_POWER_SAVE_ENABLE) + | SL_SI91X_EXT_FEAT_XTAL_CLK_ENABLE(2) +#endif + ), + .bt_feature_bit_map = (RSI_BT_FEATURE_BITMAP +#if (RSI_BT_GATT_ON_CLASSIC) + | SL_SI91X_BT_ATT_OVER_CLASSIC_ACL /* to support att over classic acl link */ +#endif + ), +#ifdef RSI_PROCESS_MAX_RX_DATA + .ext_tcp_ip_feature_bit_map = + (RSI_EXT_TCPIP_FEATURE_BITMAP | SL_SI91X_CONFIG_FEAT_EXTENTION_VALID | SL_SI91X_EXT_TCP_MAX_RECV_LENGTH), +#else + .ext_tcp_ip_feature_bit_map = (RSI_EXT_TCPIP_FEATURE_BITMAP | SL_SI91X_CONFIG_FEAT_EXTENTION_VALID), +#endif + //! ENABLE_BLE_PROTOCOL in bt_feature_bit_map + .ble_feature_bit_map = + ((SL_SI91X_BLE_MAX_NBR_PERIPHERALS(RSI_BLE_MAX_NBR_PERIPHERALS) | + SL_SI91X_BLE_MAX_NBR_CENTRALS(RSI_BLE_MAX_NBR_CENTRALS) | + SL_SI91X_BLE_MAX_NBR_ATT_SERV(RSI_BLE_MAX_NBR_ATT_SERV) | + SL_SI91X_BLE_MAX_NBR_ATT_REC(RSI_BLE_MAX_NBR_ATT_REC)) | + SL_SI91X_FEAT_BLE_CUSTOM_FEAT_EXTENTION_VALID | SL_SI91X_BLE_PWR_INX(RSI_BLE_PWR_INX) | + SL_SI91X_BLE_PWR_SAVE_OPTIONS(RSI_BLE_PWR_SAVE_OPTIONS) | SL_SI91X_916_BLE_COMPATIBLE_FEAT_ENABLE +#if RSI_BLE_GATT_ASYNC_ENABLE + | SL_SI91X_BLE_GATT_ASYNC_ENABLE +#endif + ), + + .ble_ext_feature_bit_map = ((SL_SI91X_BLE_NUM_CONN_EVENTS(RSI_BLE_NUM_CONN_EVENTS) | + SL_SI91X_BLE_NUM_REC_BYTES(RSI_BLE_NUM_REC_BYTES)) +#if RSI_BLE_INDICATE_CONFIRMATION_FROM_HOST + | SL_SI91X_BLE_INDICATE_CONFIRMATION_FROM_HOST // indication response from app +#endif +#if RSI_BLE_MTU_EXCHANGE_FROM_HOST + | SL_SI91X_BLE_MTU_EXCHANGE_FROM_HOST // MTU Exchange request initiation from app +#endif +#if RSI_BLE_SET_SCAN_RESP_DATA_FROM_HOST + | (SL_SI91X_BLE_SET_SCAN_RESP_DATA_FROM_HOST) // Set SCAN Resp Data from app +#endif +#if RSI_BLE_DISABLE_CODED_PHY_FROM_HOST + | (SL_SI91X_BLE_DISABLE_CODED_PHY_FROM_HOST) // Disable Coded PHY from app +#endif +#if BLE_SIMPLE_GATT + | SL_SI91X_BLE_GATT_INIT +#endif + ), + .config_feature_bit_map = (SL_SI91X_FEAT_SLEEP_GPIO_SEL_BITMAP | RSI_CONFIG_FEATURE_BITMAP) } +}; + +#endif diff --git a/examples/platform/silabs/ldscripts/SiWx917-common.ld b/examples/platform/silabs/ldscripts/SiWx917-common.ld new file mode 100644 index 00000000000000..e91bba8384b0ca --- /dev/null +++ b/examples/platform/silabs/ldscripts/SiWx917-common.ld @@ -0,0 +1,240 @@ +/***************************************************************************//** + * GCC Linker script for Silicon Labs devices + ******************************************************************************* + * # License + * Copyright 2020 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Zlib + * + * The licensor of this software is Silicon Laboratories Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + ******************************************************************************/ + MEMORY + { + rom (rx) : ORIGIN = 0x81c2000, LENGTH = 0x200000 + ram (rwx) : ORIGIN = 0x400, LENGTH = 0x4e200 + } + +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + KEEP(*(.reset_handler)) + *(EXCLUDE_FILE(*sl_si91x_bus.o *sl_si91x_driver.o *sli_si91x_multithreaded.o *rsi_hal_mcu_m4_ram.o ) .text*) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + *(.eh_frame*) + } > rom + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > rom + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (__etext) + LONG (__data_start__) + LONG ((__data_end__ - __data_start__) / 4) + + /* Add each additional data section here */ +/* + LONG (__etext2) + LONG (__data2_start__) + LONG ((__data2_end__ - __data2_start__) / 4) +*/ + __copy_table_end__ = .; + } > rom + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + /* Add each additional bss section here */ +/* + LONG (__bss2_start__) + LONG ((__bss2_end__ - __bss2_start__) / 4) +*/ + __zero_table_end__ = .; + } > rom + + __exidx_end = .; + __etext = .; + + /* _sidata is used in coide startup code */ + _sidata = __etext; + + /* Start placing output sections which are loaded into RAM */ + . = ORIGIN(ram); + + .noinit . (NOLOAD): + { + *(.noinit*); + } > ram + + .data . : AT (__etext) + { + . = ALIGN(4); + __data_start__ = .; + _sdata = __data_start__; + KEEP(*(.ramVector)) + KEEP(*(.init)) + KEEP(*(.fini)) + *(.rodata*) + *(vtable) + *(.data*) + *sl_si91x_bus.o(.text*) + *sl_si91x_driver.o(.text*) + *sli_si91x_multithreaded.o(.text*) + *rsi_hal_mcu_m4_ram.o(.text*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + /* _edata is used in coide startup code */ + _edata = __data_end__; + + } > ram + + .bss . : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = __bss_start__; + *(SORT_BY_ALIGNMENT(.bss*)) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = __bss_end__; + } > ram + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + Co_Stack_Size = 0x3000; + .co_stack ALIGN(8) (NOLOAD): + { + __co_stackLimit = .; + KEEP(*(.co_stack*)) + . = ALIGN(4); + . += Co_Stack_Size; + __co_stackTop = .; + } > ram + + StackSize = 0x1400; + .stack ALIGN(8) (NOLOAD): + { + __StackLimit = .; + KEEP(*(.stack*)) + . = ALIGN(4); + . += StackSize; + __StackTop = .; + PROVIDE(__stack = __StackTop); + } > ram + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + _end = __end__; + KEEP(*(.heap*)) + . = ORIGIN(ram) + LENGTH(ram); + + __HeapLimit = .; + } > ram + + __heap_size = __HeapLimit - __HeapBase; + __ram_end__ = 0x400 + 0x4e200; + __main_flash_end__ = 0x81c2000 + 0x200000; + + /* This is where we handle flash storage blocks. We use dummy sections for finding the configured + * block sizes and then "place" them at the end of flash when the size is known. */ + .internal_storage (DSECT) : { + KEEP(*(.internal_storage*)) + } > rom + + + .nvm (DSECT) : { + KEEP(*(.simee*)) + } > rom + + linker_nvm_end = __main_flash_end__; + linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm); + linker_nvm_size = SIZEOF(.nvm); + linker_storage_end = linker_nvm_begin; + __nvm3Base = linker_nvm_begin; + + linker_storage_begin = linker_storage_end - SIZEOF(.internal_storage); + linker_storage_size = SIZEOF(.internal_storage); + ASSERT((linker_storage_begin >= (__etext + SIZEOF(.data))), "FLASH memory overflowed !") + + app_flash_end = 0x81c2000 + 0x200000; + ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= app_flash_end, "NVM3 is excessing the flash size !") +} + diff --git a/src/platform/silabs/rs911x/ble_config.h b/src/platform/silabs/rs911x/ble_config.h new file mode 120000 index 00000000000000..48a308dc911649 --- /dev/null +++ b/src/platform/silabs/rs911x/ble_config.h @@ -0,0 +1 @@ +rsi_ble_config.h \ No newline at end of file