一、前言
初学RTThread,学会移植对RTThread形成初步理解有很大帮助
官方文档已经写的很清晰,也详细具体。RTThread NANO官方文档 - 使用MDK移植
此文章主要记录个人移植过程,学习到的经验,以及理清移植脉络。建议文章与官方文档配合使用
二、脉络概览
使用MDK添加NANO,内核源码已经为需要配置的步骤准备好了错误码,以提示用户
添加内核与控制台将会遇到以下错误码,用户需要注释或删除错误码,并且根据错误码配置相应函数
errror "TODO 1: OS Tick Configuration.
错误码1:配置RTThread系统节拍/心跳——void rt_hw_board_init(void)
error “TODO 2: Enable the hardware uart and config baudrate.”
错误码2:控制台输出串口初始化配置——static int uart_init(void)
error “TODO 3: Output the string ‘str’ through the uart.”
错误码3:控制台输出函数——void rt_hw_console_output(const char *str)
error “TODO 4: Read a char from the uart and assign it to ‘ch’.”
错误码4:控制台输入函数——RT_WEAK char rt_hw_console_getchar(void)
三、移植大致过程
基础工程准备
先添加Nano Pack。MDK内打开Pack Installer,找到 RealThread::RT-Thread并且安装。
1.添加NANO内核
Software Components - RTThread -Kernel
添加后找到以下函数,并且注释或者删除,避免RTThread接管后重复定义
HardFault_Handler()
PendSV_Handler()
SysTick_Handler()
此时编译,出现错误码1报错,跳转至错误码。
重新实现SysTick_Handler()
,并且添加SysTick_Config()
配置节拍
/* cortex-m 架构使用 SysTick_Handler() */
void SysTick_Handler()
{
rt_os_tick_callback();
}
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、用户自定义部分、时钟初始化 */
/* 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
}
至此,内核部分已移植成功,可以用户可以尝试调用内核函数。
2.添加UART控制台(实现控制台输出)
Software Components - RTThread -device
添加后在rtconfig.h中打开以下宏定义
# define RT_USING_DEVICE
# define RT_USING_CONSOLE
rtconfig.h使用了MDK的配置向导configuration Wizard 编写,可以很方便的对工程进行配置。
方法值得学习,可以日后尝试应用到自己项目
此时编译,出现错误码2,3,跳转至错误码。
错误码2:在static int uart_init(void)内添加用户的串口初始化函数即可。
错误码3:配置控制台输出函数
//--------------------------------------------------------------------HAL库
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, 1);
}
HAL_UART_Transmit(&huart1, (uint8_t *)(str + i), 1, 1);
}
}
//--------------------------------------------------------------------标准库
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';
size = rt_strlen(str);
for (i = 0; i < size; i++)
{
if (*(str + i) == '\n')
{
USART_SendData(USART1,a);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
USART_SendData(USART1,*(str+i));
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
}
至此,已经实现控制台输出,打开相应串口将会看见RTThread的信息输出
3.添加FinSH(实现控制台输入)
Software Components - RTThread -shell
添加后在rtconfig.h中打开
# include "finsh_config.h"
此时编译,出现错误码4,跳转至错误码。
错误码4:配置控制台输入函数
//--------------------------------------------------------------------HAL库
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->DR & 0xff;
}
else
{
if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) != RESET)
{
__HAL_UART_CLEAR_OREFLAG(&huart1);
}
rt_thread_mdelay(10);
}
return ch;
}
//--------------------------------------------------------------------标准库
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 (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)
{
ch = USART_ReceiveData(USART1);
}
else
{
if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
{
USART_ClearFlag(USART1,USART_FLAG_ORE);
}
rt_thread_mdelay(10);
}
return ch;
}
其他
引用连接在CSDN似乎跳转不到位置,可以右键-在新标签页打开链接