谷动谷力

 找回密码
 立即注册
查看: 1020|回复: 0
打印 上一主题 下一主题
收起左侧

BL808 RT-Thread Wi-Fi 驱动适配

[复制链接]
跳转到指定楼层
楼主
发表于 2023-12-1 21:04:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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,以节省系统资源。
    1. Network  --->

    2.     -*- LwIP: light weight TCP/IP stack  --->
    3.         [*]   Not use Rx thread
    4.         [*]   Not use Tx thread
    复制代码


    2、wlan 驱动框架适配
    初始化
    通过 rt_wlan_dev_register() 注册 STATION 和 AP 设备,并将 wlan 设备接口函数注册进对应设备。
    1. static const struct rt_wlan_dev_ops ops =
    2. {
    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,
    26. };
    27. int rt_hw_wifi_init(void)
    28. {
    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;
    39. }
    40. INIT_DEVICE_EXPORT(rt_hw_wifi_init);
    复制代码

    启动设备
    在 main.c 中 加入 rt_wlan_set_mode 分别设置 STATION 和 AP 模式。
    1. int main(void)
    2. {
    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;
    8. }
    复制代码

    接口实现
    在 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 中的对应服务。
    • wlan 框架通过 drv_wlan_send() 函数将需要发送的网络数据包发输出去。针对WiFi 而言,需要通过判断设备是 station 还是 ap 后,将对应的数据包发送给 WiFi 。

    1. static int drv_wlan_send(struct rt_wlan_device *wlan, void *buff, int len)
    2. {
    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;
    8. }
    复制代码

    • WiFi 设备接收到数据后,通过 rt_wlan_dev_report_data() 函数,将数据传递给 wlan 框架,wlan 框架会进一步通过 lwip 做进一步处理。

    1. int bl_wifi_rx(uint8_t idx, struct pbuf *p)
    2. {
    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;
    9. }
    复制代码

    其他必须实现的接口
    • mac相关

    主要实现 mac 地址读取和写入。
    1. static rt_err_t drv_wlan_set_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
    2. {
    3.   wifi_mgmr_sta_mac_set(mac);
    4.   return RT_EOK;
    5. static rt_err_t drv_wlan_get_mac(struct rt_wlan_device *wlan, rt_uint8_t mac[])
    6. {
    7.   wifi_mgmr_sta_mac_get(mac);
    8.   return RT_EOK;
    9. }
    复制代码

    • Wi-Fi scan

    1. static rt_err_t drv_wlan_scan(struct rt_wlan_device *wlan, struct rt_scan_info *scan_info)
    2. {
    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;
    16. }
    复制代码

    BL808 WiFi 属于 SOC 单芯片型无线 MCU,片上集成 WiFi 功能,移植 RT-Thread 过程中,需要使用 RT-Thread wlan 框架。
    版权声明:本文为RT-Thread论坛用户「燕十三」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。


  • +10
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

    GMT+8, 2024-11-24 12:25 , Processed in 0.269784 second(s), 41 queries .

    Powered by Discuz! X3.2 Licensed

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表