rt_thread_nano移植
本文最后更新于 2024年6月25日 早上
本文主要记录使用STM32cube创建的工程移植rt-thread-nano的过程,与官网不同,是直接导入文件的方式。
1. 对基础工程导入文件
1.1 基础工程
此工程由stm32cube生成,使用STM32F103ZE,功能为LED闪烁。
1.2 rt-thread-nano目录介绍
在官网有如下图,原文链接:
- bsp就是些示例工程文件,不用管,我们要使用自己的工程
- components是操作系统的上层组件,我们仅要移植最基本系统,也不管
- docs文档,也不是目标
- include存放头文件,目标之一
- libcpu移植CPU相关,目标之一
- src操作系统的源码,目标之一
1.3 将操作系统文件引入到基础工程中
- 点击manage project items,然后新建组Kernel和cpu
- 将操作系统src文件夹中的所以文件引入,如下图
- 根据芯片不同引入不同的libcpu文件,如我使用的是STM32F103ZE,keil工程,所以引入rtthread-nano\rt-thread\libcpu\arm\cortex-m3目标下的相关文件,如下图:
- 将操作系统中的include头文件目录添加到工程中
1.4 新建文件
- 新建文件rtconfig.h,该文件存放操作系统的配置宏
- 新建文件board.c,该文件主要实现时钟和板级初始化,下午将详细说明
1.5 此时的工程目录
2. 移植
首先移除stm32f1xx_it.c中的HardFault_Handler()和PendSV_Handler()函数,这两个函数已经被操作系统实现,会出现重复定义错误。
2.1 板级初始化与时钟初始化
在board.c中新建函数void rt_hw_board_init(),该函数将在rtthread_startup()函数中被调用,主要就是进行板级初始化和时钟初始化。
首先调用原本在main函数中执行的HAL库初始化函数HAL_Init(),当然移植到此处原本位置就应该删除。在board中需要添加头文件stm32f1xx_hal.h
然后将原本在main中实现的void SystemClock_Config(void)函数,移植到board中,在rt_hw_board_init函数中执行。
然后配置操作系统时钟,使用滴答定时器来作为系统时钟,SystemClock_Config(void),函数实现如下,其中RT_TICK_PER_SECOND则是需要定义在rtconfig.h中,表示每多少次系统节拍等于一分钟。
1
2
3
4
5
6void rt_hw_systick_init(void)
{
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
NVIC_SetPriority(SysTick_IRQn, 0xFF);
}还需要添加系统节拍中断服务程序SysTick_Handler(),该函数实际上就是在累加,然后删除生成文件中重复定义的此函数
1 |
|
最后添加对操作系统组件的初始化
1
2
3#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif此时的borad.c文件内容就如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67#include <rthw.h>
#include <stdint.h>
#include <rtthread.h>
#include "stm32f1xx_hal.h"
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
//Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
//Error_Handler();
}
}
void rt_hw_systick_init(void)
{
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
NVIC_SetPriority(SysTick_IRQn, 0xFF);
}
void rt_hw_board_init()
{
HAL_Init();
SystemClock_Config();
rt_hw_systick_init();
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
}
void SysTick_Handler(void)
{
/* enter interrupt */
rt_interrupt_enter();
HAL_IncTick();
rt_tick_increase();
/* leave interrupt */
rt_interrupt_leave();
}
2.2 配置文件rtconfig.h
直接从操作系统目录的bsp中复制过来作为基板。其实也没啥改的,使用默认即可。
1 |
|
2.3 main.c的修改
main函数是作为操作系统自动启动的一个线程,所以可以直接用。只需要修改延时函数,改为操作系统的rt_thread_mdelay。
1 |
|
直接编译,无错误,然后下载,现象和之前的应该时相同。
2.4 堆
如果需要创建动态的组件,那么需要实现堆的初始化,仍然在board.c 中的 rt_hw_board_init() 函数中完成,是否启用的宏定义在rtconfig.h中定义,RT_USING_HEAP ,默认不开启,所以上面就可以直接使用了。
需要添加的话,在rt_hw_board_init函数的操作系统组件初始化完成后进行
1 |
|
然后需要在board.c实现函数rt_heap_begin_get和rt_heap_end_get
1 |
|