ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

STM32HAL库FreeRTOS-2.任务管理

STM32HAL库FreeRTOS-2.任务管理 在上一章中简述了如何创建任务以及任务的优先级关系接下来讲述任务的其他功能。1.1 任务删除在HAL库中删除任务的函数是osThreadTerminate()其函数原型如下osStatus_t osThreadTerminate(osThreadId_t thread_id);该函数用于终止指定线程的执行并释放该线程所占用的内核资源。参数thread_id为要删除的任务句柄即创建任务时osThreadNew()返回的任务ID。函数返回osOK表示删除成功返回osErrorParameter表示参数无效返回osErrorResource表示任务不存在或已被删除。使用示例#include cmsis_os.h osThreadId LED_TaskHandle; void MX_FREERTOS_Init(void) { osThreadDef(LED_Task, LED_Task, osPriorityNormal, 0, 128); LED_TaskHandle osThreadCreate(osThread(LED_Task), NULL); osThreadDef(Ctrl_Task, Ctrl_Task, osPriorityNormal, 0, 128); osThreadCreate(osThread(Ctrl_Task), NULL); } /** * brief LED 任务运行 20 次后自我终止 */ void LED_Task(void const *argument) { uint8_t count 0; for (;;) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); osDelay(500); count; if (count 20) { // 使用 osThreadExit() 终止当前任务 osThreadExit(); // 这行代码永远不会执行到 } } } /** * brief 控制任务终止 LED 任务终止其他任务 */ void Ctrl_Task(void const *argument) { osDelay(10000); // 10 秒后 // 使用 osThreadTerminate() 终止其他任务 osThreadTerminate(LED_TaskHandle); for (;;) { osDelay(1000); } }需要注意的是任务不能删除自身即不能在任务自身的执行函数中调用osThreadTerminate()来终止当前任务否则会导致未定义行为。若任务需要自我终止应使用osThreadExit()函数。要注意的一点是任务一旦删除 (osThreadTerminate()/vTaskDelete())就彻底消失了。想要再次运行必须重新调用创建任务函数。osThreadId Task2Handle; // 删除任务 osThreadTerminate(Task2Handle); Task2Handle NULL; // 建议手动清空句柄防止野指针 // 重新创建任务 Task2Handle osThreadNew(StartTask2, NULL, NULL); 原生freertos vTaskDelete(xTask2Handle); xTask2Handle NULL; xTaskCreate(vTask2, T2, 1024, NULL, 2, xTask2Handle);而原生FreeRTOS则是使用xTaskDelete()进行对任务的删除。下面就例子说明原生FreeRTOS的程序使用#include FreeRTOS.h #include task.h #include stdio.h /* 任务句柄用来操作任务 */ TaskHandle_t xTask1Handle NULL; TaskHandle_t xTask2Handle NULL; /** * brief 任务15秒后自我删除 */ void vTask1( void *pvParameters ) { uint32_t ulCount 0; for(;;) { printf(任务1正在运行, count %d\r\n, ulCount); /* 运行5次之后任务删除自己 */ if(ulCount 5) { printf( 任务1调用xTaskDelete(NULL) 删除自身\r\n); xTaskDelete( NULL ); /* NULL代表删除当前任务 */ } vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1s } } /** * brief 任务2延时8秒然后删除任务1如果还存在 */ void vTask2( void *pvParameters ) { vTaskDelay(pdMS_TO_TICKS(8000)); /* 判断任务1句柄不为空才去删除 */ if(xTask1Handle ! NULL) { printf( 任务2 删除任务1\r\n); vTaskDelete( xTask1Handle ); xTask1Handle NULL; /* 删除后置空句柄防止野指针 */ } for(;;) { printf(任务2持续运行\r\n); vTaskDelay(pdMS_TO_TICKS(2000)); } } int main(void) { /* 创建两个任务 */ xTaskCreate(vTask1, Task1, 128, NULL, 2, xTask1Handle); xTaskCreate(vTask2, Task2, 128, NULL, 2, xTask2Handle); /* 启动调度器 */ vTaskStartScheduler(); /* 如果程序跑到这里说明内存不足创建空闲任务失败 */ for(;;); }运行结果如下所示任务1正在运行, count 0 任务1正在运行, count 1 任务1正在运行, count 2 任务1正在运行, count 3 任务1正在运行, count 4 任务1调用xTaskDelete(NULL) 删除自身 任务2持续运行 任务2持续运行 ...1.2 任务挂起与任务恢复在嵌入式实时系统中任务挂起Suspend和任务恢复Resume是最基础也最常用的任务控制手段。通过动态控制任务的运行状态可以实现低功耗管理、关键任务保护、调试诊断等多种功能。osThreadSuspend(TaskLEDHandle) //任务挂起 osThreadResume(TaskLEDHandle) //任务恢复 osThreadResumeFromISR() //中断内恢复任务 osThreadSuspendAll() //所有任务挂起 osThreadResumeAll() //所有任务恢复 /*对比原生freertos*/ vTaskSuspend() //任务挂起 vTaskResume() //任务恢复 xTaskResumeFromISR() //中断内恢复任务 vTaskSuspendAll() //所有任务挂起 vTaskResumeAll() //所有任务恢复当任务被挂起的时候此任务将不再运行直至挂起状态解除。可以用在一些串口接收命令或者是结合按键进行任务挂起的操作不过要注意的点是在中断内想要恢复任务必须要使用osThreadResumerFromISRxTaskResumerFromISR下面讲述运用例子-挂起任务后延时一段时间后恢复/* Includes ------------------------------------------------------------------*/ #include main.h #include cmsis_os.h #include stdio.h UART_HandleTypeDef huart1; /* 任务句柄CubeMX生成的 */ osThreadId Task1Handle; osThreadId Task2Handle; //重定向printf到串口1 int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xffff); return ch; } /* 任务1入口函数 */ void StartTask1(void const * argument) { for(;;) { printf(Task1: 准备挂起Task2\r\n); //挂起任务2 osThreadSuspend(Task2Handle); osDelay(3000); //延时3秒 printf(Task1: 恢复Task2\r\n); //恢复任务2 osThreadResume(Task2Handle); osDelay(3000); } } /* 任务2入口函数 */ void StartTask2(void const * argument) { for(;;) { printf(Task2 正在运行......\r\n); osDelay(500); } }然后时原生freertos的示例#include FreeRTOS.h #include task.h #include stdio.h /* 任务句柄 */ TaskHandle_t xTask2Handle NULL; void vTask1( void *pvParameters ) { BaseType_t xReturned; for( ;; ) { printf(任务1正在运行准备挂起任务2\r\n); /* 挂起任务2 */ vTaskSuspend( xTask2Handle ); vTaskDelay( pdMS_TO_TICKS(3000) ); printf(任务1恢复任务2\r\n); /* 恢复任务2 */ vTaskResume( xTask2Handle ); vTaskDelay( pdMS_TO_TICKS(3000) ); } } void vTask2( void *pvParameters ) { for( ;; ) { printf(任务2正在运行\r\n); vTaskDelay( pdMS_TO_TICKS(500) ); } } int main(void) { /* 创建任务1 */ xTaskCreate( vTask1, Task1, 1024, NULL, 2, NULL ); /* 创建任务2保存句柄 */ xTaskCreate( vTask2, Task2, 1024, NULL, 2, xTask2Handle ); /* 启动调度器 */ vTaskStartScheduler(); /* 如果运行到这里说明内存不足 */ for(;;); }最后再放上任务管理的关系图巩固一下记忆
返回列表