RT-Thread Wi-Fi Driver Adapts to BL808

Created at 2024-01-18 13:18:26

Author: RT-Thread Community Developer Yan Shisan

The BL808 WiFi is a wireless MCU with a single chip SOC that integrates WiFi functionality on the chip. When porting RT-Thread, the RT-Thread wlan framework is used to manage Wi-Fi driver devices.

The RT-Thread wlan framework is like a conductor that connects to specific Wi-Fi drivers, controls Wi-Fi connection, disconnection, scanning, and other operations, and provides a unified Wi-Fi control interface to the application.

The wlan framework has three main parts:

  1. dev driver interface layer: This layer provides a unified interface call for the wlan framework.
  2. manage layer: This layer provides users with Wi-Fi scanning, connection, disconnection, reconnection, and other functions.
  3. protocol: This layer is responsible for processing the data flow generated by Wi-Fi, such as lwip.

After using the wlan driver framework, the Wi-Fi driver only needs to focus on the actions of connecting, disconnecting, scanning, etc., and inform the wlan framework of the relevant actions through events. The wlan framework manages lwip according to the received events.

1. To enable the wlan driver:

Execute the following command under Linux to enable the wlan driver.

1$ scons --menuconfig
2RT-Thread Components  --->
3    Device Drivers  --->
4        [*] Using Wi-Fi framework  --->

By default, the wlan driver will select lwip after being enabled.

For WiFi SOC chips, the original SDK already has the thread to manage WiFi data transmission and reception. You can disable the Rx thread and Tx thread in lwip to save system resources.

1Network  --->
2    -*- LwIP: light weight TCP/IP stack  --->
3        [*]   Not use Rx thread
4        [*]   Not use Tx thread

2. Adapt the wlan driver framework


Use rt_wlan_dev_register() to register STATION and AP devices, and register the wlan device interface function with the corresponding device.

 1static const struct rt_wlan_dev_ops ops =
 3    .wlan_init = drv_wlan_init,
 4    .wlan_mode = drv_wlan_mode,
 5    .wlan_scan = drv_wlan_scan,
 6    .wlan_join = drv_wlan_join,
 7    .wlan_softap = drv_wlan_softap,
 8    .wlan_disconnect = drv_wlan_disconnect,
 9    .wlan_ap_stop = drv_wlan_ap_stop,
10    .wlan_ap_deauth = drv_wlan_ap_deauth,
11    .wlan_scan_stop = drv_wlan_scan_stop,
12    .wlan_get_rssi = drv_wlan_get_rssi,
13    .wlan_set_powersave = drv_wlan_set_powersave,
14    .wlan_get_powersave = drv_wlan_get_powersave,
15    .wlan_cfg_promisc = drv_wlan_cfg_promisc,
16    .wlan_cfg_filter = drv_wlan_cfg_filter,
17    .wlan_cfg_mgnt_filter = drv_wlan_cfg_mgnt_filter,
18    .wlan_set_channel = drv_wlan_set_channel,
19    .wlan_get_channel = drv_wlan_get_channel,
20    .wlan_set_country = drv_wlan_set_country,
21    .wlan_get_country = drv_wlan_get_country,
22    .wlan_set_mac = drv_wlan_set_mac,
23    .wlan_get_mac = drv_wlan_get_mac,
24    .wlan_recv = drv_wlan_recv,
25    .wlan_send = drv_wlan_send,
27int rt_hw_wifi_init(void)
29    rt_err_t ret = RT_EOK;
30    static struct rt_wlan_device wlan0;
31    static struct rt_wlan_device wlan1;
32    memset(&wifi_sta, 0, sizeof(wifi_sta));
33    ret = rt_wlan_dev_register(&wlan0, RT_WLAN_DEVICE_STA_NAME, &ops, 0, &wifi_sta);
34    wifi_sta.wlan = &wlan0;
35    memset(&wifi_ap, 0, sizeof(wifi_ap));
36    ret |= rt_wlan_dev_register(&wlan1, RT_WLAN_DEVICE_AP_NAME, &ops, 0, &wifi_ap);
37    wifi_ap.wlan = &wlan1;
38    return ret;

Starting the device

In main.c, add rt_wlan_set_mode to set the STATION and AP modes separately.

1int main(void)
3    rt_kprintf("Hello, RISC-V!\n");
4    /* set wifi work mode */
5    rt_wlan_set_mode(RT_WLAN_DEVICE_STA_NAME, RT_WLAN_STATION);
6    rt_wlan_set_mode(RT_WLAN_DEVICE_AP_NAME, RT_WLAN_AP);
7    return 0;

Interfaces Implementation

In STATION mode, at least two functions need to be implemented: drv_wlan_join() to connect to the router and drv_wlan_disconnect() to disconnect from the router.

In AP mode, at least two functions need to be implemented: drv_wlan_softap() to start the AP and drv_wlan_ap_stop() to stop the AP.

These four functions can be implemented according to the corresponding interfaces on the chip SDK.

Event Management

When implementing the above interfaces, you need to notify the wlan driver framework through events when the corresponding Wi-Fi events are triggered.

In STATION mode, when the router is successfully connected, use the rt_wlan_dev_indicate_event_handle(wifi_sta.wlan, RT_WLAN_DEV_EVT_CONNECT, RT_NULL) function to notify the wlan framework that the station has successfully connected to the router. When the router is disconnected, use the rt_wlan_dev_indicate_event_handle(wifi_sta.wlan, RT_WLAN_DEV_EVT_DISCONNECT, RT_NULL) function to notify the wlan framework that the station has disconnected from the router.

The wlan framework will obtain the IP address through the DHCP service after receiving the RT_WLAN_DEV_EVT_CONNECT event.

In AP mode, after the soft AP is successfully started, use the rt_wlan_dev_indicate_event_handle(wifi_ap.wlan, RT_WLAN_DEV_EVT_AP_START, RT_NULL) function to notify the wlan framework that the AP mode has been successfully started. After the soft AP is successfully stopped, use the rt_wlan_dev_indicate_event_handle(wifi_ap.wlan, RT_WLAN_DEV_EVT_AP_STOP, RT_NULL) function to notify the wlan framework that the soft AP has been stopped.

The wlan framework will start the DHCP_SERVER service after receiving the RT_WLAN_DEV_EVT_AP_START event.

After adopting the RT-Thread wlan driver framework, the chip SDK only needs to manage the Wi-Fi-related connection services, without managing the lwip protocol stack.

Data Transmission and Reception

As mentioned earlier, the wlan framework is responsible for starting the corresponding service in lwip after receiving the corresponding event.

  • The wlan framework uses the drv_wlan_send() function to send the required network data packets. For WiFi, the corresponding data packets need to be sent to WiFi by judging whether the device is a station or an AP.
1static int drv_wlan_send(struct rt_wlan_device *wlan, void *buff, int len)
3  if (wlan->user_data == &wifi_sta)
4      bl_wifi_tx(0, (struct pbuf *)buff);
5  else
6      bl_wifi_tx(1, (struct pbuf *)buff);
7  return RT_EOK;
  • When the WiFi device receives data, it uses the rt_wlan_dev_report_data() function to pass the data to the wlan framework, which further processes it through lwip.
1int bl_wifi_rx(uint8_t idx, struct pbuf *p)
3  rt_err_t ret = RT_EOK;
4  if (idx == 0)
5      ret = rt_wlan_dev_report_data(wifi_sta.wlan, p, p->tot_len);
6  else
7      ret = rt_wlan_dev_report_data(wifi_ap.wlan, p, p->tot_len);
8  return ret;

Other Required Interfaces

  • MAC-related

The main implementation is to read and write MAC addresses.

1static rt_err_t drv_wlan_set_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
3  wifi_mgmr_sta_mac_set(mac);
4  return RT_EOK;
1static rt_err_t drv_wlan_get_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
3  wifi_mgmr_sta_mac_get(mac);
4  return RT_EOK;
  • Wi-Fi scan
 1static rt_err_t drv_wlan_scan(struct rt_wlan_device *wlan, struct rt_scan_info *scan_info)
 3  int  channel_input_num = 0;
 4  uint8_t channel_input[MAX_FIXED_CHANNELS_LIMIT] = {0};
 5  const char *ssid = NULL;
 6  uint8_t bssid[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 7  uint8_t scan_mode = SCAN_ACTIVE;
 8  uint32_t duration_scan_us = 0;
 9  if (scan_info != NULL && scan_info->ssid.len > 0)
10  {
11      ssid = scan_info->ssid.val;
12  }
13  if (wifi_mgmr_scan_adv(wlan, wifi_scan_complete_callback, channel_input, channel_input_num, bssid, ssid, scan_mode, duration_scan_us) != 0)
14      return -RT_ERROR;
15  return RT_EOK;

BL808 WiFi is a wireless MCU with a single chip SOC that integrates WiFi functionality on the chip. When porting RT-Thread, the RT-Thread wlan framework needs to be used to manage Wi-Fi driver devices.


0 Answer
There is no answer, come and add the answer

Write Your Answer

Log in to publish your answer.,Click here to log in.