FreeRTOS应用(参数,优先级,延时,钩子,任务,删除函数)

📅 2026/7/24 0:17:48 👁️ 阅读次数 📝 编程学习
FreeRTOS应用(参数,优先级,延时,钩子,任务,删除函数)

1.任务参数使用

2.任务的优先级

3.相对延时函数

4.绝对延时函数

5.空闲钩子函数

6.任务句柄

7.删除任务函数

一.任务参数使用

1.void指针可以指向任意类型的数据,既可以用任意类型的指针对void指针赋值。例如:

int *a; void *p; p=a;

如果将void指针p赋给其它类型的指针,则需要强制转换,例如:

a=(int*)p;

2.在不同的标准中ANSI c标准中,void不能进行算数运算,因为void是无类型,每次算数运算就不知道该操作几个字节。而在GNU中可以,因为GNU认为void*和char*一样。

sizeof(void*)=sizeof(char*);

3.应用

①CubeMX的配置:

代码:

在FreeRTOS.c与main.c中加:#include "user_app.h"

user_app.h #ifndef __USER_APP_H__ #define __USER_APP_H__ #include "usart.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os2.h" #include "string.h" void vTaskFunction(void *pvParameters); void vprintfString(const char *pcString); #endif
user_app.c #include "user_app.h" #define mainDELAY_LOOP_COUNT 0xffffff int fputc(int ch, FILE *f) { HAL_UART_Transmit (&huart1 ,(uint8_t*)&ch,1,0xffff); return ch; } void vprintfString(const char *pcString) { //临近保护 taskENTER_CRITICAL(); { printf("%s",pcString); } taskEXIT_CRITICAL(); } void vTaskFunction(void *pvParameters) { char *pcTaskName; volatile uint32_t ul; pcTaskName=(char*)pvParameters; for(;;) { vprintfString(pcTaskName); for(ul=0;ul<mainDELAY_LOOP_COUNT ;ul++) { //延时 } char cSectionStr1[]="task1"; char *pcRetPtr=strstr(pcTaskName,cSectionStr1); //对比pcTaskName与cSectionStr1是否一样 if(pcRetPtr !=NULL) { HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); } else { HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin); } } }

二.任务的优先级

1.优先级的介绍

调度器始终确保可以运行的最高优先级任务是被选中进入运行状态的任务。具有相同优先级的任务会依次进入和退出运行状态。
② 用于创建任务的 xTaskCreate() API函数的uxPriority 参数为任务分配其初始优先级。vTaskPrioritySet() API函数在任务创建后改变其优先级
③ 最大优先级数量由FreeRTOSConfig.h 中定义的configMAX_PRIORITIES 编译时配置常量设置。较低的数值优先级表示低优先级任务,其中优先级0是最低优先级。可以使用的优先级范围是从0到(configMAX_PRIORITIES – 1)。【建议configMAX_PRIORITIES的值保持在最小值减少RAM的开销和减少执行时间

扩展:若将FreeRTOSConfig.h中的configUSE_PORT_OPTIMISED_TASK_SELECTION设置为 0 。如果没有定义configUSE_PORT_OPTIMISED_TASK_SELECTION 或者通用方法是为正在使用的FreeRTOS移植提供的唯一方法,就会使用通用方法。在FreeRTOSConfig.h中将configUSE_PORT_OPTIMISED_TASK_SELECTION设置为1时,就会使用架构优化的方法。注意,并非所有的FreeRTOS移植都提供了架构优化方法

2.测量与滴答中断

3.应用

CubeMX的配置:略

代码:

在FreeRTOS.c与main.c中加:#include "user_app.h"

user_app.h #ifndef __USER_APP_H__ #define __USER_APP_H__ #include "usart.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os2.h" #include "string.h" void vTaskFunction(void *pvParameters); void vprintfString(const char *pcString); #endif
user_app.c #include "user_app.h" #define mainDELAY_LOOP_COUNT 0xffffff int fputc(int ch, FILE *f) { HAL_UART_Transmit (&huart1 ,(uint8_t*)&ch,1,0xffff); return ch; } void vprintfString(const char *pcString) { //临近保护 taskENTER_CRITICAL(); { printf("%s",pcString); } taskEXIT_CRITICAL(); } void vTaskFunction(void *pvParameters) { char *pcTaskName; volatile uint32_t ul; pcTaskName=(char*)pvParameters; for(;;) { vprintfString(pcTaskName); for(ul=0;ul<mainDELAY_LOOP_COUNT ;ul++) { } char cSectionStr1[]="task1"; char *pcRetPtr=strstr(pcTaskName,cSectionStr1); if(pcRetPtr !=NULL) { HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); } else { HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin); } } }

效果:

三.相对延时函数

1.事件驱动型任务

到目前为止,创建的任务总是需要执行处理操作,并且从未需要等待任何东西,因此总是能够进入运行状态。 “连续处理”类型的任务用途有限,任务只能在最低优先级下创建。如果这些任务以其他优先级运行,就会阻止优先级更低的任务运行。
必须将任务重新编写成事件驱动型的任务。事件驱动型的任务(具有的不同优先级)只有在触发事件发生后才有工作要执行,在事件发生前不会进入运行状态。
调度器始终选择可以运行的最高优先级任务。如果无法选择高优先级任务,例如正在等待某个事件,则调度器必须选择可以运行的优先级较低的任务。

2.任务的阻塞状态

正在等待事件的任务称为处于“阻塞”状态,这是“非运行”状态的一个子状态。任务
可以进入阻塞状态以等待两种不同类型的事件:
• 时间性事件:这些事件发生在延迟期到期或达到绝对时间时。例如,任务可能
会进入阻塞状态,以等待10毫秒过去。
• 同步事件:这些事件来自另一个任务或中断。例如,任务可能会进入阻塞状态,
等待队列中的数据到达。同步事件涵盖了广泛的事件类型。
队列、二进制/计数信号量、互斥量、递归互斥量、事件组、流缓冲区、消息缓冲
区和直接任务通知都可以创建同步事件。
任务也可以在同步事件上设置超时,从而有效地同时阻塞两种类型的事件。

3.挂起和就绪状态

①挂起状态
挂起状态也是非运行状态的一个子状态。处于挂起状态的任务对调度器不可用。进
入挂起状态的唯一方法是调用vTaskSuspend() API函数。
退出挂起状态的唯一方法是调用vTaskResume()或xTaskResumeFromISR() API函
数。大多数应用程序不使用挂起状态。
②就绪状态
处于非运行状态且未阻塞或挂起的任务被称为处于就绪状态。它们可以运行,因此
准备运行,但当前不在运行状态。

4.vTaskDelay()函数

5.应用

CubeMX配置:

代码:

在FreeRTOS.c与main.c中加:#include "user_app.h"

user_app.h #ifndef __USER_APP_H__ #define __USER_APP_H__ #include "usart.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os2.h" #include "string.h" void vTaskFunction(void *pvParameters); void vprintfString(const char *pcString); #endif
user_app.c #include "user_app.h" #define mainDELAY_LOOP_COUNT 0xffffff int fputc(int ch, FILE *f) { HAL_UART_Transmit (&huart1 ,(uint8_t*)&ch,1,0xffff); return ch; } void vprintfString(const char *pcString) { //临近保护 taskENTER_CRITICAL(); { printf("%s",pcString); } taskEXIT_CRITICAL(); } void vTaskFunction(void *pvParameters) { char *pcTaskName; const TickType_t xDelay250ms=pdMS_TO_TICKS (250); //注意:把250ms转换为滴答数 pcTaskName=(char*)pvParameters; for(;;) { vprintfString(pcTaskName); vTaskDelay (xDelay250ms ); char cSectionStr1[]="task1"; char *pcRetPtr=strstr(pcTaskName,cSectionStr1); if(pcRetPtr !=NULL) { HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); } else { HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin); } } }

效果:

四.绝对延时函数

CubeMX配置:略

代码:在FreeRTOS.c与main.c中加:#include "user_app.h"

在FreeRTOS.c中

user_app.h #ifndef __USER_APP_H__ #define __USER_APP_H__ #include "usart.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os2.h" #include "string.h" void vContinuousProcessingTask(void *pvParameters); void vprintfString(const char *pcString); void vPeriodicTask(void* pvParameters); #endif
user_app.c #include "user_app.h" #define mainDELAY_LOOP_COUNT 0xfffff int fputc(int ch, FILE *f) { HAL_UART_Transmit (&huart1 ,(uint8_t*)&ch,1,0xffff); return ch; } void vprintfString(const char *pcString) { //临近保护 taskENTER_CRITICAL(); { printf("%s",pcString); } taskEXIT_CRITICAL(); } void vContinuousProcessingTask(void *pvParameters) { char *pcTaskName; volatile uint32_t ul; pcTaskName=(char*)pvParameters ; for(;;) { vprintfString(pcTaskName); for(ul=0;ul<mainDELAY_LOOP_COUNT;ul++) { } char*pcRetPtr=strstr(pcTaskName ,"task1"); if(pcRetPtr !=NULL) { HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); } else { HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin); } } } void vPeriodicTask(void* pvParameters) { TickType_t xLastWakeTime; const TickType_t xDelay250ms=pdMS_TO_TICKS (250UL); const char *a=(char*) pvParameters; xLastWakeTime =xTaskGetTickCount (); for(;;) { vprintfString(a); vTaskDelayUntil (&xLastWakeTime ,xDelay250ms ); } }

效果:

五.空闲钩子函数

应用:

CubeMX的配置:

代码:

在FreeRTOS.c与main.c中加:#include "user_app.h"

在FreeRTOS中

user_app.h #ifndef __USER_APP_H__ #define __USER_APP_H__ #include "usart.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os2.h" #include "string.h" void vContinuousProcessingTask(void *pvParameters); void vprintfString(const char *pcString,uint32_t ulValue); #endif
user_app.c #include "user_app.h" #define mainDELAY_LOOP_COUNT 0xfffff uint32_t ulIdleCycleCount=0; int fputc(int ch, FILE *f) { HAL_UART_Transmit (&huart1 ,(uint8_t*)&ch,1,0xffff); return ch; } void vprintfString(const char *pcString,uint32_t ulValue) { //临近保护 taskENTER_CRITICAL(); { printf("%s",pcString); printf("ulIdleCycleCount=%d\n\r",ulValue); } taskEXIT_CRITICAL(); } void vContinuousProcessingTask(void *pvParameters) { char *pcTaskName; //volatile uint32_t ul; pcTaskName=(char*)pvParameters ; const TickType_t xDelay250ms=pdMS_TO_TICKS (250); for(;;) { vprintfString(pcTaskName,ulIdleCycleCount); vTaskDelay (xDelay250ms ); char*pcRetPtr=strstr(pcTaskName ,"task1"); if(pcRetPtr !=NULL) { HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); } else { HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin); } } }

效果:

六.任务句柄

应用:

CubeMX的配置:略

代码:

在FreeRTOS.c与main.c中加:#include "user_app.h"

user_app.h #ifndef __USER_APP_H__ #define __USER_APP_H__ #include "usart.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os2.h" #include "string.h" void vTask1(void *pvParameters); void vprintfString(const char *pcString); void vTask2(void* pvParameters); #endif
user_app.c #include "user_app.h" #define mainDELAY_LOOP_COUNT 0xfffff extern osThreadId_t Task1Handle; extern osThreadId_t Task2Handle; int fputc(int ch, FILE *f) { HAL_UART_Transmit (&huart1 ,(uint8_t*)&ch,1,0xffff); return ch; } void vprintfString(const char *pcString) { //临近保护 taskENTER_CRITICAL(); { printf("%s",pcString); // printf("ulIdleCycleCount=%d\n\r",ulValue); } taskEXIT_CRITICAL(); } void vTask1(void *pvParameters) { UBaseType_t uxPriority=uxTaskPriorityGet(NULL); for(;;) { vprintfString("Task1 is Running\n\r"); vprintfString ("About to raise the Task2 priority\n\r"); vTaskPrioritySet (Task2Handle,(uxPriority+1)); //注意 HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); } } void vTask2(void* pvParameters) { UBaseType_t uxPriority=uxTaskPriorityGet(NULL); for(;;) { vprintfString("Task2 is Running\n\r"); vprintfString ("About to lower the Task2 priority\n\r"); vTaskPrioritySet(NULL,(uxPriority -2)); //注意 HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin); } }

效果:

七.删除任务函数

应用:

在FreeRTOS.c与main.c中加:#include "user_app.h"

user_app.h #ifndef __USER_APP_H__ #define __USER_APP_H__ #include "usart.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os2.h" #include "string.h" void vTask1(void *pvParameters); void vprintfString(const char *pcString); void vTask2(void* pvParameters); #endif
user_app.c #include "user_app.h" TaskHandle_t xTask2Handle; extern osThreadId_t Task1Handle; extern osThreadId_t Task2Handle; int fputc(int ch, FILE *f) { HAL_UART_Transmit (&huart1 ,(uint8_t*)&ch,1,0xffff); return ch; } void vprintfString(const char *pcString) { //临近保护 taskENTER_CRITICAL(); { printf("%s",pcString); } taskEXIT_CRITICAL(); } void vTask1(void *pvParameters) { const TickType_t xDelay100ms=pdMS_TO_TICKS (100UL); for(;;) { vprintfString("Task1 is Running\n\r"); xTaskCreate(vTask2,"Task 2",1000,NULL,osPriorityLow+1,&xTask2Handle); } } void vTask2(void* pvParameters) { HAL_GPIO_TogglePin(LED4_GPIO_Port, LED4_Pin); vprintfString ("Task2 is running and abut to delete itself\n\r"); vTaskDelete (xTask2Handle ); }

效果: