网站建设的需求怎么写,网站需要流量,广告网络平台,太原网站制作开发文章目录目的创建任务任务调度任务控制延时函数任务句柄获取与修改任务优先级删除任务挂起与恢复任务强制任务离开阻塞状态空闲任务总结目的
任务#xff08;Task#xff09;是FreeRTOS中供用户使用的最核心的功能#xff0c;本文将介绍任务创建与使用相关的基础内容。
本…
文章目录目的创建任务任务调度任务控制延时函数任务句柄获取与修改任务优先级删除任务挂起与恢复任务强制任务离开阻塞状态空闲任务总结目的
任务Task是FreeRTOS中供用户使用的最核心的功能本文将介绍任务创建与使用相关的基础内容。
本文接上篇《FreeRTOS入门01基础说明与使用演示》
创建任务
创建任务主要使用 xTaskCreate 这个函数
// 创建成功会返回pdPASS(1)失败通常返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY(-1)即内存不足
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 任务函数const char * const pcName, // 任务名称// 长度由FreeRTOSConfig.h中configMAX_TASK_NAME_LEN定义const configSTACK_DEPTH_TYPE usStackDepth, // 该任务栈深度栈大小对于32位架构一个深度为四字节void * const pvParameters, // 传递给任务的参数UBaseType_t uxPriority, // 任务优先级值越大优先级越高// 最大值为FreeRTOSConfig.h中configMAX_PRIORITIES - 1TaskHandle_t * const pxCreatedTask ) // 任务句柄后续可以用过该句柄来操作任务任务需要使用 vTaskStartScheduler(); 来调度运行通常将该行语句放在程序主循环前面正常情况下程序将在这里无限循环。
下面是个基础的创建和使用任务的演示使用CH32V307的FreeRTOS项目模板方式创建项目替换 main.c 为下面内容
#include debug.h
#include FreeRTOS.h // 引入头文件
#include task.h // 引入头文件/* Task1相关参数与任务处理函数 */
void task1_task(void *pvParameters)
{while(1){printf(TickCount: %u\r\n, xTaskGetTickCount()); // 打印FreeRTOS时间刻vTaskDelay(250); // FreeRTOS的延时函数// FreeRTOSConfig.h中configTICK_RATE_HZ为500即每2ms调度一次// 所以这里的延时时间是 250 * 2 500ms}
}/* 主函数 */
int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SystemCoreClockUpdate();Delay_Init();USART_Printf_Init(115200);xTaskCreate(task1_task, task1, 256, NULL, 5, NULL); // 创建一个任务vTaskStartScheduler(); // 任务调度任务将在这里根据情况开始运行程序将在这里无序循环while(1){} // 程序不会运行到这里
}同一个任务的函数可以用来创建不同的任务因为默认情况下不同任务有不同的堆栈
#include debug.h
#include FreeRTOS.h // 引入头文件
#include task.h // 引入头文件/* Task1相关参数与任务处理函数 */
void task(void *pvParameters)
{const char *pcTaskText pvParameters;while(1){printf(%s\r\n, pcTaskText);vTaskDelay(500);}
}/* 主函数 */
int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SystemCoreClockUpdate();Delay_Init();USART_Printf_Init(115200);xTaskCreate(task, task1, 256, task 1 run, 5, NULL); // 创建一个任务xTaskCreate(task, task2, 256, task 2 run, 5, NULL); // 创建一个任务vTaskStartScheduler(); // 任务调度任务将在这里根据情况开始运行程序将在这里无序循环while(1){} // 程序不会运行到这里
}任务也可以动态的创建
#include debug.h
#include FreeRTOS.h // 引入头文件
#include task.h // 引入头文件/* Task2相关参数与任务处理函数 */
void task2(void *pvParameters){while(1){printf(task 2 run.\r\n);vTaskDelay(500);}
}/* Task1相关参数与任务处理函数 */
void task1(void *pvParameters)
{volatile size_t i 0; // 使用volatile关键词防止编译器优化while(1){printf(task 1 run.\r\n);i;if (i 3) { // task1执行3次后xTaskCreate(task2, task2, 256, NULL, 5, NULL); // 动态创建任务}vTaskDelay(1000);}
}/* 主函数 */
int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SystemCoreClockUpdate();Delay_Init();USART_Printf_Init(115200);printf(FreeRTOS Kernel Version:%s\r\n,tskKERNEL_VERSION_NUMBER); // 打印FreeRTOS内核版本号xTaskCreate(task1, task1, 256, NULL, 5, NULL); // 创建一个任务vTaskStartScheduler(); // 任务调度任务将在这里根据情况开始运行程序将在这里无序循环while(1){} // 程序不会运行到这里
}除了使用 xTaskCreate 创建任务还有一些其它方法可以创建任务主要是一些使用静态内存分配方式创建任务的方法目前来说除非要求非常高的场合一般没必要使用这些方式。
任务调度
通常来说FreeRTOS使用时都会用到一个定时器常用SysTick定时器定时产生中断FreeRTOS每次中断时累加系统时间 Tick 就是前面例子中使用 xTaskGetTickCount() 获取的内容并检查和调度任务运行。
FreeRTOSConfig.h 文件中 configTICK_RATE_HZ 参数用于设置系统中断频率。在上面项目中默认值为 500 表示每秒中断 500 次即每秒 Tick 值加 500 每两次调度发生间隔为 2ms 这 2ms 其实就是每次被调度到执行的任务工作的时间。
任务在OS中各个阶段通常使用下面状态转换图表示 Running 即表示当前正在运行的任务 Ready 表示已经准备好但没有时间可以分配给它运行的任务 Blocked 表示正在等待时间或者其它资源可用的任务比如前面的vTaskDelay方法就会使任务进入Blocked状态 Suspended 主要是手动使用函数挂起的任务。
除了手动创建的任务系统还有个空闲任务优先级为0在没有用户任务执行的适合空闲任务将会执行。空闲任务中会进行一些资源释放等操作通常开发是最好保证空闲任务能够定期被调度到。
这里有一个问题如果当前有多个任务处于就绪状态 Ready 那么应该调度哪个任务执行
在上面项目的默认设定下
configUSE_PREEMPTION 1 在 FreeRTOSConfig.h 文件中定义 可以抢占多任务同时就绪时最高优先级任务将执行configUSE_TIME_SLICING 1 没有主动定义默认值为1 轮流执行多个同优先级的项目将轮流交替执行configUSE_TICKLESS_IDLE 0 没有主动定义默认值为0configIDLE_SHOULD_YIELD 0 在 FreeRTOSConfig.h 文件中定义 空闲任务不让出时间
除了上面的调度逻辑还有一个逻辑是在运行 vTaskStartScheduler(); 语句前添加的任务高优先级的会先运行同优先级的后添加的将先运行。
任务控制
任务创建后可以通过一些函数来控制任务状态主要可以实现改变任务优先级、删除任务、挂起与恢复任务、阻塞任务等功能。
需要注意的是下面出现的任务控制功能可能并不会在相关函数执行后立即生效比如任务删除自身这种情况下需要等到下一次任务调度或是空闲任务执行后才会真正生效。
延时函数
前面例子中有出现延时函数FreeRTOS提供了延时函数主要有下面两种
// 从进入vTaskDelay函数到函数返回总时间至少为xTicksToDelay个系统Tick时间
void vTaskDelay(const TickType_t xTicksToDelay)// 从pxPreviousWakeTime系统时间开始至少经过xTimeIncrement个系统时间
BaseType_t xTaskDelayUntil(TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement)
void vTaskDelayUntil(TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement)
// 上面函数中需要用到的系统时间 pxPreviousWakeTime 可以使用下面两个函数获取
TickType_t xTaskGetTickCount(void) // 在普通任务中使用
TickType_t xTaskGetTickCountFromISR(void) // 在中断服务程序中使用通常来说如果想要设置任务每次执行完成到下次开始执行的延时可以使用第一种延时方式如果想要任务每次开始执行时间间隔相等那就需要使用第二种方式周期性任务。
任务句柄
下面的各种任务控制功能都需要用到任务句柄。任务句柄可以理解为一个结构体用来保存任务相关的各种内容所以我们可以通过它来控制指定的任务。
任务句柄类型是 TaskHandle_t 可以使用下面方式在创建任务时获得
TaskHandle_t Task_Handler; // 声明任务句柄对象int main(void)
{xTaskCreate(task_func, name, 256, NULL, 5, Task_Handler); // 创建任务并获得任务句柄
}除了在创建时获得任务句柄也可以使用下面函数获得已创建的任务的任务句柄
// 获取当前任务任务句柄
// FreeRTOSConfig.h中INCLUDE_xTaskGetCurrentTaskHandle 设置为1才能使用
TaskHandle_t xTaskGetCurrentTaskHandle(void)// 通过任务名称获取任务句柄
// FreeRTOSConfig.h中INCLUDE_xTaskGetHandle设置为1才能使用
TaskHandle_t xTaskGetHandle(const char *pcNameToQuery)获取与修改任务优先级
获取与修改任务优先级主要由下面函数进行操作
// 获取任务优先级
UBaseType_t uxTaskPriorityGet(const TaskHandle_t xTask) // 在普通任务中使用
UBaseType_t uxTaskPriorityGetFromISR(const TaskHandle_t xTask) // 在中断服务程序中使用// 设置任务优先级
void vTaskPrioritySet(TaskHandle_t xTask, UBaseType_t uxNewPriority)// xTask可以填入NULL表示执行该函数的任务自身
// uxNewPriority为欲设的任务优先级值越大优先级越高最大值为FreeRTOSConfig.h中configMAX_PRIORITIES - 1删除任务
可以使用下面函数来删除任务
void vTaskDelete(TaskHandle_t xTaskToDelete)
// xTaskToDelete可以填入NULL表示执行该函数的任务自身挂起与恢复任务
挂起与恢复任务主要由下面函数进行操作
// 挂起任务
void vTaskSuspend(TaskHandle_t xTaskToSuspend)
// xTaskToSuspend可以填入NULL表示执行该函数的任务自身// 恢复任务
void vTaskResume(TaskHandle_t xTaskToResume) // 在普通任务中使用
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume) // 在中断服务程序中使用
// 通常恢复任务只能恢复别人自己不能恢复自己因为已经被挂起了// 暂停所有任务调度
void vTaskSuspendAll(void)
// 恢复所有任务调度
BaseType_t xTaskResumeAll(void)强制任务离开阻塞状态
强制任务离开阻塞状态主要就下面函数进行操作
BaseType_t xTaskAbortDelay(TaskHandle_t xTask)
// 如果xTask不在阻塞状态则返回pdFAIL否则返回pdPASS空闲任务
FreeRTOS调度器启动时会自动创建空闲任务以确保始终存在一个能够运行的任务。空闲任务处于最低优先级0以确保如果有更高的优先级应用程序任务处于准备就绪状态时空闲任务不会占用任何CPU时间。
空闲任务负责释放删除自身的任务的内存。除了这个功能空闲任务还可以有一个由用户实现具体功能的钩子函数 void vApplicationIdleHook(void)该函数会在每次空闲任务运行时被调用。
要使用空闲任务钩子函数需要在 FreeRTOSConfig.h 文件中定义 configUSE_IDLE_HOOK 值为 1 然后实现钩子函数
void vApplicationIdleHook(void) {// TDOD
}必须确保钩子函数不能调用任何可能导致空闲任务阻塞的 API 函数 (例如vTaskDelay () 或带有阻塞时间的队列或信号量函数
空闲钩子函数比较常用的功能有下面一些
将 CPU 置于省电模式测量空闲时间计算 CPU 占用率执行一些低优先级但需要长时间执行的任务
总结
FreeRTOS中任务的基础使用还是比较简单的。实际项目中通常会有多个任务任务间多数时候会需要配合工作这些时候就需要用到 队列、信号量、互斥量 等功能了这些内容将在后面的文章中进行介绍。