1:任务模板
//任务优先级
#define XXX_TASK_PRIO 1
//任务堆栈大小
#define XXX_STK_SIZE 128
//任务句柄
TaskHandle_t XXXTask_Handler = NULL;
/*
* 放在开始任务,只需要执行一次为了创建任务
*/
void Create_XXX_Task(void)
{
BaseType_t xReturned;
//创建XXX任务
xReturned = xTaskCreate((TaskFunction_t )XXX_Task,
(const char* )"XXX_Task",
(uint16_t )XXX_STK_SIZE,
(void* )NULL,
(UBaseType_t )XXX_TASK_PRIO,
(TaskHandle_t* )&XXXTask_Handler);
//判断任务是否正常创建
if( xReturned != pdPASS)
{
/* 任务创建失败 一般原因是栈空间不够 */
vTaskDelete( XXXTask_Handler );
/* 打印创建失败消息---使用宏定义选择性使用,一般就是调试的时候使用 */
#if 0
printf("xxxx失败");
#endif
}
}
/*
* 任务函数
*/
void XXX_Task(void *pvParameters)
{
while(1)
{
}
}
2:常见问题
1:高优先级得任务必须存在阻塞状态,一个任务得大部分时间是处于阻塞状态得
2:对于新建工程以及新建任务,其任务得堆栈大小和优先级先配置为128和1,后面再调与改
3:内核控制函数
1:任务切换函数taskYIELD()
作用:切换任务(可手动切换任务)
我们知道当优先级任务相同的时候,每个任务运行的时间为一个时间片,假如我们此时的任务只需要0.5ms就可以了,不需要1ms,那么我们就可以手动切换任务了
taskYIELD() 用于请求切换上下文到另一个任务。 但是, 除非存在其他任务,其优先级等于或高于调用 taskYIELD() 的任务的优先级, 否则 RTOS 调度器将选择 调用了 taskYIELD() 的任务并使其再次运行。
2:临界段保护代码函数
//任务使用 void taskENTER_CRITICAL( void ); void taskEXIT_CRITICAL( void );场景:很重要的代码,不允许被其他中断打断,比如我这里是数据处理,而有一个任务是数据判断 ,我必须此时先处理数据才能有效,不然就浪费了一次 要求:执行代码必须要短,不能花很长时间 taskENTER_CRITICAL(); /*执行语句代码*/ taskEXIT_CRITICAL();
//中断使用 UBaseType_t taskENTER_CRITICAL_FROM_ISR( void ); void taskEXIT_CRITICAL_FROM_ISR( UBaseType_t uxSavedInterruptStatus );使用在中断中,与任务不同的事情是需要单独定义一个变量(模板) 使用起来与任务一样 UBaseType_t save_state; save_state = taskENTER_CRITICAL_FROM_ISR(); /*执行语句代码*/ taskEXIT_CRITICAL_FROM_ISR(save_state);
注意点:
临界区必须保持非常短,否则将影响 更高优先级的中断的响应时间,会导致该中断嵌套。 每次 taskENTER_CRITICAL_FROM_ISR() 调用都必须紧密配taskEXIT_CRITICAL_FROM_ISR() 调用一起使用。
不得从临界区调用 FreeRTOS API 函数。
4:任务创建函数类
1:xTaskCreate
2:vTaskDelete
void vTaskDelete( TaskHandle_t xTask );//形参是句柄
INCLUDE_vTaskDelete 必须定义为 1 才能使用此函数
此函数的作用为从 RTOS 内核管理中移除任务。被删除的任务将从所有的就绪、阻塞、挂起和事件的列表中移除。
请注意,空闲任务负责从已删除任务中释放 RTOS 内核分配的内存。因此,重要的是,如果您的应用程序调用了 vTaskDelete (),空闲任务不会失去微控制器处理时间。任务代码分配的内存(相当于自己malloc的内存)不会自动释放,并且应在删除任务之前释放。
if( XXXTask_Handler != NULL ) { /* 这样写是防止输出重复删除任务,任务只能删除一次,不然会打印错误信息 */ vTaskDelete( XXXTask_Handler ); printf("任务删除"); XXXTask_Handler = NULL; //然后此任务会在空闲任务中回收资源, }
5:任务控制类函数
1:vTaskDelay
void vTaskDelay( const TickType_t xTicksToDelay );必须将 INCLUDE_vTaskDelay 定义为 1,此函数才可用
形参是多少个tick,因此不要觉得是多少个ms,只不过我们学的时候,一直是1tick就是1ms,因此初学会误认为这个函数是专门延时ms的
非周期延时
2:vTaskDelayUntil
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement
INCLUDE_vTaskDelayUntil 必须被定义为 1 才能使用此函数
// Perform an action every 10 ticks. void vTaskFunction( void * pvParameters ) { TickType_t xLastWakeTime; const TickType_t xFrequency = 10; // Initialise the xLastWakeTime variable with the current time. xLastWakeTime = xTaskGetTickCount(); for( ;; ) { // Wait for the next cycle. vTaskDelayUntil( &xLastWakeTime, xFrequency ); // Perform action here. } }周期延时
3:uxTaskPriorityGet
作用:获取任务的优先级
原型:UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ); //返回值为typedef unsigned long UBaseType_t;
返回值:优先级
使用步骤如下:
#define INCLUDE_uxTaskPriorityGet 1UBaseType_t TaskPriority_Num = 0;
TaskPriority_Num = uxTaskPriorityGet( xHandle );//uxTaskPriorityGet( NULL );
printf("%ld",TaskPriority_Num);4:vTaskPrioritySet
作用:改变任务的优先级
原型:void vTaskPrioritySet( TaskHandle_t xTask,
UBaseType_t uxNewPriority );
使用步骤如下:
#define INCLUDE_vTaskPrioritySet 1
UBaseType_t TaskNewPriority_Num = 20; //TaskNewPriority_Num的范围为0-31(推荐是最大优先级数为32)
vTaskPrioritySet(xHandle,TaskNewPriority_Num); //vTaskPrioritySet(NULL,TaskNewPriority_Num);5:vTaskResume和vTaskSuspend
中断的恢复稍微复杂一点点
* 挂起和恢复函数模板使用 */ /* 宏置一 */ //挂起不支持嵌套,多次挂起,一次恢复就可以了 //任务 vTaskResume(XXXTask_Handler); --无返回值 vTaskSuspend(XXXTask_Handler);--无返回值 //中断 BaseType_t xYieldRequired; /* 恢复被挂起的任务 */ xYieldRequired = xTaskResumeFromISR( XXXTask_Handler ); if ( xYieldRequired == pdTRUE ) { /* 执行上下文切换, ISR 返回的时候将运行另外一个任务 */ portYIELD_FROM_ISR(); }
6:任务实用函数(调试使用)
7:队列模板使用与讲解
1:xQueueCreate
QueueHandle_t xQueue1 = NULL; #define QUEUE1_LENGTH 3 #define QUEUE1_ITEMSIZE sizeof(uint8_t) void vATask( void *pvParameters ) { /* Create a queue capable of containing 10 unsigned long values. */ xQueue1 = xQueueCreate( QUEUE1_LENGTH , QUEUE1_ITEMSIZE ); if( xQueue1 == NULL ) { /* Queue was not created and must not be used. */ //创建失败,需要打印错误信息,一般因为空间不够而无法正确 } }
如何学好FreeRTOS
学会看懂官网给的信息
This page describes the RTOS uxTaskPriorityGet() FreeRTOS API function which is part of the RTOS task control API. FreeRTOS is a professional grade, small footprint, open source RTOS for microcontrollers.
如果忘记了,重新看一遍就行,基础知识其实很少,忘记了就来查找就行