stm32_f103c8t6 RT Thread 移植笔记
该文章用来记录移植RT Thread的过程记录,本次移植基于STM32 F103C8T6,使用STM32 CubeMX工具构建HALL库的Makefile工程。
环境
- 开发板:STM32F103C8T6最小开发板之一
- 操作系统:Linux
- 开发环境:VSCode
- 编译工具:GCC Makefile
- 烧录工具:CMSIS DAP + openOCD
构建Makefile工程
- 首先在构建工具STM32 CubeMX创建STM3F103的工程,如下图
- 然后配置好对应的引脚时钟和外围,随后导出一个Makefile工程
- 工程如下,因为使用了USB和stm32 CubeMX来构建工程,所以会生成如下的目录结构
.
├── Core
├── Drivers
├── Makefile
├── Middlewares
├── startup_stm32f103xb.s
├── stm32f103c8t6_bare.ioc
├── STM32F103C8Tx_FLASH.ld
└── USB_DEVICE
4 directories, 4 files
接下来相关的移植操作就会在这个工程的基础上进行
获取RT Thread Nano资源
RT Thread的资源位于其官方的github仓库中,点击获取官网提供版本
- 下载下来的RT Thread Nano的官网版本目录结构如下
.
├── AUTHORS
├── bsp
├── ChangeLog.md
├── components
├── docs
├── include
├── libcpu
├── LICENSE
├── README.md
└── src
6 directories, 4 files
接下来会使用其中的主要文件夹为
- components:组件文件夹,主要使用其中的finsh组件,这个是一个命令行控制组件
- include:头文件相关文件夹,RT Thread的主要文件之一
- libcpu:MCU资源移植文件夹,用来是的MCU能够 完美支持RT Thread去运行
- src:源文件相关文件夹,RT Thread的主要文件之一
移植RT Thread的一些要点简述
- 主要的移植要点都在这里,下面讲的都是大致内容
移植过程基本分为下面几步:
- 添加 Nano 源文件
- 配置工程相关内容
上述的内容即为
开始移植
- 移植前我已经在项目中添加了一个闪灯的功能,等移植完毕后也会和移植前有一样的效果
文件拷贝
根据上述的内容说明,我们应该将文件夹components、include、libcpu、src的内容悉数移动过来,但是也有一些其他内容需要注意,基本如下步骤
- 移动相关文件夹
- 移动相关文件
- context_gcc.s:该文件是用来控制上下文切换(例如线程切换)时要做的操作,一般是使用芯片原厂提供的内容
- board.c:这个文件是用来实现一些RT_Thread的一些要求的函数,如系统时钟初始化,滴答计时器中断实现等
- rtconfig.h:该文件用于配置RT thread的功能开启和关闭的
项目配置
和项目配置相关的内容有两个,分别是项目的源文件配置和项目的配置文件配置
源文件配置
- 源文件的配置一般是相关中断的配置和项目配置文件,所以做如下的配置
- 启动文件配置
该动作是用来让RT_Thread
取代裸机main为启动入口的功能,先进入entry来启动RT_Thread
,然后在新线程中调用main功能
- rtconfig.h文件配置
目前保持默认,finsh关闭
- stm32f1xx_it.c的中断配置
需要注释掉的中断分别为如下几个
- void HardFault_Handler(void):硬件错误中断处理函数
- void PendSV_Handler(void):任务切换处理函数
- void SysTick_Handler(void):系统滴答定时器中断处理函数
项目配置文件配置
本次使用Makefile文件来管理项目,所以配置的是Makefile文件内容,基本上 原理就是添加对应的源文件,如下图:
注意:在此处我将汇编文件context_gcc.S文件名改成了小写后缀的context_gcc.s,因为大写的S不符合后续的Makefile规则
测试运行
使用make编译完成后在build文件夹中将elf文件通过openOCD烧录进板子中后可以达成运行效果
移植finsh
finsh是RT_Thread
中的一个比较有特点的组件,目前的RT_Thread Nano
中支持了该组件的移植,因为该组件依赖的功能不多
移植步骤
- 复制代码
- 配置项目
- 编辑源文件
- 测试
复制代码
之前的复制RT_Thread的源文件的过程中,components中的内容就是finsh的源代码
配置项目
需要配置的项目文件有:
- Makefile:添加finsh的头文件包含和源文件内容
- 链接文件:添加finsh遗漏的链接函数声明和RT_Thread的初始化函数声明
- 添加的内容
/* section information for finsh shell */
. = ALIGN(4);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(4);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
. = ALIGN(4);
/* section information for initial. */
. = ALIGN(4);
__rt_init_start = .;
KEEP(*(SORT(.rti_fn*)))
__rt_init_end = .;
. = ALIGN(4);
编辑源文件
编辑源文件需要的内容如下:
- 添加基本的控制台输出和配置
- 添加finsh msh的配置
- 添加finsh msh相关的控制台输入
- 添加finsh生效的链接文件内容
添加基本的控制台输出和配置
如果只是使用finsh作为基本的输出而不需要输入的话(也就是只使用rt_kprintf()函数),只需要做简单的配置就可以实现
- 配置rtconfig.h
- 实现控制台输出函数,该函数的功能是从串口输出一个字符
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);
}
}
然后使用函数rt_kprintf()
当作printf功能输出即可
添加finsh msh的配置
配置如下:
在#if defined(RTE_USING_FINSH)
之前添加#define RTE_USING_FINSH
,因为我们的Makefile工程不需要rte配置文件(MDK中的才有)
添加finsh msh相关的控制台输入
- 在控制台输出函数的下方加入以下代码即可,该函数功能是从串口获取一个字符
char rt_hw_console_getchar(void)
{
int ch = -1;
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
{
ch = huart1.Instance->DR & 0xff;
}
else
{
rt_thread_mdelay(10);
}
return ch;
}
添加finsh生效的链接文件内容
因为在与其他的工程的链接文件的对比中法相,使用STM32CubeMX生成的工程的链接文件中没有添加相关的一些内容,已经在上面说明,不再赘述
测试
基本上做完上面的内容后finsh就可以生效了