|
BL808 RT-Thread Wi-Fi 驱动适配
BL808 WiFi 属于 SOC 单芯片型无线 MCU,片上集成 WiFi 功能,移植 RT-Thread 过程中,需要使用 RT-Thread wlan 框架。RT-Thread wlan 框架是用于管理 Wi-Fi 驱动设备的框架,对下连接具体的 Wi-Fi 驱动,控制 Wi-Fi 的连接断开、扫描等操作,对上为应用提供统一的 Wi-Fi 控制接口。wlan 框架主要有 3 部分组成:- dev 驱动接口层:为 wlan 框架提供统一的接口调用。
- manage 管理层:为用户提供 Wi-Fi 扫描,链接,断线重连等功能。
- protocol 协议:负责处理 Wi-Fi 产生的数据流,如 lwip。
使用了 wlan 驱动框架之后,Wi-Fi 驱动只需要关注 Wi-Fi 的连接、断开、扫描等动作,并通过 event 将相关动作告知 wlan 框架,由 wlan 框架根据收到的 event 管理 lwip。1、使能 wlan 驱动 在 Linux 下 执行如下命令,并开启 wlan 驱动。 1$ scons --menuconfig
2RT-Thread Components --->
3 Device Drivers --->
4 Using Wi-Fi framework --->
开启 wlan 驱动后,默认会选中 lwip。 如 WiFi SOC 类芯片,原厂 SDK 中已经有线程管理 WiFi 数据收发,可关闭 lwip 中的 Rx thread 和 Tx thread,以节省系统资源。 - Network --->
- -*- LwIP: light weight TCP/IP stack --->
- [*] Not use Rx thread
- [*] Not use Tx thread
复制代码
2、wlan 驱动框架适配 初始化 通过 rt_wlan_dev_register() 注册 STATION 和 AP 设备,并将 wlan 设备接口函数注册进对应设备。 - static const struct rt_wlan_dev_ops ops =
- {
- .wlan_init = drv_wlan_init,
- .wlan_mode = drv_wlan_mode,
- .wlan_scan = drv_wlan_scan,
- .wlan_join = drv_wlan_join,
- .wlan_softap = drv_wlan_softap,
- .wlan_disconnect = drv_wlan_disconnect,
- .wlan_ap_stop = drv_wlan_ap_stop,
- .wlan_ap_deauth = drv_wlan_ap_deauth,
- .wlan_scan_stop = drv_wlan_scan_stop,
- .wlan_get_rssi = drv_wlan_get_rssi,
- .wlan_set_powersave = drv_wlan_set_powersave,
- .wlan_get_powersave = drv_wlan_get_powersave,
- .wlan_cfg_promisc = drv_wlan_cfg_promisc,
- .wlan_cfg_filter = drv_wlan_cfg_filter,
- .wlan_cfg_mgnt_filter = drv_wlan_cfg_mgnt_filter,
- .wlan_set_channel = drv_wlan_set_channel,
- .wlan_get_channel = drv_wlan_get_channel,
- .wlan_set_country = drv_wlan_set_country,
- .wlan_get_country = drv_wlan_get_country,
- .wlan_set_mac = drv_wlan_set_mac,
- .wlan_get_mac = drv_wlan_get_mac,
- .wlan_recv = drv_wlan_recv,
- .wlan_send = drv_wlan_send,
- };
- int rt_hw_wifi_init(void)
- {
- rt_err_t ret = RT_EOK;
- static struct rt_wlan_device wlan0;
- static struct rt_wlan_device wlan1;
- memset(&wifi_sta, 0, sizeof(wifi_sta));
- ret = rt_wlan_dev_register(&wlan0, RT_WLAN_DEVICE_STA_NAME, &ops, 0, &wifi_sta);
- wifi_sta.wlan = &wlan0;
- memset(&wifi_ap, 0, sizeof(wifi_ap));
- ret |= rt_wlan_dev_register(&wlan1, RT_WLAN_DEVICE_AP_NAME, &ops, 0, &wifi_ap);
- wifi_ap.wlan = &wlan1;
- return ret;
- }
- INIT_DEVICE_EXPORT(rt_hw_wifi_init);
复制代码
启动设备 在 main.c 中 加入 rt_wlan_set_mode 分别设置 STATION 和 AP 模式。 - int main(void)
- {
- rt_kprintf("Hello, RISC-V!\n");
- /* set wifi work mode */
- rt_wlan_set_mode(RT_WLAN_DEVICE_STA_NAME, RT_WLAN_STATION);
- rt_wlan_set_mode(RT_WLAN_DEVICE_AP_NAME, RT_WLAN_AP);
- return 0;
- }
复制代码
接口实现 在 STATION 模式下,至少需要实现连接路由器 drv_wlan_join() 和断开路由器 drv_wlan_disconnect() 这 2 个函数。 在 AP 模式下,至少要实现 AP 开启 drv_wlan_softap 和 AP 关闭 drv_wlan_ap_stop() 这 2个函数。 这 4 个函数可以按照芯片 SDK 上的接口对应实现即可。 event 管理 在实现以上接口用,需要在 Wi-Fi 触发对应事件后,通过 event 通知 wlan 驱动框架。 在 STATION 模式下,当连接路由器成功后,通过 rt_wlan_dev_indicate_event_handle(wifi_sta.wlan, RT_WLAN_DEV_EVT_CONNECT, RT_NULL) 函数通知 wlan 框架 station 已经连接路由成功。当断开路由器后,通过 rt_wlan_dev_indicate_event_handle(wifi_sta.wlan, RT_WLAN_DEV_EVT_DISCONNECT, RT_NULL) 函数通过 wlan 框架 station 已经断开路由器。 wlan 框架在收到 RT_WLAN_DEV_EVT_CONNECT 时间后会通过 dhcp 服务获取 IP。 在 AP 模式下,开启软 AP 成功后,通过 rt_wlan_dev_indicate_event_handle(wifi_ap.wlan, RT_WLAN_DEV_EVT_AP_START, RT_NULL) 函数通知 wlan 框架 AP 模式开启成功。关闭软 AP 成功后,通过 rt_wlan_dev_indicate_event_handle(wifi_ap.wlan, RT_WLAN_DEV_EVT_AP_STOP, RT_NULL) 函数通知 wlan 框架软 AP 关闭。 wlan 框架在收到 RT_WLAN_DEV_EVT_AP_START 时间后会开启 DHCP_SERVER 服务。 采用了 RT-Thread wlan 驱动框架后,芯片 SDK 只需要负责管理 WiFi 相关的连接服务,而不需要管理 lwip 协议栈, 数据收发 上面说到 wlan 框架在收到对应的 evnet 后,负责启动 lwip 中的对应服务。 - static int drv_wlan_send(struct rt_wlan_device *wlan, void *buff, int len)
- {
- if (wlan->user_data == &wifi_sta)
- bl_wifi_tx(0, (struct pbuf *)buff);
- else
- bl_wifi_tx(1, (struct pbuf *)buff);
- return RT_EOK;
- }
复制代码
- int bl_wifi_rx(uint8_t idx, struct pbuf *p)
- {
- rt_err_t ret = RT_EOK;
- if (idx == 0)
- ret = rt_wlan_dev_report_data(wifi_sta.wlan, p, p->tot_len);
- else
- ret = rt_wlan_dev_report_data(wifi_ap.wlan, p, p->tot_len);
- return ret;
- }
复制代码
其他必须实现的接口 主要实现 mac 地址读取和写入。 - static rt_err_t drv_wlan_set_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
- {
- wifi_mgmr_sta_mac_set(mac);
- return RT_EOK;
- static rt_err_t drv_wlan_get_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
- {
- wifi_mgmr_sta_mac_get(mac);
- return RT_EOK;
- }
复制代码
- static rt_err_t drv_wlan_scan(struct rt_wlan_device *wlan, struct rt_scan_info *scan_info)
- {
- int channel_input_num = 0;
- uint8_t channel_input[MAX_FIXED_CHANNELS_LIMIT] = {0};
- const char *ssid = NULL;
- uint8_t bssid[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- uint8_t scan_mode = SCAN_ACTIVE;
- uint32_t duration_scan_us = 0;
- if (scan_info != NULL && scan_info->ssid.len > 0)
- {
- ssid = scan_info->ssid.val;
- }
- if (wifi_mgmr_scan_adv(wlan, wifi_scan_complete_callback, channel_input, channel_input_num, bssid, ssid, scan_mode, duration_scan_us) != 0)
- return -RT_ERROR;
- return RT_EOK;
- }
复制代码
BL808 WiFi 属于 SOC 单芯片型无线 MCU,片上集成 WiFi 功能,移植 RT-Thread 过程中,需要使用 RT-Thread wlan 框架。版权声明:本文为RT-Thread论坛用户「燕十三」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
|
+10
|