一、FreeRTOS介绍
1、FreeRTOS主要特点
(1)、支持抢占式调度,合作式调度和时间片调度;
(2)、高效的软件定时器;
(3)、开源免费;
(4)、支持多种系统架构;
(5)、任务数量不限等等;
2、FreeRTOS命令规则
(1)、变量
uint32_t定义的变量都加前缀ul,u -- unsigned l -- long;
uint16_t定义的变量都加前缀us,u -- unsigned s -- short;
uint8_t定义的变量都加前缀uc, u -- unsigned c -- char;
size_t定义的变量加上前缀ux;
枚举变量会加上前缀e;
指针变量加上前缀p,uint16_t定义的指针变量加上pus;
(2)、函数
static声明的函数,定义时加上前缀prv(private的缩写);
带返回值的函数,根据返回值的类型,加上响应前缀,void前缀加上v;
文件中的函数名也包含文件名;
3、FreeRTOS中的数据类型
(1)、TickType_t
如果定义了configUSE_16_BIT_TICKS,TickType_t为16位无符号,否则为32位无符号,因此,对于32位处理器来说,此宏必须为0。
(2)、BaseType_t (与系统架构有关,此类型定义的是有符号数)
(3)、UBaseType_t(BaseType_t的无符号版本)
(4)、StackType_t(栈变量数据类型)
二、FreeRTOS配置文件(FreeRTOSConfig —— 系统裁剪)
1、基本配置
(1)、configUSE_PREEMPTION:抢占式调度器师使能(1:抢占式调度器 0:合作式调度器);
(2)、configUSE_PORT_OPTIMISED_TASK_SELECTION:优化列表中要执行的最高优先级任务的算法(1:专用方式 0:通用方式);
(3)、configUSE_TICKLESS_IDLE:tickless低功耗模式使能;
(4)、configCPU_CLOCK_HZ:定义SOC主频;
(5)、configTICK_RATE_HZ:定义系统时钟节拍数,单位HZ,一般为1000HZ;
(6)、configMAX_PRIORITIES:定义用户可使用的最大优先级数;
(7)、configMINIMAL_STACK_SIZE:定义空闲任务的栈大小;
(8)、configTOTAL_HEAP_SIZE:定义堆大小,任务创建,消息队列创建等都需要;
(9)、configMAX_TASK_NAME_LEN:任务名最大字符数;
(10)、configUSE_16_BIT_TICKS:TickType_t类型含义, 1:16位架构处理器 0:32位架构处理器;
(11)、configIDLE_SHOULD_YIELD:建议配置为0;
(12)、configUSE_TASK_NOTIFICATIONS: 1:使能任务间直接的消息传递 0:失能;
(13)、configUSE_MUTEXES: 1:使能互斥信号量 0:失能互斥信号量;
(14)、configUSE_RECURSIVE_MUTEXES: 1:使能递归互斥信号量 0:失能递归互斥信号量;
(15)、configUSE_COUNTING_SEMAPHORES: 1:使能计数信号量 0:失能计数信号量;
(16)、configQUEUE_REGISTRY_SIZE: 设置可以注册的信号量和消息队列个数;
(17)、configUSE_QUEUE_SETS: 1:使能消息队列 0:失能消息队列;
(18)、configUSE_TIME_SLICING: 1:使能时间片调度 0:失能时间片调度;
2、钩子函数
(1)、configUSE_IDLE_HOOK: 1:使能空闲任务的钩子函数 0:失能空闲任务钩子函数;
(2)、configUSE_MALLOC_FAILED_HOOK: 1:使能动态内存申请失败的钩子函数 0:失能;
(3)、configUSE_TICK_HOOK: 1:使能滴答定时器中断的钩子函数;
3、合作式任务配置
(1)、configUSE_CO_ROUTINES: 1:使能合作式调度相关函数 0:失能合作式调用相关函数;
(2)、configMAX_CO_ROUTINE_PRIORITIES:最大的合作式任务优先级数;
4、软件定时器配置
(1)、configUSE_TIMERS: 1:使能软件定时器 0:失能软件定时器;
(2)、configTIMER_TASK_PRIORITY:软件定时器任务的优先级;
(3)、configTIMER_QUEUE_LENGTH:软件定时器命令队列的长度;
(4)、configTIMER_TASK_STACK_DEPTH:软件定时器任务的栈空间大小;
5、内核配置
(1)、configPRIO_BITS:stm32f103/407/429等都是4;
(2)、configLIBRARY_LOWEST_INIERRUPT_PRIORITY:0-15,建议配置中断最低优先级15,;
(3)、configLIBRARY_MAX_SYSCALL_INIERRUPT_PRIORITY:系统可管理的最高优先级中断;
(4)、configKERNEL_INTERRUPT_PRIORITY
(5)、configMAX_SYSCALL_INTERRUPT_PRIORITY
6、INCLUDE配置
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1
三、FreeRTOS任务管理
1、任务状态(运行态,就绪态,阻塞态,挂起态)
2、系统启动vTaskStartScheduler()
启动FreeRTOS调度器,即启动多任务运行。
3、任务创建xTaskCreate()
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, /* 任务函数 */
const char * const pcName, /* 任务名 */
unsigned short usStackDepth, /* 任务栈大小,单位 word,也就是 4 字节 */
void *pvParameters, /* 任务参数 */
UBaseType_t uxPriority, /* 任务优先级 */
TaskHandle_t *pvCreatedTask /* 任务句柄 */
);
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "croutine.h"
#define TASK_PRIO_START 1
#define TASK_START_STK_SIZE (1 * 256)
TaskHandle_t start_handler;
static void start_task(void *arg)
{
while(1)
{
vTaskDelay(500);
}
}
int main(void)
{
xTaskCreate(start_task,
"start_task",
TASK_START_STK_SIZE,
NULL,
TASK_PRIO_START,
&start_handler);
vTaskStartScheduler();
}
4、任务删除vTaskDelete()
void vTaskDelete( TaskHandle_t xTaskToDelete )
必须配置#define INCLUDE_vTaskDelete 1
5、任务挂起vTaskSuspend()
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
必须配置#define INCLUDE_vTaskSuspend 1
6、任务恢复vTaskResume()
void vTaskResume( TaskHandle_t xTaskToResume )
必须配置#define INCLUDE_vTaskResume 1
7、任务恢复中断方式xTaskResumeFromISR()
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
必须配置#define INCLUDE_vTaskResumeFromISR 1
8、空闲任务(低功耗时,在空闲任务中实现睡眠)
四、临界段和开关中断
1、临界段
不允许中断打断,进入临界区前必须关中断,退出临界区后开中断。UCOS有临界区,RTX没有。
2、临界段处理(开关中断)
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
开关中断就是对计数uxCriticalNesting变量操作,进入临界区,变量+1,退出临界区,变量-1。
3、中断临界段
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
五、FreeRTOS时间管理
1、任务等待vTaskDelay()
void vTaskDelay( const TickType_t xTicksToDelay )
延时等待范围:1-0xFFFFFFFF
作用:任务切换
其他几个任务延时函数个人没怎么使用,故不介绍了。
六、FreeRTOS消息队列
消息传递的是数据的复制,RTX/UCOS传递的是数据的地址。
1、消息队列创建xQueueCreate()
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, /* 消息个数 */
UBaseType_t uxItemSize ); /* 每个消息大小,单位字节 */
返回消息队列句柄。
2、消息队列发送xQueueSend()
BaseType_t xQueueSend(
QueueHandle_t xQueue, /* 消息队列句柄 */
const void * pvItemToQueue, /* 要传递数据地址 */
TickType_t xTicksToWait /* 等待消息队列有空间的最大等待时间 */
);
3、消息队列从中断发送xQueueSendFromISR()
BaseType_t xQueueSendFromISR(
QueueHandle_t xQueue, /* 消息队列句柄 */
const void * pvItemToQueue, /* 要传递数据地址 */
TickType_t xTicksToWait /* 等待消息队列有空间的最大等待时间 */
);
4、消息队列接收xQueueReceive() xQueueReceiveFromISR
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )
BaseType_t xQueueReceive(
QueueHandle_t xQueue, /* 消息队列句柄 */
void *pvBuffer, /* 接收消息队列数据的缓冲地址 */
TickType_t xTicksToWait /* 等待消息队列有数据的最大等待时间 */
);
七、FreeRTOS事件标志组(任务间同步)
1、事件标志组创建xEventGroupCreate()
EventGroupHandle_t xEventGroupCreate( void );
返回事件标志组句柄。
必须定义:
#define INCLUDE_xEventGroupSetBitFromISR 1
#define configUSE_TIMERS 1
#define INCLUDE_xTimerPendFunctionCall 12、时间标志组设置xEventGroupSetBits()
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */
const EventBits_t uxBitsToSet ); /* 事件标志位设置 */
BaseType_t xEventGroupSetBitsFromISR(EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */
const EventBits_t uxBitsToSet, /* 事件标志位设置 */
BaseType_t *pxHigherPriorityTaskWoken ); /* 高优先级任务是否被唤醒的状态保存 */
第二个参数表示24个可设置的时间标志位,返回当前的事件标志组数值。中断中使用xEventGroupSetBitsFromISR()。
3、事件标志组获取xEventGroupWaitBits()
EventBits_t xEventGroupWaitBits(const EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */
const EventBits_t uxBitsToWaitFor, /* 等待被设置的事件标志位 */
const BaseType_t xClearOnExit, /* 选择是否清零被置位的事件标志位 */
const BaseType_t xWaitForAllBits, /* 选择是否等待所有标志位都被设置 */
TickType_t xTicksToWait ); /* 设置等待时间 */
// STM32F10X FreeRTOSConfig举例
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "type.h"
/***************************************************************************************************************/
/* FreeRTOS基础配置配置选项 */
/***************************************************************************************************************/
#define configUSE_PREEMPTION 1 // 1使用抢占式内核,0使用协程
#define configUSE_TIME_SLICING 1 // 1使能时间片调度(默认式使能的)
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 // 1启用特殊方法来选择下一个要运行的任务
// 一般是硬件计算前导零指令,如果所使用的
// MCU没有这些硬件指令的话此宏应该设置为0!
#define configUSE_TICKLESS_IDLE 0 // 1启用低功耗tickless模式
#define configUSE_QUEUE_SETS 1 // 为1时启用队列
#define configCPU_CLOCK_HZ 72000000 // CPU频率
#define configTICK_RATE_HZ (1000) // 时钟节拍频率,这里设置为1000,周期就是1ms
#define configMAX_PRIORITIES (32) // 可使用的最大优先级
#define configMINIMAL_STACK_SIZE ((unsigned short)130) // 空闲任务使用的堆栈大小
#define configMAX_TASK_NAME_LEN (20) // 任务名字字符串长度
#define configUSE_16_BIT_TICKS 0 // 系统节拍计数器变量数据类型,
// 1表示为16位无符号整形,0表示为32位无符号整形
#define configIDLE_SHOULD_YIELD 1 // 为1时空闲任务放弃CPU使用权给其他同优先级的用户任务
#define configUSE_TASK_NOTIFICATIONS 1 // 为1时开启任务通知功能,默认开启
#define configUSE_MUTEXES 1 // 为1时使用互斥信号量
#define configQUEUE_REGISTRY_SIZE 8 // 不为0时表示启用队列记录,具体的值是可以
// 记录的队列和信号量最大数目。
#define configCHECK_FOR_STACK_OVERFLOW 0 // 大于0时启用堆栈溢出检测功能,如果使用此功能
// 用户必须提供一个栈溢出钩子函数,如果使用的话
// 此值可以为1或者2,因为有两种栈溢出检测方法。
#define configUSE_RECURSIVE_MUTEXES 1 // 为1时使用递归互斥信号量
#define configUSE_MALLOC_FAILED_HOOK 0 // 1使用内存申请失败钩子函数
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1 // 为1时使用计数信号量
/***************************************************************************************************************/
/* FreeRTOS与内存申请有关配置选项 */
/***************************************************************************************************************/
#define configSUPPORT_DYNAMIC_ALLOCATION 1 // 支持动态内存申请
#define configTOTAL_HEAP_SIZE ((size_t)(20*1024)) // 系统所有总的堆大小
/***************************************************************************************************************/
/* FreeRTOS与钩子函数有关的配置选项 */
/***************************************************************************************************************/
#define configUSE_IDLE_HOOK 0 // 1,使用空闲钩子;0,不使用
#define configUSE_TICK_HOOK 0 // 1,使用时间片钩子;0,不使用
/***************************************************************************************************************/
/* FreeRTOS与协程有关的配置选项 */
/***************************************************************************************************************/
#define configUSE_CO_ROUTINES 0 // 为1时启用协程,启用协程以后必须添加文件croutine.c
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) // 协程的有效优先级数目
/***************************************************************************************************************/
/* FreeRTOS与软件定时器有关的配置选项 */
/***************************************************************************************************************/
#define configUSE_TIMERS 1 // 为1时启用软件定时器
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) // 软件定时器优先级
#define configTIMER_QUEUE_LENGTH 5 // 软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) // 软件定时器任务堆栈大小
/***************************************************************************************************************/
/* FreeRTOS可选函数配置选项 */
/***************************************************************************************************************/
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTimerPendFunctionCall 1
/***************************************************************************************************************/
/* FreeRTOS与中断有关的配置选项 */
/***************************************************************************************************************/
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 // 中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 // 系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/***************************************************************************************************************/
/* FreeRTOS与中断服务函数有关的配置选项 */
/***************************************************************************************************************/
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#endif /* FREERTOS_CONFIG_H */