0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

冬至子 来源:螺丝松掉的人 作者:螺丝松掉的人 2023-11-28 17:15 次阅读

前言:

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

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

准备工作

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

开始开发

主要有以下三种类型: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 中使能即可:

1.jpg

引入兼容层后大部分报错消失了,但报错没有 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 。主要包含以下内容:

替换头文件:

用 RT-Thread 的头文件替换 FreeRTOS 的头文件。

修改任务创建和管理:

使用 RT-Thread 的任务创建和管理 API 替代 FreeRTOS 的任务 API。

注意 RT-Thread 的任务入口函数参数和返回值的差异。

修改互斥锁:

替换 xSemaphoreCreateRecursiveMutex 为 RT-Thread 提供的互斥锁创建 API。

替换 xSemaphoreTakeRecursive 和 xSemaphoreGiveRecursive 为 RT-Thread 互斥锁的 API。

替换定时器:

使用 RT-Thread 的软定时器或者实时时钟服务替代 FreeRTOS 定时器。

任务通知:

替换 FreeRTOS 的任务通知 API 为 RT-Thread 的事件和信号量等。

任务挂起和唤醒:

替换 FreeRTOS 的 vTaskSuspend 和 vTaskResume 为 RT-Thread 的任务挂起和唤醒 API
主要涉及 async_context_rtthread,cyw43_arch,cyw43_arch_rtthread,lwip_rtthread这些文件,基础的移植完成后,就可以开始将其对接到 RT-Thread 的 Wi-Fi 设备驱动框架了,主要参考 rw007 和 cyw43012-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 中适当改大即可

1.jpg

对接完成后测试功能,使能为 STA 模式,日志中显示 mac 地址

1.jpg

扫描附近ap

1.jpg

连接ap并成功ping通

1.jpg

测试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

1.jpg

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

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 无线通信
    +关注

    关注

    58

    文章

    4565

    浏览量

    143500
  • LED控制
    +关注

    关注

    0

    文章

    39

    浏览量

    16903
  • Wi-Fi技术
    +关注

    关注

    0

    文章

    58

    浏览量

    8372
  • RT-Thread
    +关注

    关注

    31

    文章

    1285

    浏览量

    40093
收藏 人收藏

    评论

    相关推荐

    BL808 RT-Thread Wi-Fi 驱动适配

    BL808 WiFi 属于 SOC 单芯片型无线 MCU,片上集成 WiFi 功能,移植 RT-Thread 过程中,需要使用 RT-Thread wlan 框架。 RT-Thread wlan
    的头像 发表于 12-02 11:06 1462次阅读
    BL808 <b class='flag-5'>RT-Thread</b> <b class='flag-5'>Wi-Fi</b> 驱动<b class='flag-5'>适配</b>

    RT-ThreadC语言编码规范

    这是一份 RT-Thread 开发人员的开发指引。RT-Thread 做为一份开源软件,它需要由不同的人采用合作的方式完成,这份文档是开发人员的一个指引。RT-Thread 的开发人员请遵守这样
    的头像 发表于 02-21 16:50 2469次阅读

    BL808 RT-Thread Wi-Fi驱动适配

    BL808 WiFi 属于 SOC 单芯片型无线 MCU,片上集成 WiFi 功能,移植 RT-Thread 过程中,需要使用 RT-Thread wlan 框架。
    的头像 发表于 12-04 11:38 869次阅读

    【每日精选】开源鸿蒙系统DAYU200教程及Tina Wi-Fi模组移植

    大家好,今天推荐一些社区好帖,欢迎大家留言也推荐更多好帖子,推荐会有奖励哈!今日推荐:【网络专题1】Tina Wi-Fi模组移植_实践篇【网络专题1】Tina Wi-Fi模组移植_理论篇 [经验
    发表于 03-15 15:32

    RT-Thread实战笔记资料汇总

    Cortex-M/R/A, MIPS, X86, Xtensa, C-Sky, RISC-V,几乎支持市场上所有主流的 MCU 和 Wi-Fi 芯片。
    发表于 03-25 15:54

    【BPI-Pico-RP2040 开发板】+Pico运行RT-Thread

    Type-C插座NorFlash存储IC开发板脚位以及功能图:拿到手焊接后的图:使用过程本次在RT-Studio上进行开发,打开RT-Thread Studio,打开SDK Mana
    发表于 03-17 23:01

    嵌入式 | 如何在搭载了RT-Thread系统的STM32平台上使用C++?

    本文描述了如何使用在搭载了 RT-Thread 系统的 STM32 平台上使用 C++,包括 C++ 的配置和应用等,并给出了在STM32F411 NUCLEO开发板上验证的代码示例。
    的头像 发表于 06-20 14:04 4476次阅读

    如何使用在搭载了RT-Thread系统的STM32平台上使用C++

    RT-Thread Components ---> C++ features ---> Support C++ features,如图所示:
    的头像 发表于 12-08 10:27 3828次阅读
    如何使用在搭载了<b class='flag-5'>RT-Thread</b>系统的STM32平台上使用<b class='flag-5'>C++</b>

    基于STM32F4和RT-Thread通用BootLoader使用经验

    基于STM32F4、RT-Thread通用BootLoader使用经验
    的头像 发表于 02-27 17:23 6299次阅读
    基于STM32F4和<b class='flag-5'>RT-Thread</b>通用BootLoader使用<b class='flag-5'>经验</b>

    如何在搭载了RT-Thread系统的STM32平台上使用C++

    本文描述了如何使用在搭载了 RT-Thread 系统的 STM32 平台上使用 C++,包括 C++ 的配置和应用等,并给出了在STM32F411 NUCLEO开发板上验证的代码示例。
    发表于 02-10 10:43 3次下载
    如何在搭载了<b class='flag-5'>RT-Thread</b>系统的STM32平台上使用<b class='flag-5'>C++</b>?

    2022 RT-Thread全球技术大会:萤石EZIOT SDKRT-Thread的支持

    2022 RT-Thread全球技术大会:RT-Thread在摄像头及IoT设备上的实践经验分享
    的头像 发表于 05-27 11:08 1310次阅读
    2022 <b class='flag-5'>RT-Thread</b>全球技术大会:萤石EZIOT <b class='flag-5'>SDK</b>对<b class='flag-5'>RT-Thread</b>的支持

    RT-Thread全球技术大会:萤石EZloT SDKRT-Thread的支持以及多芯片平台管理策略

    RT-Thread全球技术大会:萤石EZloT SDKRT-Thread的支持以及多芯片平台管理策略           审核编辑:彭静  
    的头像 发表于 05-27 11:55 1719次阅读
    <b class='flag-5'>RT-Thread</b>全球技术大会:萤石EZloT <b class='flag-5'>SDK</b>对<b class='flag-5'>RT-Thread</b>的支持以及多芯片平台管理策略

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 9次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植

    RT-Thread文档_I2C 总线设备

    RT-Thread文档_I2C 总线设备
    发表于 02-22 18:35 0次下载
    <b class='flag-5'>RT-Thread</b>文档_I2<b class='flag-5'>C</b> 总线设备

    经验总结】一位近10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的?

    经验总结】一位近10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的?
    的头像 发表于 05-16 15:33 1084次阅读
    【<b class='flag-5'>经验总结</b>】一位近10年的嵌入式开发老手,到底是如何快速学习和使用<b class='flag-5'>RT-Thread</b>的?