1.通过STM32CubeMX配好好使用的外设并生成一个完整的工程 2.打开工程并编译,确保工程可以顺利编译完成 3.下载RT-Thread源码,下载方式有 1)GitHub 的下载链接:https://github.com/RT-Thread/rt-thread 2)Gitee 的下载链接:https://gitee.com/rtthread/rt-thread 3)百度网盘的下载链接:https://pan.baidu.com/s/1mgIAyWo#list/path=%2F 4)RT-Thread Nano(纯净的内核版本):https://www.rt-thread.org/document/site/tutorial/nano/an0038-nano-introduction/ 4. 移植以纯净内核版为基础,所以下载RT-Thread Nano。 5. 将下载并解压出来的rt-thread文件夹复制到工程目录下。 6. 将rt-thread下的需要用到的文件添加到工程中,其中必须的文件包括: 1)rt-thread/bsp文件夹中的board.c和rtconfig.h:这两个文件在移植中是需要修改的,所以一般跟其他需要修改的文件放到同一目录下。 2)rt-thread/include文件夹和rt-thread/include/libc文件夹的内容也是必须的,只不过这两个文件夹下面的文件都是头文件,不需要添加,只需要在头文件路径中包含即可。 3)rt-thread\libcpu文件夹下面包含的是处理器内核和编译器相关的文件,只需要选择想对应的内核文件夹下面的文件即可,比如M3内核的CPU,MDK编译器需要选择:rt-thread\libcpu\arm\cortex-m3路径下的cpuport.c和context_rvds.S两个文件。 4)rt-thread\src文件夹下面包含的是RT-Thread的内核代码,整个文件夹下面的文件都是必须的。 7. 添加头文件路径。 8. 编译,一般情况下都会报下图所示的错误,报该错误的原因是RT-Thread代码中实现了这三个中断服务函数,而STM32CubeMX生成的工程中也实现了这个三个函数,导致这三个函数重复定义了。STM32CubeMX生成的工程是在stm32f3xx_it.c中实现这三个函数的,只需要在这个文件中找到这三个函数并将该文件中的三个函数注释掉即可。由于注释掉了stm32f3xx_it.c,那么HAL_Delay就不能正常使用了(因为HAL_Delay函数是基于stm32f3xx_it.c文件中的SysTick_Handler调用HAL_IncTick对uwTick进行累加实现了),如果要保证HAL_Delay正常使用,我们可以将HAL_IncTick()函数添加到board.c文件中的SysTick_Handler()函数中,需要注意的是推荐添加在开关中断中间。
9.把main.h文件复制到工程目录下的rt-thread\bsp文件夹下并将mian.h文件改成board.h。 10. 打开board.h文件将里面的MAIN统统换成BOARD。 11. 打开main.c文件,将#include "main.h"改成#include “board.h”。 12. 编译,确认上述更改解决了中断服务函数重复定义问题和上述更改没有引入新语法错误。 13. 打开main.c文件,将该文件中除了#include "board.h"外的头文件统统剪切复制到board.h文件中。 14. 打开board.c文件,在里面添加#include “board.h” 15. 编译确认没有引入新语法错误。(在移植的过程中,做了一些改动后最好重新编译下确保没有引进新错误,要是等所有操作都做完了再编译发现一堆错误就不知道是哪个步骤引进来的了,想要排查就会非常困难和费时) 16. 打开board.c文件,将main.c文件中的void SystemClock_Config(void)函数完整地剪切到board.c文件的void rt_hw_board_init()函数前面,因为rt_hw_board_init()需要调用SystemClock_Config()函数来完成时钟初始化。 17. 注释掉void rt_hw_board_init()函数中的SystemCoreClockUpdate()和_SysTick_Config(),不用该文件中提供的时钟初始化函数,而是用我们自己的函数代替这两个函数。 18. 按main.c文件main()函数的顺序将各外设的初始化函数剪切到rt_hw_board_init()的前面,其中SystemClock_Config就是用来替换SystemCoreClockUpdate()进行时钟初始化配置的,初始之外还需要在紧跟着该函数的后面添加函数HAL_SYSTICK_Config( HAL_RCC_GetSysClockFreq() / RT_TICK_PER_SECOND );用于配置systick。 19. 再来编译一次,如果你没有注释掉main.c中的SystemClock_Config会发现报了个SystemClock_Config函数重定义的错误,回过头去将main.c文件中的该函数注释掉即可,注释掉后再编译正常的话是没有错误的。 20. 至此,基本的移植已经完成了。此时的代码烧到板子上是看不到任何效果的,我们可以在rt_hw_board_init()函数中加个点灯测试下。为什么并不是在main()函数中加呢?这里设计到系统的启动过程,在RT-Thread中,系统上电后在运行我们main.c文件的main函数之前会先运行
S
u
b
Sub
Sub
m
a
i
n
函
数
,
在
main函数,在
main函数,在Sub$$main函数里又会调用rtthread_startup()函数,rtthread_startup()函数里面在关了中断后会先调用rt_hw_board_init()进行板件外设初始化,然后再初始化操作系统相关的额组件,只有等操作系统调度器工作后才会进入到我们的maic.c文件里面的main函数。所以如果我们在main函数中点灯测试的话如果操作系统的某个组件异常我们也很有可能点灯不成功,我们还是一步一步来,先不验证操作系统组价,先验证前面的移植工作是否正确,确保前面的移植工作正确后再测试操作系统的其他组件。 21. 由于延时还是还不能使用(暂时不知道为啥不能使用,SysTick_Handler中断一直进不去),所以在验证中可以使用单步的方式先点亮灯,在单步一下熄灭灯,如果成功,说明前面的移植是没有问题的。 22. 回到main.c文件中,创建一个线程点灯线程: 1)申请一个线程控制块变量:static struct rt_thread led1_thread; 2)申请一块线程堆栈内存:static rt_uint8_t led1_thread_stack[512];申请堆栈内存前需要用ALIGN(RT_ALIGN_SIZE)做对齐处理 3)新建线程入口函数 4)在main函数中调用rt_thread_init初始化线程控制块 5)初始化后调用rt_thread_startup启动线程,至此线程便加入了调度列表参与调度。 23. 打开rtconfig.h文件并找到#define RT_USING_HEAP(大约在一百零几行)并使能该宏(即将该宏前面的注释符号给去掉),如果不使能的话线程会跑不起来。 24. 编译并烧录进板子,一切正常的话可以看到线程已经控制着LED灯在闪烁了。
|