笔记:FreeRTOS要点总结
- 格式:pdf
- 大小:180.69 KB
- 文档页数:5
笔记:FreeRTOS要点总结
⼀、基本配置
1.1 数据类型
FreeRTOS 使⽤的数据类型主要分为 stdint.h ⽂件中定义的和⾃⼰定义的两种
FreeRTOS 主要⾃定义了以下四种数据类型:
TickType_t----32 位⽆符号数( 32位MCU,配置configUSE_16_BIT_TICKS = 0)
BaseType_t----32 位有符号数(32位MCU)
UBaseType_t---32 位⽆符号数(BaseType_t类型⽆符号版本)
StackType_t----32 位变量(栈变量数据类型定义,32位MCU)
1.2 代码风格变量
uint32_t 定义的变量都加上前缀 ul。u 代表 unsigned ⽆符号,l 代表 long 长整型。
uint16_t 定义的变量都加上前缀 us。u 代表 unsigned ⽆符号,s 代表 short 短整型。
uint8_t 定义的变量都加上前缀 uc。u 代表 unsigned ⽆符号,c 代表 char 字符型。
stdint.h ⽂件中未定义的变量类型,在定义变量时需要加上前缀 x,⽐如 BaseType_t 和
TickType_t 定义的变量。
stdint.h ⽂件中未定义的⽆符号变量类型,在定义变量时要加上前缀 u,⽐如 UBaseType_t 定义
的变量要加上前缀 ux。
size_t 定义的变量也要加上前缀 ux。
枚举变量会加上前缀 e。
指针变量会加上前缀 p,⽐如 uint16_t 定义的指针变量会加上前缀 pus。
根据 MISRA 代码规则,char 定义的变量只能⽤于 ASCII 字符,前缀使⽤ c。
根据 MISRA 代码规则,char *定义的指针变量只能⽤于 ASCII 字符串,前缀使⽤ pc。函数
加上了 static 声明的函数,定义时要加上前缀 prv,这个是单词 private 的缩写。
带有返回值的函数,根据返回值的数据类型,加上相应的前缀,如果没有返回值,即 void 类型
,函数的前缀加上字母 v。
根据⽂件名,⽂件中相应的函数定义时也将⽂件名加到函数命名中,⽐如 tasks.c ⽂件中函数
vTaskDelete,函数中的 task 就是⽂件名中的 task。宏定义
根据宏定义所在的⽂件,⽂件中的宏定义声明时也将⽂件名加到宏定义中,⽐如宏定义
configUSE_PREEMPTION 是定义在⽂件 FreeRTOSConfig.h ⾥⾯。宏定义中的 config 就是⽂
件名中的 config。另外注意,前缀要⼩写。
除了前缀,其余部分全部⼤写,同时⽤下划线分开。排版和注释
缩进
Tab 制表符⽤于缩进,Tab ⼀次缩进 4 个字符空间。
注释
FreeRTOS 中注释不会超过 80 个字符宽度,除⾮对函数的参数进⾏注释时。源码中主要是采⽤/* */
的形式进⾏注释,不采⽤ C++中的双斜杠风格来注释。
1.3 关键配置
configCPU_CLOCK_HZ---配置MCU主频,单位Hz
configTICK_RATE_HZ---配置系统时钟节拍数,单位 Hz
configMAX_PRIORITIES---配置⽤户可⽤最⼤优先级数,0~configMAX_PRIORITIES-1
configTOTAL_HEAP_SIZE---配置堆⼤⼩
configUSE_TASK_NOTIFICATIONS---配置任务通知
configUSE_TIME_SLICING---配置时间⽚轮转调度
configLIBRARY_LOWEST_INTERRUPT_PRIORITY---受RTOS管理的最⼩中断优先级
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY---受RTOS管理的最⼤中断优先级
⼆、任务管理
2.1 任务栈
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 17 * 1024 ) )
1,局部变量,函数调⽤时的现场保护和返回地址,函数的形参,进⼊中断函数前和中断嵌套等都需要栈空间,栈空间定义⼩了会造成系统崩溃
2,实际分配的栈⼤⼩可以在最⼩栈需求的基础上乘以⼀个安全系数,⼀般取 1.5-2
3,栈⽣长⽅向从⾼地址向低地址⽣长(M4 和 M3 是这种⽅式)
2.2 系统栈
任务栈不使⽤系统栈控件,中断函数和中断嵌套使⽤
Cortex-M3 和 M4 内核具有双堆栈指针,MSP 主堆栈指针和 PSP 进程堆栈指针
在 FreeRTOS 操作系统中,主堆栈指针 MSP 是给系统栈空间使⽤的,进
程堆栈指针 PSP 是给任务栈使⽤的 对于 Cortex-M3 内核和未使⽤ FPU(浮点运算单元)功能的 Cortex-M4 内核,需要64字节
对于具有 FPU(浮点运算单元)功能的 Cortex-M4 内核,需要200字节
2.3 任务优先级
1. FreeRTOS 中任务的最⾼优先级是通过 FreeRTOSConfig.h ⽂件中的 configMAX_PRIORITIES 进⾏配置的,⽤户实际可以使⽤的优先级范围是 0 到
configMAX_PRIORITIES – 1
2. ⽤户配置任务的优先级数值越⼩,那么此任务的优先级越低,空闲任务的优先级是 0
3. 建议⽤户配置宏定义 configMAX_PRIORITIES 的最⼤值不要超过 32
4. FreeRTOS 中处于运⾏状态的任务永远是当前能够运⾏的最⾼优先级任务
2.3.1 任务优先级分配
1. IRQ 任务:IRQ 任务是指通过中断服务程序进⾏触发的任务,此类任务应该设置为所有任务⾥⾯优先级最⾼的
2. ⾼优先级后台任务:⽐如按键检测,触摸检测,USB 消息处理,串⼝消息处理等,都可以归为这⼀类任务 低优先级的时间⽚调度任务:⽐如 emWin 的界⾯显
⽰,LED 数码管的显⽰等不需要实时执⾏的都可以归为这⼀类任务
实际应⽤中⽤户不必拘泥于将这些任务都设置为优先级 1 的同优先级任务,可以设置多个优先级,只需注意这类任务不需要⾼实时性
3. 空闲任务:空闲任务是系统任务
4. 特别注意:IRQ 任务和⾼优先级任务必须设置为阻塞式(调⽤消息等待或者延迟等函数即可), 只有这样,⾼优先级任务才会释放 CPU 的使⽤权,,从⽽低优先级
任务才有机会得到执⾏
2.3.2 中断优先级与任务优先级中断的优先级永远⾼于任何任务的优先级,即任务在执⾏的过程中,中断来了就开始执⾏中断服务程序
对于 STM32F103,F407 和 F429 来说,中断优先级的数值越⼩,优先级越⾼。⽽ FreeRTOS的任务优先级是,任务优先级数值越⼩,任务优先级越低
2.3.2 任务调度
2.2.3 相关API
vTaskStartScheduler-任务启动空闲任务和可选的定时器任务是在调⽤这个函数后⾃动创建
正常情况下这个函数是不会返回的,运⾏到这⾥极有可能是⽤于定时器任务或者空闲任务的 heap 空 间不⾜造成创建失败,此时需要加⼤
FreeRTOSConfig.h ⽂件中定义的 heap ⼤⼩
如果在此类任务函数⾥⾯填的任务 ID 是 NULL,即数值 0 的话,那么执⾏⽣效的就是当前正在执⾏的任务
系统框架写法
int main(void)
{
/* 初始化外设 */
xTaskCreate(); /* 创建开始任务 */
vTaskStartScheduler(); /* 开启任务调度 */
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* */进⼊临界区
xTaskCreate(); /* 创建任务 1 */
xTaskCreate(); /* 创建任务 2 */
xTaskCreate(); /* 创建任务 3 */
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
任务创建、挂起、删除
/* 相关配置 */
#define configSUPPORT_DYNAMIC_ALLOCATION 1 /* ⽀持动态内存申请 */
//#define configSUPPORT_STATIC_ALLOCATION 1 /* ⽀持静态内存申请 */
#define configTOTAL_HEAP_SIZE ((size_t)(20*1024)) /* 系统所有总的堆⼤⼩,heap_x.h需要,动态申请 */
/* 任务创建 */
/* 任务创建宏定义,便于修改 */
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 256 /* 任务堆栈⼤⼩ */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 */
/* 任务创建函数 */
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈⼤⼩ */
(void* )NULL, /* 传递给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
/* 任务挂起 */
vTaskSuspend(Task1Task_Handler);
/* 任务内解挂 */
vTaskResume(Task1Task_Handler);
/* 中断内解挂 */