RT-Thread移植到nRF52840

04/14 14:18
阅读数 125

编者按:  

其实很忙的,但是还是抽时间记录了我的学习过程。这应该是我写的格式比较正规的第3本学习笔记了,第一本《BLE4.0低功耗蓝牙协议总结》、第二本《ANT协议研究》,再就是这本了《RT-Thread BLE5.0和ANT+应用开发实战指南》,名字取得很大,哈哈哈!!目前这本已经写到了第19章,目前规划到了35章左右,慢慢写吧!在这呢!感谢熊大团队的RT-Thread操作系统,的确是一个非常好的RTOS,至少对于我来说很喜欢,因为其他RTOS就是个内核,大一点的就是Linux,太庞大了,吃不消。本文从文档中抽出RT-Thread移植到nRF52840这篇和大家分享,这个文档应该会在11月底发到论坛,公众号、qq群和百度网盘的。


《RT-Thread BLE5.0和ANT+应用开发实战指南》

当前目录如下图

第11章 RT-Thread移植到nRF52840


    终于进入正文了,这里再啰嗦一句,如果需要了解RT-Thread的内核等问题,可以参考RT-Thread官放的《rtthread_manual.zh》(下载地址-复制至外部浏览器打开:https://www.rt-thread.org/document/site/submodules/rtthread-manual-doc/README/)以及火哥的《RT-Thread 内核实现与应用开发实战—基于STM32》(本公众号后台回复:野火RT-Thread 即可下载),本书的重点还是侧重蓝牙理论和实战。这个工程是由001.led_none工程修改而来,对应ZJ-SDK的002.led_RT_Thread_Doing工程。


11.1 RT-Thread的内核源码加入基础工程


    为了从0到1的移植RT-Thread,这里先将RT-Thread的内核源码加入到 001.led_none 基础工程,看遇到的问题。添加的步骤是先添加.c文件,再添加.h文件路径到头文件,同时改了工程中文件夹的名字。


11.1.1 添加源文件

添加后的工程和基础工程对比如图11-1所示

  图11-1    基础工程添加RT-Thread内核源码

11.1.2 添加头文件路径

    头文件的添加对比如图11-2所示,只是添加了RT-Thread的内核头文件,以及M4核相关的头文件。


                          

  图11-2   基础工程添加RT-Thread相关头文件


11.2 编译解除错误

    上面添加之后,进行编译,编译结果如图11-3所示。编译报出没有rtconfig.h的头文件,实际上也的确没有这个头文件,可以从官方RT-Thread源码中的bsp目录下的nrf52832中的工程中拷贝一个rtconfig.h来,放到本工程的config文件夹中。这样编译就能完全通过了。

  图11-3    编译报错


11.3 编程成功存储分布

    再次编译,看看胜利的果实,如图11-4所示的存储分布,falshram的各个段都有明确的示意,堆和栈各使用了8K空间,中断向量表使用了256字节flash

 图11-4    存储分布图


11.4 运行RT-Thread内核

   经过上面的处理,只需要一个衔接nRF52840RT-Thread内核的关联文件,以及一个初始化RT-Thread的文件,那么就能使RT-Thread运行起来了。RT-Thread能运行起来就一定需要一个系统tick,也就是需要给RT-Thread内核创造一个产生tick的接口,实际上就是systick或者RTCtick中断函数,这个中断函数中处理RT-Thread的相关东西,从而使RT-ThreadnRF52840连接在一起。


11.4.1 衔接及初始化文件来源

    这里为了方便,我们依然从官方RT-Thread源码中的bspnRF52832中得到一些参考。官方nRF52832工程所包含的文件如图11-5所示。

    图11-5    官方nRF52832工程文件夹


    从官方工程文件中,我们只需要4个文件,分别是application文件夹下的application.c文件和startup.c文件以及board文件夹下的board.cboard.h文件。startup文件夹是arm相关以及nrf52832相关的文件,这里不需要。这几个文件中application.c是用户的函数入口,startup.cRT-Thread系统的初始化文件,而board.c文件则是产生tick的地方。将这4个文件直接拷贝到001.len_none目录下,如图11-6所示。

  图11-6    拷贝衔接启动文件后的工程目录


11.4.2 添加文件第一次编译排错

    接下来直接将这3.c文件添加到工程,以及包含头文件路径后进行第一次编译报错如图11-7所示。

图11-7    第一次编译报错


    因为没有使用uart,所有将这个头文件删掉。这样经过多次的编译删掉多余的头文件同时添加缺少的没有包含的头文件路径,一步一步地逼近编译成功。下面统计修改的地方。

  • 多的头文件:

uart.h softdevice_handler.h nrf_drv_uart.h

  • 少包含了的头文件路径:

nrf_drv_common.h路径:../../../NORDIC_SDK/integration/nrfx/legacy nrfx_clock.h路径:../../../NORDIC_SDK/modules/nrfx/drivers/include


11.4.3 第二次编译排错

   经过上面的修改之后,再次编译时,出现如图11-8的错误,有多个main函数。

图11-8    多个main函数定义

 可以查看到代码中除了原本的工程中有一个main.c文件中有main函数之外,还有一个文件application.c中也有main函数,这里为了保持led的闪烁功能,将移除main.c文件,将main.c中的main函数功能在application.c中的main函数实现。最后修改application.c的代码如代码清单11-1,红色部分为修改部分:

代码清单11-1    修改后的application.c

#include <rtthread.h> #include <stdbool.h> #include <stdint.h> #include "nrf_delay.h" #include "nrf_gpio.h" #ifdef RT_USING_FINSH #include <finsh.h> #include <shell.h> #endif void rt_init_thread_entry(void* parameter) {    nrf_gpio_cfg_output(ZJ_LED1);    /* Toggle LEDs. */    while (true)    {       nrf_gpio_pin_toggle(ZJ_LED1);       nrf_delay_ms(500);    } } int rt_application_init(void) {    rt_thread_t tid;    tid = rt_thread_create("init", rt_init_thread_entry, RT_NULL, 1024,                            RT_THREAD_PRIORITY_MAX / 3, 20);    if (tid != RT_NULL)        rt_thread_startup(tid);    return 0; }

11.4.4第三次编译排错

    再次进行编译出现如图11-9的错误

 图11-9    第三次编译出错

看报错记录有3个错误:

  • 第一个错误缺少函数定义,

    这个应该是缺少.c文件,这里使用了RTC,但是工程中没有相关的.c文件,所以这个错误只需将对应的.c文件添加到工程,同时在sdk_config.h中将这个功能宏打开即能解决。

    添加的两个.c文件是nrfx_clock.cnrf_drv_clock.c

   sdk_config.h文件末尾添加宏代码清单如11-2

代码清单11-2    sdk_config.h文件末尾添加宏

// </h> //========================================================== // <h> nRF_Drivers //========================================================== // <e> CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer //========================================================== #ifndef CLOCK_ENABLED #define CLOCK_ENABLED 1 #endif // <o> CLOCK_CONFIG_LF_SRC  - LF Clock Source // <0=> RC // <1=> XTAL // <2=> Synth #ifndef CLOCK_CONFIG_LF_SRC #define CLOCK_CONFIG_LF_SRC 1 #endif // <o> CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority // <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice // <0=> 0 (highest) // <1=> 1 // <2=> 2 // <3=> 3 // <4=> 4 // <5=> 5 // <6=> 6 // <7=> 7 #ifndef CLOCK_CONFIG_IRQ_PRIORITY #define CLOCK_CONFIG_IRQ_PRIORITY 7 #endif // </e> // </h> //==========================================================

  • 第二个错误是board.c中多了rt_hw_uart_init();删掉即可

  • 第三个错误是符号__bss_end没有定义

    这个符号的是没有初始在RAM中的段末地址,而这个地址要作为RT-Threadheap的起始地址,既然知道了是没有初始化的段末地址符号,那么就可以直接搜索__bss_end这个符号试试运气,可以找到在thumb_crt0.s中进行bss段清零时的使用到bss段末地址符号为__bss_end__(如图11-10所示),所以将这个错误宏改为__bss_end__即可。

  图11-10    bss段末地址符号__bss_end__


11.4.5编译成功存储分布

    经过多次的编译排错终于见到了胜利的曙光,编译的存储分布如图11-11所示。和只是加入源码的图11-4进行对比可以明显看到某些段有变化。

 图11-11    RT-Thread启动编译成功存储分布


11.5下载调试

     将上面的固件下载到ZJ曹孟德开发板中,可以看到LED1在闪烁,至此整个移植过程算是结束,但是我在调试时发现进入不了idle回调的休眠模式,因为在闪灯的延时函数是使用的死等延时,需要将nrf_delay_ms(500)修改为RT-Thread系统延时函数rt_thread_mdelay(500),再次编译下载调试发现灯没有闪烁,停止调试时,发现代码一直在一个while等待中,如图11-12所示。

图11-12    RT-Thread跳不出while


   NVIC_ISPR是中断挂起设置寄存器,这个while就是等到中断挂起寄存器中有中断挂起,而__WFE()则是wait for event 等待事件,即下一次事件发生前都在此hold住不干活从而使cpu进入low-power standby模式,这里去读NVIC_ISPR应该是有一定的逻辑问题的,经过参考其他资料和代码,可以将上面的do-while改为如代码清单11-3所示:

代码清单11-1    修改do-while

{    /* No SD -  we would just block interrupts globally.    * BASEPRI cannot be used for that because it would prevent WFE from wake up.    */     __WFE();     __WFE(); }

再次编译下载就可以看到LED1又活跃的闪烁起来了。至此整个移植过程完毕。


11.6美化工程

    上面的工程即是ZJ-SDK中的002.led_RT_Thread_Doing工程,虽然能完美的工作了,但是工程文件夹的组织还需要做一个适当的调整。所以就出现了ZJ-SDK中的003.led_RT_Thread工程,这个工程将是带有RT-Thread的基础工程。这两个工程的文件对比如图11-13所示。

    board.cstartup.c以及application.c都作为RT-Thread的启动文件,而用户的操作将在application文件夹中的app_init.c中进行,也就是LED1闪烁的功能实现是在app_init.c中了,而在application.c中进行调用,从而进入用户应用层。同时更改工程的名字为zj_ble_rt_thread,之后的工程名都将是这个名字,不会根据功能修改工程名,只会根据功能修改工程文件夹名。002.led_RT_Thread_Doing工程文件和003.led_RT_Thread工程文件对比图如图11-13所示。

   board.c文件不修改也是可以运行的,但是有一些不合理的逻辑,所以0003.led_RT-Thread工程中这个文件做了大的修改,在后文的第13章分析RT-Thread基础工程启动流程中将会进行详细分析。

 图11-13    工程美化

 图11-14    美化后的工程文件对比



往期精彩(点击文章即可阅读)

带你进入绚丽多彩的柿饼M(一)

带你进入绚丽多彩的柿饼M(二)

带你进入绚丽多彩的柿饼M(三)

带你进入绚丽多彩的柿饼M(四)

带你进入绚丽多彩的柿饼M(五)

基于RT-Thread和i.MX RT1052的开源AutoQuad飞控

基于RT-Thread的开源飞控StarryPilot

基于RT-Thread的蓝牙遥控平衡小车




RT-Thread近期活动

1.在本公众号后台回复“野火RT-Thread”即可下载《RT-Thread内核实现与应用开发实战指南》完整版

2.长按添加“小师妹”为好友,备注“学生”拉你进“RT-Thread官方学生”群,凡是在校学生组团报名参加大学生计划审核通过的,即可获得RT-Thread官方的竞赛支持、培训学习等。


你可以添加微信13924608367为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群

RT-Thread


让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。GPLv2+协议,可免费在商业产品中使用。

长按二维码,关注我们


👇点击进入官方论坛        

本文分享自微信公众号 - RTThread物联网操作系统(RTThread)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部