RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用于家电、消费电子、医疗设备、工控等领域大量使用的 32 位 ARM 入门级 MCU 的场合。
下图是 RT-Thread Nano 的软件框图,包含支持的 CPU 架构与内核源码,还有可拆卸的 FinSH 组件:
在 Nano 上添加 UART 控制台(实现打印)在 RT-Thread Nano 上添加 UART 控制台打印功能后,就可以在代码中使用 RT-Thread 提供的打印函数 rt_kprintf() 进行信息打印,从而获取自定义的打印信息,方便定位代码 bug 或者获取系统当前运行状态等。实现控制台打印(需要确认 rtconfig.h 中已使能 RT_USING_CONSOLE 宏定义),需要完成基本的硬件初始化,以及对接一个系统输出字符的函数,本小节将详细说明。
实现串口初始化
使用串口对接控制台的打印,首先需要初始化串口,如引脚、波特率等。 初始化的串口函数 uart_init() 有以下两种调用方式,二选一:
1. 方法一:默认使用宏 INIT_BOARD_EXPORT() 进行自动初始化,不需要显式调用,如下所示。
2. 方法二:可以使用显式调用:uart_init() 需要在 board.c 中的 rt_hw_board_init() 函数中调用。
示例代码:如下是基于 HAL 库的 STM32F103 串口驱动,完成添加控制台的示例代码,仅做参考。
static UART_HandleTypeDef UartHandle; static int uart_init(void) {
/* 初始化串口参数,如波特率、停止位等等 */
UartHandle.Instance = USART1;
UartHandle.Init.BaudRate = 115200;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE; /* 初始化串口引脚等 */
if (HAL_UART_Init(&UartHandle) != HAL_OK)
{
while(1);
}
return 0;
}
INIT_BOARD_EXPORT(uart_init);
/* 默认选择初始化方法一:使用宏 INIT_BOARD_EXPORT 进行自动初始化 */
/* board.c */
初始化方法二:可以选择在 rt_hw_board_init 函数中直接调用 串口初始化 函 数 */
void rt_hw_board_init(void) {
....
uart_init(); /*
....
}
实现 rt_hw_console_output实现 finsh 组件输出一个字符,即在该函数中实现 uart 输出字符:
/* 实现 2:输出一个字符,系统函数,函数名不可更改 */
void rt_hw_console_output(const char *str);
void rt_hw_console_output(const char *str)
{
rt_size_t i = 0, size = 0;
char a = '\r';
__HAL_UNLOCK(&UartHandle);
size = rt_strlen(str);
for (i = 0; i < size; i++)
{
if (*(str + i) == '\n')
{
HAL_UART_Transmit(&UartHandle, (uint8_t *)&a, 1, 1);
}
HAL_UART_Transmit(&UartHandle, (uint8_t *)(str + i), 1, 1);
}
}
结果验证在应用代码中编写含有 rt_kprintf() 打印的代码,编译下载,打开串口助手进行验证。如下图是一个在 main() 函数中每隔 1 秒进行循环打印 Hello RT-Thread 的示例效果:
添加 FinSH 源码到工程在RTT官网下载finsh源码
将
cmd.c
msh.c
shell.c
finsh_port.c
添加到源码中
在rtconfig.c添加#define RT_USING_FINSH
实现 rt_hw_console_getchar要实现 FinSH 组件功能:既可以打印也能输入命令进行调试,控制台已经实现了打印功能,现在还需要在 board.c 中对接控制台输入函数,实现字符输入:
/* 实现 3:finsh 获取一个字符,系统函数,函数名不可更改 */ char rt_hw_console_getchar(void);
· rt_hw_console_getchar():控制台获取一个字符,即在该函数中实现 uart 获取字符,可以使用查询方式获取(注意不要死等,在未获取到字符时,需要让出 CPU),推荐使用中断方式获取。
示例代码:如下是基于 STM32F103 HAL 串口驱动对接的 rt_hw_console_getchar(),完成对接 FinSH 组件,其中获取字符采用查询方式,示例仅做参考,可自行实现中断方式获取字符。
char rt_hw_console_getchar(void)
{
int ch = -1;
if (__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_RXNE) != RESET)
{
ch = UartHandle.Instance->DR & 0xff;
}
Else
{
if(__HAL_UART_GET_FLAG(&UartHandle, UART_FLAG_ORE) != RESET)
{
__HAL_UART_CLEAR_OREFLAG(&UartHandle);
}
rt_thread_mdelay(10);
}
return ch;
}
编译下载代码,打开串口助手,可以在串口助手中打印输入 help 命令,回车查看系统支持的命令: