移植FreeRTOS
下载源码包
去官网下载库文件
FreeRTOS™ - FreeRTOS™
复制需要使用的源代码文件
-
复制所有.c文件
-
复制include中所有.h文件
-
protable中的兼容文件
这里使用的是KEIL开发的
这里的打开Keil是一个文本,指向的RVDS中文件
MemMang选择的heap4版本
复制一个芯片的操作系统的裁剪文件
复制FreeRTOSConfig.h文件
freeRTOS运行原理
运用中断
- SysTick(系统定时器中断)
- 作用:产生系统时钟节拍(Tick),是 FreeRTOS 的 “心跳”
- 频率:默认 1ms 一次(可配置)
- 工作:每次中断触发时间片轮询、超时检查、延时到期
- 触发点:定时到 → 进入
SysTick_Handler()
- SVC(系统调用中断)
- 指令:
SVC #0
- 作用:启动第一个任务(从无调度 → 进入第一个任务)
- 特点:只在系统启动时调用 1 次
- 触发点:
vTaskStartScheduler() 里会触发 SVC
- PendSV(可挂起系统调用中断)
- 作用:任务上下文切换(任务切换的真正执行者)
- 特点:最低优先级中断,确保所有硬件中断处理完才切换任务
- 触发点:需要切换任务时,软件置位 PendSV 请求 → 进入
PendSV_Handler()
通过使用freeRTOS中定义的函数,实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
启动 → vTaskStartScheduler()
↓
初始化硬件、空闲任务
↓
触发 SVC 中断
↓
SVC_Handler 启动第一个任务
↓
系统正常运行
↓
SysTick 定时触发(1ms)
↓
检查是否需要切换任务
↓
需要切换 → 挂起 PendSV
↓
PendSV_Handler 执行上下文切换
↓
运行下一个任务
循环
|
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
|
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
vPortSVCHandler();
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
xPortPendSVHandler();
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
//手动调用系统滴答处理函数
if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
//判断调度器是否已经启动,只有在调度器启动后才调用系统滴答处理函数
xPortSysTickHandler();
}
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
|
问题
configTICK_TYPE_WIDTH_IN_BITS 设置为不支持的时钟节拍类型位宽。
Cortex‑M3 推荐 32 位
去FreeRTOSConfig.h中找
1
|
#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITS //改为32
|
ucHeap (在 heap_4.o 中被引用)
搜索ucHeap
再去FreeRTOSConfig.h找
1
2
|
/* 启用动态内存分配(必须为1,heap_4依赖此宏) */
#define configSUPPORT_DYNAMIC_ALLOCATION 1
|
使用
创建任务
1
2
3
4
5
6
|
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, //任务入口函数指针
const char * const pcName, //自己定义个名字 任务名字
const configSTACK_DEPTH_TYPE uxStackDepth, //任务堆栈深度
void * const pvParameters, //任务函数参数
UBaseType_t uxPriority, //任务优先级
TaskHandle_t * const pxCreatedTask ) //任务句柄 用来操控任务
|
1
|
typedef void (* TaskFunction_t)( void * arg ); //定义任务入口函数指针类型
|
启用任务调度器