Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
Linux
RT-Thread Nano
移植问题
linux下基于stm32cubemx的RT-Thread-nano移植
发布于 2021-12-22 16:41:24 浏览:1538
订阅该版
[tocm] linux下STM32CUBEMX+手工移植rt-thread nano 代码与原文:[https://gitee.com/jixukong/rt-thread-nano.git](https://gitee.com/jixukong/rt-thread-nano.git) 因官方推荐的cubemx移植方法导致每次修改stm32CubeMX重新生成后需屏蔽部分代码,cubemx中添加组件方式造成目录复杂,内容杂乱,且网络中对于使用gcc交叉编译工具下的stm32相关教程较少,因此在此探究一种尽量减少移植难度的方法。望大家指正。 by:jixukong email:1242408274@qq.com # 移植过程 ## 0.环境 软件: 操作系统:20.04.1-Ubuntu x86_64 x86_64 x86_64 GNU/Linux 编译工具:gcc-arm-none-eabi-10.3-2021.10 代码编辑工具:visual studio code 代码生成:stm32cubemx-linux版本 下载:如在linux下使用串口下载方式,可使用stm32flash工具 串口调试:可使用minicom进行调试 硬件: 芯片:stm32f103c8t6(64KB FLASH+20KB SRAM) 时钟:均使用内部时钟 外设:本实验中以 GPIOA1为LED显示,GPIOA9-10为UART1作为shell端口 ## 1.stm32CubeMX配置 1.打开cubeMX->File->new project,搜索并选择STM32F103C8 2.Project Manager配置 主要配置IDE为makefile 设置生成独立的.h.c文件 ![](./.figures/cube-project-manager-1.png) 3.Clock configuration 这里全部使用内部时钟,使内部时钟最大化 ![](./.figures/cube-clock-1.png) 4.Pinout&Configuration 配置LED引脚和USART1,USART1开启全局中断 ![](./.figures/cube-pinout-1.png) 5.保存并生成代码 目录结构如下:tree -L 2 ``` . ├── Core │ ├── Inc │ └── Src ├── Drivers │ ├── CMSIS │ └── STM32F1xx_HAL_Driver ├── Makefile ├── rt_thread.ioc ├── startup_stm32f103xb.s └── STM32F103C8Tx_FLASH.ld ``` ## 2.下载并移动rt-thread nano 本例中使用3.1.5版本,解压至本项目文件夹中 新建bsp目录,移动board.c、rtconfig.h 为使内容看起来更清晰,删除了代码无关的部分文件 因个人喜好并不喜欢目录过深,因此在根目录下新建了bsp,也可以使用rtthread中的bsp目录新建一个板子。 ``` . ├── bsp │ ├── Inc │ │ └── rtconfig.h │ └── Src │ └── board.c ├── Core │ ├── Inc │ │ ├── gpio.h │ │ ├── main.h │ │ ├── stm32f1xx_hal_conf.h │ │ ├── stm32f1xx_it.h │ │ └── usart.h │ └── Src │ ├── gpio.c │ ├── main.c │ ├── stm32f1xx_hal_msp.c │ ├── stm32f1xx_it.c │ ├── system_stm32f1xx.c │ └── usart.c ├── Drivers │ ├── CMSIS │ │ ├── 省略 │ └── STM32F1xx_HAL_Driver │ ├── Inc │ ├── License.md │ └── Src ├── Makefile ├── rt-thread │ ├── components │ │ ├── device │ │ └── finsh │ ├── include │ │ ├── libc │ │ ├── rtdbg.h │ │ ├── rtdebug.h │ │ ├── rtdef.h │ │ ├── rthw.h │ │ ├── rtlibc.h │ │ ├── rtm.h │ │ ├── rtservice.h │ │ └── rtthread.h │ ├── libcpu │ │ ├── arm │ │ └── risc-v │ └── src │ ├── clock.c │ ├── components.c │ ├── cpu.c │ ├── idle.c │ ├── ipc.c │ ├── irq.c │ ├── kservice.c │ ├── mem.c │ ├── memheap.c │ ├── mempool.c │ ├── object.c │ ├── scheduler.c │ ├── slab.c │ ├── thread.c │ └── timer.c ├── rt_thread.ioc ├── startup_stm32f103xb.s └── STM32F103C8Tx_FLASH.ld ``` ## 3.修改main.c文件内容 1.修改前在main.c中添加LED闪烁测试,此时并未移植RTOS 修改makefile中的交叉编译工具环境 ``` ####################################### # binaries at makefile ####################################### GCC_PATH=/usr/local/gcc-arm-none-eabi-10.3-2021.10/bin PREFIX = arm-none-eabi- ``` 2.makefile中添加ASMsrc Csrc INC ``` C_SOURCES = \ ...省略原有的 rt-thread/src/clock.c \ rt-thread/src/components.c \ rt-thread/src/cpu.c \ rt-thread/src/idle.c \ rt-thread/src/ipc.c \ rt-thread/src/irq.c \ rt-thread/src/kservice.c \ rt-thread/src/mem.c \ rt-thread/src/memheap.c \ rt-thread/src/mempool.c \ rt-thread/src/object.c \ rt-thread/src/scheduler.c \ rt-thread/src/slab.c \ rt-thread/src/thread.c \ rt-thread/src/timer.c \ rt-thread/libcpu/arm/cortex-m3/cpuport.c \ rt-thread/components/device/device.c \ bsp/Src/board.c # ASM sources ASM_SOURCES = \ startup_stm32f103xb.s \ rt-thread/libcpu/arm/cortex-m3/context_gcc.s # C includes C_INCLUDES = \ -ICore/Inc \ -IDrivers/STM32F1xx_HAL_Driver/Inc \ -IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \ -IDrivers/CMSIS/Device/ST/STM32F1xx/Include \ -IDrivers/CMSIS/Include \ -Irt-thread/components/finsh \ -Irt-thread/include \ -Ibsp/Inc ``` ## 4.RT-Thread 操作系统重定义 HardFault_Handler、PendSV_Handler、SysTick_Handler 中断函数 为了避免重复定义的问题,在cubemx中,需要在中断配置中,代码生成的选项中,取消选择三个中断函数(对应注释选项是 Hard fault interrupt, Pendable request, Time base :System tick timer)重新生成并编译测试。 ## 5.在main中调用entry 调整rt_config.h中的#define RT_THREAD_PRIORITY_MAX 32 否则可能会导致出错 ``` /* USER CODE BEGIN 2 */ entry(); /* USER CODE END 2 */ ``` 由于entry会启动rtthread,启动过程中会绑定main函数作为main线程。这里需修改绑定的main函数为usr_main,新建bsp/Src/usr_main.c并添加到makefile编写usr_main函数 main_thread_entry中main修改为usr_main,将main.c中的main作为了一个启动函数,但可以避免重新编译时移动board.c,因此main中取消while循环 在我们新建的usr_main函数中添加led测试代码,注意rtthead正常情况下已被启动,故此时调用的函数不是HAL_Delay()而是rt_thread_mdelay 在main.h中包含#include
## 6.在 RT-Thread Nano 上添加控制台与 FinSH ### 添加 UART 控制台(实现打印) 串口初始化和系统输出函数,即可完成 UART 控制台打印功能。 串口初始化工作我们已使用cubemx完成,rtconfig.h 中使能 RT_USING_CONSOLE,在此前我们可以在usr_main中使用HAL_UART_Transmit();测试串口输出 Core/Src/usart.c中添加对接函数rt_hw_console_output,打印出了启动信息 ```C //对接的 rt_hw_console_output() 函数,实现控制台字符输出 void rt_hw_console_output(const char *str) { rt_size_t i = 0, size = 0; char a = '\r'; __HAL_UNLOCK(&huart1); size = rt_strlen(str); for (i = 0; i < size; i++) { if (*(str + i) == '\n') { HAL_UART_Transmit(&huart1, (uint8_t *)&a, 1, 1); } HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1); } } ``` ```bash \ | / - RT - Thread Operating System / | \ 3.1.5 build Dec 22 2021 2006 - 2020 Copyright by rt-thread team ``` ### 添加 FinSH 组件(实现命令输入) 在 rtconfig.h 中使能 #define RT_USING_FINSH 宏定义 makefile src中添加bsp/Src/ringbuffer.c ``` rt-thread/components/finsh/cmd.c \ rt-thread/components/finsh/finsh_port.c \ rt-thread/components/finsh/msh.c \ rt-thread/components/finsh/shell.c ``` 此时编译会出现 ``` #error "TODO 4: Read a char from the uart and assign it to 'ch'." 24 | #error "TODO 4: Read a char from the uart and assign it to 'ch'." ``` 对接控制台输入函数,实现字符输入:实现 rt_hw_console_getchar Core/Src/usart.c ```C 具体修改见代码 bsp/Src/ringbuffer.c Core/Src/usart.c ``` 由于对接完成后完成后依旧报错"TODO 4:",在makefile SRC中去掉了rt-thread/components/finsh/finsh_port.c ### 链接脚本 在lds中的text段添加以下内容,否则系统无法进行自动初始化函数,导致finsh线程不会被开启 ``` /***************RTOS add**********************/ /* section information for finsh shell */ . = ALIGN(4); __fsymtab_start = .; KEEP(*(FSymTab)) __fsymtab_end = .; . = ALIGN(4); __vsymtab_start = .; KEEP(*(VSymTab)) __vsymtab_end = .; /* section information for utest */ . = ALIGN(4); __rt_utest_tc_tab_start = .; KEEP(*(UtestTcTab)) __rt_utest_tc_tab_end = .; /* section information for at server */ . = ALIGN(4); __rtatcmdtab_start = .; KEEP(*(RtAtCmdTab)) __rtatcmdtab_end = .; . = ALIGN(4); /* section information for initial. */ . = ALIGN(4); __rt_init_start = .; KEEP(*(SORT(.rti_fn*))) __rt_init_end = .; . = ALIGN(4); PROVIDE(__ctors_start__ = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) PROVIDE(__ctors_end__ = .); . = ALIGN(4); /********************************************/ ``` ## 7.完成 编译后FINSH组建已经可用,并且修改cubemx后无需再移动main中的文件 目录与修改的文件如下所示 ``` . ├── bsp -我们自己的代码使用的文件夹 │ ├── Inc │ │ ├── ringbuffer.h -对接Finsh的缓冲头文件 │ │ └── rtconfig.h -由Rtthread复制出来做rtos功能配置 │ └── Src │ ├── board.c -与官方移植不同的是我们没有动这个文件 │ ├── ringbuffer.c -对接Finsh的缓冲实现 │ └── usr_main.c -usr_main函数,也是main线程调用的函数 ├── Core -使用cubemx生成的代码 │ ├── Inc │ │ └── ... │ └── Src -只修改了main.c和usart.c,且写在合适位置处,cubemx重新生成代码时不会被冲掉 │ └── ... ├── Drivers -cubemx生成的驱动文件和HAL库 │ ├── CMSIS │ │ └── ... │ └── STM32F1xx_HAL_Driver │ └── ... ├── Makefile -makefile文件,用来指导编译,最初由cubemx生成,修改了编译环境,添加了一些源码结构 ├── README.md -说明,即本文 ├── rt-thread │ ├── components -组件,用到了其中的finsh组建,没有修改源码 │ │ ├── device │ │ └── finsh │ ├── include -rtthread使用的头文件,未修改 │ │ └── ... │ ├── libcpu -rtthread对于不同cpu支持的汇编代码,这里我们选用了arm/m3下的gcc.s │ │ ├── arm │ │ └── risc-v │ └── src -rtthread相关的源码,未作修改 │ └── ... ├── rt_thread.ioc -cubemx项目文件 ├── startup_stm32f103xb.s -启动汇编代码cubemx生成,与官方不同的是,未做修改 └── STM32F103C8Tx_FLASH.ld -链接脚本,cubemx生成,添加了rtthread所需的代码段 ``` 可以看到,我们并未修改rt-thread下的文件,因此无需关心这些源码的修改 完成后三层目录结构如下 ```shell rt-thread-nano$ tree -L 3 . ├── bsp │ ├── Inc │ │ ├── ringbuffer.h │ │ └── rtconfig.h │ └── Src │ ├── board.c │ ├── ringbuffer.c │ └── usr_main.c ├── Core │ ├── Inc │ │ ├── gpio.h │ │ ├── main.h │ │ ├── stm32f1xx_hal_conf.h │ │ ├── stm32f1xx_it.h │ │ └── usart.h │ └── Src │ ├── gpio.c │ ├── main.c │ ├── stm32f1xx_hal_msp.c │ ├── stm32f1xx_it.c │ ├── system_stm32f1xx.c │ └── usart.c ├── Drivers │ ├── CMSIS │ │ ├── Core │ │ ├── Core_A │ │ ├── Device │ │ ├── docs │ │ ├── DSP │ │ ├── Include │ │ ├── Lib │ │ ├── LICENSE.txt │ │ ├── NN │ │ ├── RTOS │ │ └── RTOS2 │ └── STM32F1xx_HAL_Driver │ ├── Inc │ ├── License.md │ └── Src ├── Makefile ├── README.md ├── rt-thread │ ├── components │ │ ├── device │ │ └── finsh │ ├── include │ │ ├── libc │ │ ├── rtdbg.h │ │ ├── rtdebug.h │ │ ├── rtdef.h │ │ ├── rthw.h │ │ ├── rtlibc.h │ │ ├── rtm.h │ │ ├── rtservice.h │ │ └── rtthread.h │ ├── libcpu │ │ ├── arm │ │ └── risc-v │ └── src │ ├── clock.c │ ├── components.c │ ├── cpu.c │ ├── idle.c │ ├── ipc.c │ ├── irq.c │ ├── kservice.c │ ├── mem.c │ ├── memheap.c │ ├── mempool.c │ ├── object.c │ ├── scheduler.c │ ├── slab.c │ ├── thread.c │ └── timer.c ├── rt_thread.ioc ├── startup_stm32f103xb.s └── STM32F103C8Tx_FLASH.ld ``` # 附录:思路 ## rt-thread的执行过程 本部分分析文件启动过程 ``` startup_stm32f103xb.s: Reset_Handler 64:将数据段初始化器从闪存复制到SRAM 81:清BSS 96:系统时钟初始化 ->Core/Src/system_stm32f1xx.c-SystemInit()空的 98:静态构造函数 ->__libc_init_array c 库的初始化 101:跳转到入口函数(原来是main) -> RTOS/src/components.c-entry(void) -> rtthread_startup(); 中断异常向量表: 中断入口函数定义: RTOS/src/components.c rtthread_startup() 关中断//RTOS/libcpu/context_gcc.s-rt_hw_interrupt_disable 板初始化//RTOS/board.c-rt_hw_board_init 打印RTOS版本信息//RTOS/src/kservice.c-rt_show_version(); 初始化系统系统定时器 //RTOS/src/timer.c-rt_system_timer_init(); 调度器初始化//RTOS/src/scheduler.c-rt_system_scheduler_init 初始化应用程序//RTOS/src/components.c-rt_application_init 初始化main线程并启动绑定main_thread_entry函数 main_thread_entry:rt线程组件初始化 函数指针遍历执行了许多函数... 执行了main(); 定时器线程初始化//RTOS/src/timer.c-rt_system_timer_thread_init 此线程未开启需开启RT_USING_TIMER_SOFT宏//定时器线程绑定timer_thread函数 空闲线程初始化//RTOS/src/idle.c-rt_thread_idle_init 绑定rt_thread_idle_entry函数 while(1){ 未开启RT_USING_IDLE_HOOK,若开启会执行idle钩子函数 rt_thread_idle_excute该功能将在系统空闲时执行系统后台任务。内部未开启RT_USING_HEAP 未开启RT_USING_PM,否则会进入电源管理器rt_system_power_manager } 开启调度器//RTOS/src/scheduler.c-rt_system_scheduler_start 进行调度执行RTOS/libcpu/context_gcc.s-rt_hw_context_switch_to ``` ## cubemx生成的默认执行过程 startup_stm32f103xb.s 之前同上,101:跳转到入口函数main中直接执行
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
1242408274
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
求高手指点,RTThread下nanosleep()函数功能如何实现?在线等啊
2
RTT1.2.2在新塘Nano130KE3BN的移植中始终出现栈溢出的问题
3
官方能否出一个nano在mdk下移植finsh到stm32的教程
4
从裸机开始,创建一个RT-Thread Nano系统工程
5
Nano版如何启用shell
6
项目从RTT 2.x NANO移植到 RTT 3.x ENV 环境
7
nano 版本有没有集成到 IAR 中啊?
8
关于MDK5的RT-THREAD NANO中添加MSH组件的例程
9
rtt_nano版本,源代码在哪里下载啊?
10
RTT Nano 在keil 使用C++11 的问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
cubemx
PWM
flash
packages_软件包
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
出出啊
1516
个答案
342
次被采纳
小小李sunny
1440
个答案
289
次被采纳
张世争
799
个答案
171
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
4
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部