一、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      1

2、时间标志组设置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 */




Logo

开源、云原生的融合云平台

更多推荐