Pico-W-基于-C-C-SDK-适配-RT-Thread-Wi-Fi-经验总结


title: Pico W 基于 C/C++ SDK 适配 RT-Thread Wi-Fi 经验总结
date: 2023-11-22 22:19:33
tags:

Pico W 基于 C/C++ SDK 适配 RT-Thread Wi-Fi 经验总结

前言:

Pico W 作为 Raspberry Pi Pico 的衍生版本,主要增加了无线通信的功能,通过搭载 CYW43439 无线芯片,支持 2.4 GHz Wi-Fi 4 及蓝牙5.0 ,其余和 Raspberry Pi Pico 基本相同,外部引脚也相互兼容。

也可以参考我之前文章中介绍的使用 Clion 搭建开发调试下载环境,同样适用。这里需要注意的一点是,当你首次烧录使板载 LED 闪烁的程序时,开发板可能没有相应的现象,这可能不是你下载失败了,也不是你的开发板是坏的,而是 Pico W 的板载 LED 由无线模块控制,想要使其闪烁需要参照官方 Pico-Example 中 Pico W 的具体示例:pico w/wifi/blink

准备工作

开发环境搭建完成后,接下来就可以根据树莓派官方的 SDK 和 Example 调一调程序,逐渐梳理清楚逻辑和各模块之间的依赖关系。例如先运行一个最简单的 Wi-Fi scan 的示例程序,其主要逻辑是先 cyw43_arch_init() 初始化模块,再通过 cyw43_arch_enable_sta_mode() 使能为 STA 模式,最后使用cyw43_wifi_scan() 开始扫描并注册扫描完成回调函数打印扫描结果,整体的逻辑和 API 还是很简洁明了的。

主要依赖于英飞凌提供的 cyw43-driver 驱动库,接下来我们开始通过分析 Cmake 文件确定各模块之间的调用关系和对一些宏定义的依赖关系。以下是一部分我通过 Cmake 文件大致整理的关系图:

在这里插入图片描述

通过这样的关系图,我们能更直观快速的将官方的 SDK 和 Example 等 Cmake 工程移植为 RT-Thread 所使用的 Scons 工程。

开始开发

主要有以下三种类型:poll , threadsafe_background, freertos 。poll 是需要用户定期调用的,并且不保证线程安全性;threadsafe_background 和 freertos 能够保证线程安全性,threadsafe_background 不使用 RTOS,通过低优先级的 ISR 实现调度同步,freertos 是通过专门的线程处理调动同步。

一开始我选择的是基于 threadsafe_background 进行开发,通过参照以上 Cmake 关系图很快就成功在 RT-Thread 的 Bsp 中复现了 Wi-Fi scan 示例程序。但是开发后续需要使用 lwip 的功能时,与 RT-Thread 就产生了很多冲突。

想要更好的适配 RT-Thread 还是得按照 RTOS 的来,于是开始复现官方提供的基于 FreeRTOS 的,首先想到的是使用 RT-Thread 的 FreeRTOS 兼容层软件包,在 menuconfig 中使能即可:

在这里插入图片描述

引入兼容层后大部分报错消失了,但报错没有 portCHECK_IF_IN_ISR 的相关实现,在 FreeRTOS 的源码中查找发现其为 RP2040 特有的实现。其是用于判断上下文环境是否处于中断中,改为 RT-Thread 中的检测中断 nest 是否大于 0 即可。

成功编译下载程序后,却因为定时器进入了 hardfault ,检查发现 FreeRTOS 兼容层中的 portMAX_DEALY 对接错了,不是 RT_TICK_MAX ,应该为 RT_TICK_MAX / 2 - 1(韦东山老师在rtt开发者大会上专门讲解过 RTT 优雅的定时器算法,感兴趣可以看看)这个问题目前已经修复了。

之后程序还是进入 hardfault ,一直 debug 对比代码没有发现问题,再次分析对比 FreeRTOS 和 RT-Thread 之间的差异,两者的优先级等级和数值的关系是相反的,检查发现 async_context_task 线程的优先级为 tskIDLE_PRIORITY + 4 在 FreeRTOS 中优先级比空闲线程高4,但在 RT-Thread 中因为优先级太低,得不到调度,造成死锁问题。解决办法是将其线程优先级提高。

移植 RT-Thread

以上的示例程序跑通以后,就开始将 wifi freertos 的相关的文件移植为 RT-Thread 。主要包含以下内容:

  1. 替换头文件:
    • 用 RT-Thread 的头文件替换 FreeRTOS 的头文件。
  2. 修改任务创建和管理:
    • 使用 RT-Thread 的任务创建和管理 API 替代 FreeRTOS 的任务 API。
    • 注意 RT-Thread 的任务入口函数参数和返回值的差异。
  3. 修改互斥锁:
    • 替换 xSemaphoreCreateRecursiveMutex 为 RT-Thread 提供的互斥锁创建 API。
    • 替换 xSemaphoreTakeRecursivexSemaphoreGiveRecursive 为 RT-Thread 互斥锁的 API。
  4. 替换定时器:
    • 使用 RT-Thread 的软定时器或者实时时钟服务替代 FreeRTOS 定时器。
  5. 任务通知:
    • 替换 FreeRTOS 的任务通知 API 为 RT-Thread 的事件和信号量等。
  6. 任务挂起和唤醒:
    • 替换 FreeRTOS 的 vTaskSuspendvTaskResume 为 RT-Thread 的任务挂起和唤醒 API

主要涉及 async_context_rtthreadcyw43_archcyw43_arch_rtthreadlwip_rtthread这些文件,基础的移植完成后,就可以开始将其对接到 RT-Thread 的 Wi-Fi 设备驱动框架了,主要参考 rw007cyw43012-RTT 的对接。需要使能 RT-Thread 的 lwip 和 SAL 等组件。需要注意的一点是 RT-Thread 的 lwip 组件使能后,已经包含了 lwip 的初始化,cyw43_arch_init() 中的 lwip 初始化相关注释即可,否则重复初始化会因为完成量无法获取造成阻塞。

#if CYW43_LWIP
//    ok &= lwip_rtthread_init(context);
#endif
// 重复初始化信号量无法获取造成阻塞
bool lwip_rtthread_init(async_context_t *context) {
    RT_ASSERT(!lwip_context);
    lwip_context = context;
    static bool done_lwip_init;
    if (!done_lwip_init) {
        done_lwip_init = true;
        rt_sem_t init_sem = rt_sem_create("lwip_init_sem", 0, RT_IPC_FLAG_PRIO);
        tcpip_task_blocker = rt_sem_create("tcpip_task_blocker", 0, RT_IPC_FLAG_PRIO);
        tcpip_init(tcpip_init_done, init_sem);
        // 阻塞在信号量获取
        rt_sem_take(init_sem, RT_TICK_MAX / 2 - 1);
        rt_sem_delete(init_sem);
    } else {
        rt_sem_release(tcpip_task_blocker);
    }
    return true;
}

运行过程中可能会报错提示 lwip 线程栈空间不足,在 menuconfig 中适当改大即可
对接完成后测试功能,使能为 STA 模式,日志中显示 mac 地址

在这里插入图片描述

扫描附近ap

在这里插入图片描述

连接ap并成功ping通

在这里插入图片描述

测试ap功能,使能为AP模式,设置名称及pwd,可以使用手机成功连接。

注意事项

  • 使用pico w的无线模块需要使用一些相关的宏定义,如无线模块的引脚定义等,其定义在 picow.h 中。但程序默认包含的是 pico.h 。可以通过定义宏 PICO_CONFIG_HEADER=boards/pico_w.h 进行切换。

  • 吞吐量还未进行测试。

  • 目前基于 C/C++ SDK 的开发案例较少,推荐直接阅读官方文档。

  • 在对接设备驱动框架 wifi_join 方法时苦恼于 ap 的 channel 和 bssid 没有正常传递,查看源码发现使能 RT_WLAN_JOIN_SCAN_BY_MGNT
    这个宏可以先扫描ap,并传递包含 channel 和 bssid 的 info,但要将以下改为rt_memcpy在这里插入图片描述

    个人理解,没有找到其他的说明和用例。(不过最后发现,连接ap没有 channel 和 bssid 也行,直接设置为 RT_NULL )

觉得不错的话就给项目点个 star 吧!
软件包地址:cyw43439-RTT

Ref:

  • https://www.raspberrypi.com/documentation/pico-sdk
  • https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
  • https://datasheets.raspberrypi.com/picow/connecting-to-the-internet-with-pico-w.pdf
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值