记录代码移植过程,成功一步记录一步

第一步:建立裸机程序

使用STM32CubeMx建立一个裸机程序



生成MDK5工程

第二步:参考0-bare-metal完成board.c、board.h文件



在Drivers组下添加board.c、board.h文件
添加board.c文件
实现board.c里面关于关于时钟配置、串口初始化、GPIO初始化等函数
void bsp_uart_init(void) { MX_USART1_UART_Init(); } void bsp_uart_send(char c)
{ while ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE) == RESET));
huart1.Instance->DR = c; } void bsp_led_init(void) { MX_GPIO_Init(); } void
bsp_led_on(void) { HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin, GPIO_PIN_RESET); }
void bsp_led_off(void) { HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,
GPIO_PIN_SET); } void rt_hw_board_init() { /* HAL_Init() function is called at
the beginning of program after reset and before * the clock configuration. */
HAL_Init(); /* Clock Config: * System Clock : 80M * HCLK : 80M * PCLK1 : 80M *
PCLK2 : 80M * SDMMC1 : 48M * USART1 : PCLK2 */ SystemClock_Config();
bsp_led_init(); bsp_uart_init(); }
void SystemClock_Config(void)

void _Error_Handler(char *file, int line)

以上两个函数采用cubemx工具生成的函数,main函数和例程中一样

现象:



第三步:添加RT-Thread源码

拷贝RT-Thread源代码到工程路径下,当然也可以不移动,就是指定路径的时候长一点,没关系


添加两个新组一个叫做kernel,防止内核代码,另一个叫做CROTEX-M3放置平台相关代码,我用的是STM32F103ZET6使用的是crotex-m3内核。

添加相关文件到对应的组下面,添加完如图,对了还有一个rtconfig.h文件,用于配置和裁剪内核。









添加代码之后别忘了添加头文件,rtconfig.h文件放在了工程的根目录之下,别忘了添加头文件。

在编译之后有了有符号重定义,注释掉原有的函数
在编译之后有了有符号重定义,注释掉原有的函数 //void HardFault_Handler(void) //{ // /* USER CODE
BEGIN HardFault_IRQn 0 */ // /* USER CODE END HardFault_IRQn 0 */ // while (1)
// { // /* USER CODE BEGIN W1_HardFault_IRQn 0 */ // /* USER CODE END
W1_HardFault_IRQn 0 */ // } // /* USER CODE BEGIN HardFault_IRQn 1 */ // /*
USER CODE END HardFault_IRQn 1 */ //} //void PendSV_Handler(void) //{ // /*
USER CODE BEGIN PendSV_IRQn 0 */ // /* USER CODE END PendSV_IRQn 0 */ // /*
USER CODE BEGIN PendSV_IRQn 1 */ // /* USER CODE END PendSV_IRQn 1 */ //}
编译下载正常运行

第四步:console移植,实现控制台输出功能

实现函数
void rt_hw_console_output(const char *str) { RT_ASSERT(str != RT_NULL); while
(*str != '\0') { if (*str == '\n') { bsp_uart_send('\r'); }
bsp_uart_send(*str++); } }
这个函数主要是实现bsp_usart_send,此函数在第二步已经实现。

接下来修改SysTick_Handler函数
/** * @brief This function handles System tick timer. */ void
SysTick_Handler(void) { rt_interrupt_enter(); rt_tick_increase();
rt_interrupt_leave(); }
注意包含rtthread.h头文件

修改main函数如下
int main(void) { while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */
rt_kprintf("led on\n"); rt_thread_delay(RT_TICK_PER_SECOND); rt_kprintf("led
off\n"); rt_thread_delay(RT_TICK_PER_SECOND); } /* USER CODE END 3 */ }
编译下载输出如图



第五步:内存堆配置,实现动态内存管理功能

在rt_config.h中添加宏
//#define RT_USING_NOHEAP #define RT_USING_SMALL_MEM #define RT_USING_HEAP
注意:注释掉RT_USING_NOHEAP,如果有的话

在rt_hw_board_init函数中添加动态内存管理初始化函数
void rt_hw_board_init() { static uint8_t heap_buf[10 * 1024]; ……….
rt_system_heap_init(heap_buf, heap_buf + sizeof(heap_buf) - 1); }
在main函数中初始化一个线程函数
#define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 512 #define
THREAD_TIMESLICE 5 void test_thread_entry(void *parameter) { while (1) {
rt_kprintf("enter test thread\n"); rt_thread_delay(RT_TICK_PER_SECOND); } } /**
* @brief The application entry point. * * @retval None */ int main(void) {
rt_thread_t tid; tid = rt_thread_create("test", test_thread_entry, RT_NULL,
THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid != RT_NULL) {
rt_thread_startup(tid); return 0; } else { return -1; } }
编译下载,输出如图



第六步:实现Finsh Shell功能

将components组件文件夹下的drivers和finsh文件添加到工程

新建finsh组和DeviceDrivers组,添加文件



 

在前几步添加文件的时候在Kernel组莫名少添加了device.c文件在调试的时候浪费很长时间,

在官方的1-basic的rt-thread\src文件下也没有,感受到来自NPC的调戏。

添加代码之后先修改board.c文件里的rt_hw_board_init函数,
/** * This function will initial STM32 board. */ void rt_hw_board_init() {
static uint8_t heap_buf[10 * 1024]; /* HAL_Init() function is called at the
beginning of program after reset and before * the clock configuration. */
HAL_Init(); /* Clock Config: * System Clock : 80M * HCLK : 80M * PCLK1 : 80M *
PCLK2 : 80M * SDMMC1 : 48M * USART1 : PCLK2 */ SystemClock_Config(); /*
Configure the Systick interrupt time */
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND); /* Configure
the Systick */ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /*
SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0,
0); //bsp_led_init(); stm32_hw_usart_init(); #ifdef RT_USING_CONSOLE
rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #endif #ifdef RT_USING_HEAP
rt_system_heap_init(heap_buf, heap_buf + sizeof(heap_buf) - 1); #endif #ifdef
RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif }
stm32_hw_usart_init();

用来初始化并注册串口

屏蔽掉board.c文件里面串口初始化函数、串口发送函数、控制台输出函数,工作交给drv_usart.c。

接下来修改rtconfig.h中的宏定义

添加#define BSP_USING_UART1等

添加后rtconfig.h如下
#ifndef RT_CONFIG_H__ #define RT_CONFIG_H__ /* Automatically generated file;
DO NOT EDIT. */ /* RT-Thread Configuration */ /* RT-Thread Kernel */ #define
RT_NAME_MAX 8 #define RT_ALIGN_SIZE 4 #define RT_THREAD_PRIORITY_32 #define
RT_THREAD_PRIORITY_MAX 32 #define RT_TICK_PER_SECOND 1000 #define
RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_IDEL_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 256 #define RT_DEBUG /* Inter-Thread
communication */ #define RT_USING_SEMAPHORE #define RT_USING_MUTEX #define
RT_USING_EVENT #define RT_USING_MAILBOX #define RT_USING_MESSAGEQUEUE /* Memory
Management */ //#define RT_USING_NOHEAP #define RT_USING_SMALL_MEM #define
RT_USING_HEAP /* Kernel Device Object */ #define RT_USING_DEVICE #define
RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 #define RT_CONSOLE_DEVICE_NAME
"uart1" /* RT-Thread Components */ #define RT_USING_COMPONENTS_INIT #define
RT_USING_USER_MAIN #define RT_MAIN_THREAD_STACK_SIZE 2048 #define
RT_MAIN_THREAD_PRIORITY 10 /* C++ features */ /* Command shell */ #define
RT_USING_FINSH #define FINSH_THREAD_NAME "tshell" #define FINSH_USING_HISTORY
#define FINSH_HISTORY_LINES 5 #define FINSH_USING_SYMTAB #define
FINSH_USING_DESCRIPTION #define FINSH_THREAD_PRIORITY 20 #define
FINSH_THREAD_STACK_SIZE 4096 #define FINSH_CMD_SIZE 80 #define FINSH_USING_MSH
#define FINSH_USING_MSH_DEFAULT #define FINSH_ARG_MAX 10 /* Device virtual file
system */ /* Device Drivers */ #define RT_USING_DEVICE_IPC #define
RT_PIPE_BUFSZ 512 #define RT_USING_SERIAL /* Env config */ #define
SYS_PKGS_DOWNLOAD_ACCELERATE #define BSP_USING_UART1 #endif
之前mian函数中的初始化函数去掉

编译下载如图



出了问题,finsh没有跑起来,没有msh>,重启、没有、重启、还没有

调试了很久还是不行,之后经大神指点在rtdef.h文件如图位置添加了RT_USED



编译下载,还是没有,不过这次是因为串口接收引脚模式配置错误,修改之后编译下载运行,



成功运行,但是为什么要加RT_USED,还是不知道。

以上

对了,这种移植模式值得吐槽,希望以后官方可以更加人性化一点

这里可以下载移植好的程序
<https://www.rt-thread.org/qa/forum.php?mod=viewthread&tid=7794&page=1&extra=#pid37101>


https://www.rt-thread.org/qa/forum.php?mod=viewthread&tid=7794&page=1&extra=#pid37101

<https://www.rt-thread.org/qa/forum.php?mod=viewthread&tid=7794&page=1&extra=#pid37101>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信