目录
概述
1 RT-Thread Nano
1.1 Nano版本介绍
1.2 RT-Thread Nano的特点
2 STM32Cube创建项目
2.1 配置参数
2.2 RT-Thread配置
3 RT-Thread适配MCU
3.1 预编译代码
3.2 解决编译错误
3.2.1 配置OS_TICK
3.2.2 使能finsh_config.h
3.3.3 移植FINSH
3.3 配置TICK
4 测试
概述
本文主要介绍RT-Thread Nano版本在STM32G474上的快速移植,笔者详细介绍了移植该系统的每个步骤,已经需要修改的源代码信息。最后在板卡上测试,以验证其功能。
1 RT-Thread Nano
1.1 Nano版本介绍
RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用32 位 ARM 入门级 MCU 。
下图是 RT-Thread Nano 的软件框图,包含支持的 CPU 架构与内核源码,还有可拆卸的 FinSH 组件:
1.2 RT-Thread Nano的特点
RT-Thread Nano 在使用上也非常简单,带给开发者友好的开发体验。
- 易裁剪:Nano 的配置文件为 rtconfig.h,该文件中列出了内核中的所有宏定义,有些默认没有打开,如需使用,打开即可。具体的配置可见 Nano 版块的 RT-Thread Nano 配置 教程。
- 易添加 FinSH 组件:FinSH 组件 可以很方便的在 Nano 上进行移植,而不再依赖 device 框架,只需要对接两个必要的函数即可完成 FinSH 移植。
- 自选驱动库:可以使用厂商提供的固件驱动库,如 ST 的 STD 库、HAL 库、LL 库等,可以自行选择。
- 完善的文档:包含 内核基础、线程管理 (例程)、时钟管理 (例程)、线程间同步 (例程)、线程间通信 (例程)、内存管理 (例程)、中断管理,以及 Nano 版块的移植教程。
2 STM32Cube创建项目
2.1 配置参数
配置MCU参数,包括系统时钟和UART,配置完成参数后,就可以生成Project
生成的项目固件架构如下:
2.2 RT-Thread配置
使用STM32Cube生成项目后,在Keil中配置RT-Thread,点击如下图标使能RT-Thread
完成配置后,在Keil中可以看见如下代码
3 RT-Thread适配MCU
3.1 预编译代码
首次编译代码后,会看见如下ERROR信息,不要惊慌,下面来分析这些Error log
Log message 列表
compiling board.c...
RTE/RTOS/board.c(47): error: #35: #error directive: "TODO 1: OS Tick Configuration."
#error "TODO 1: OS Tick Configuration."
RTE/RTOS/board.c: 0 warnings, 1 error
compiling finsh_port.c...
RTE/RTOS/finsh_port.c(14): error: #35: #error directive: Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h
#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h
RTE/RTOS/finsh_port.c: 0 warnings, 1 error
compiling main.c...
3.2 解决编译错误
3.2.1 配置OS_TICK
根据log提示,在board.c文件中配置TICK
compiling board.c...
RTE/RTOS/board.c(47): error: #35: #error directive: "TODO 1: OS Tick Configuration."
#error "TODO 1: OS Tick Configuration."
RTE/RTOS/board.c: 0 warnings, 1 error
找到代码的位置:
在该函数中添加如下代码:
/**
* This function will initial your board.
*/
void rt_hw_board_init(void)
{
//#error "TODO 1: OS Tick Configuration."
/*
* TODO 1: OS Tick Configuration
* Enable the hardware timer and call the rt_os_tick_callback function
* periodically with the frequency RT_TICK_PER_SECOND.
*/
/* 1、系统、时钟初始化 */
HAL_Init(); // 初始化 HAL 库
SystemClock_Config(); // 配置系统时钟
/* 2、OS Tick 频率配置,RT_TICK_PER_SECOND = 1000 表示 1ms 触发一次中断 */
SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
/* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}
3.2.2 使能finsh_config.h
根据log提示,在rtconfig.h文件中使能该配置
compiling finsh_port.c...
RTE/RTOS/finsh_port.c(14): error: #35: #error directive: Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h
#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h
RTE/RTOS/finsh_port.c: 0 warnings, 1 error
compiling main.c...
3.3.3 移植FINSH
错误log:
compiling finsh_port.c...
RTE/RTOS/finsh_port.c(24): error: #35: #error directive: "TODO 4: Read a char from the uart and assign it to 'ch'."
#error "TODO 4: Read a char from the uart and assign it to 'ch'."
RTE/RTOS/finsh_port.c: 0 warnings, 1 error
在在rtconfig.h文件中使能该配置
配置串口的相关函数
源代码如下:
#ifdef RT_USING_CONSOLE
static int uart_init(void)
{
//#error "TODO 2: Enable the hardware uart and config baudrate."
MX_USART1_UART_Init();
return 0;
}
INIT_BOARD_EXPORT(uart_init);
void rt_hw_console_output(const char *str)
{
//#error "TODO 3: Output the string 'str' through the uart."
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, 1000);
}
HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1000);
}
}
#endif
串口输入函数接口
配置方法如下:
源代码信息如下:
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*/
#include <rthw.h>
#include <rtconfig.h>
#include "usart.h"
#ifndef RT_USING_FINSH
#error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h
#endif
#ifdef RT_USING_FINSH
RT_WEAK char rt_hw_console_getchar(void)
{
/* Note: the initial value of ch must < 0 */
int ch = -1;
//#error "TODO 4: Read a char from the uart and assign it to 'ch'."
if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)
{
ch = huart1.Instance->RDR & 0xff;
}
else
{
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) != RESET)
{
__HAL_UART_CLEAR_OREFLAG(&huart1);
}
rt_thread_mdelay(10);
}
return ch;
}
#endif /* RT_USING_FINSH */
3.3 配置TICK
在SysTick_Handler函数中调用rt_os_tick_callback()
4 测试
编译和下载代码,串口如果能打印如下log,说明移植成功。
输入如下命令:
help
输入ps命令,查看系统的线程信息