欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

2、FreeRTOS任务相关API函数

发布时间:2025/4/16 编程问答 4 豆豆
生活随笔 收集整理的这篇文章主要介绍了 2、FreeRTOS任务相关API函数 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

1.任务相关的API函数

函数存在于task.c中,主要的函数有:

  • xTaskCreate():使用动态的方法创建一个任务;
  • xTaskCreatStatic():使用静态的方法创建一个任务(用的非常少);
  • xTaskCreateRestricted():创建一个使用MPU进行限制的任务;
  • vTaskDelete():删除一个任务;
  • vTaskSuspend():挂起一个任务;
  • vTaskResume():恢复一个任务的运行;
  • vTaskResumeFromISR():中断服务函数中恢复一个任务的运行;
  • portENABLE_INTERRUPTS():打开FreeRTOS中断;
  • portDISABLE_INTERRUPTS():关闭freeRTOS中断;

2.动态创建任务

  • xTaskCreate()函数原型: BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,const char * const pcName,uint16_t usStackDepth,void *pvParameters,UBaseType_t uxPriority,TaskHandle_t *pvCreatedTask);
  • 动态创建任务:使用前先判断 #if( configSUPPORT_STATIC_ALLOCATION == 1 ) 是否成立,如果不成立需要在FreeRTOSConfig.h 文件中添加;
    #include "FreeRTOS.h" #include "task.h"//start_task 任务 void start_task(void *pvParameters); // 任务函数 #define start_task_zise 50 // 任务堆栈的大小 #define start_task_prio 1 // 任务优先级 TaskHandle_t start_task_handler; // 任务句柄//led1_task 任务 void led1_task(void *pvParameters); // 任务函数 #define led1_task_zise 50 // 任务堆栈的大小 #define led1_task_prio 2 // 任务优先级 TaskHandle_t led1_task_handler; // 任务句柄
    int main(void) {NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200);delay_init();LED_Init();// 创建一个任务 xTaskCreate(任务函数, 任务名, 任务堆栈的大小, 传递给任务函数的参数, 任务优先级, 任务句柄);xTaskCreate( start_task, "start_stask", start_task_zise, NULL, start_task_prio, &start_task_handler); vTaskStartScheduler(); // 开启任务调度return 0; }void start_task( void * pvParameters ) {taskENTER_CRITICAL(); // 创建临界区// 创建led1任务xTaskCreate(led1_task, "led1_task", start_task_zise, NULL, led1_task_prio, &led1_task_handler); vTaskDelete(start_task_handler); //删除开始任务taskEXIT_CRITICAL(); // 退出临界区 } //LED1任务函数 void led1_task( void * pvParameters ) {for( ;; ){LED0 = ~LED0;vTaskDelay(1000);} }

3.静态创建任务

  • xTaskCreatStatic()函数原型: TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,const char * const pcName,const uint32_t ulStackDepth,void * const pvParameters,UBaseType_t uxPriority,StackType_t * const puxStackBuffer,StaticTask_t * const pxTaskBuffer )
  • 静态创建任务:使用前先判断 #if( configSUPPORT_STATIC_ALLOCATION== 1 ) 是否成立,如果不成立需要在FreeRTOSConfig.h 文件中添加;
  • 在FreeRTOSConfig.h 文件中添加中添加宏后,编译报错: .\Objects\freeRTOS_sCreate_task.axf: Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory(referred from tasks.o). .\Objects\freeRTOS_sCreate_task.axf: Error: L6218E: Undefined symbol vApplicationGetTimerTaskMemory (referred from timers.o).
  • 由于把静态创建的宏给打开了,所以这两个数需要我们自己去实现 // 空闲任务 static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE]; static StaticTask_t IdleTaskTCB; // 定时器任务 static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH]; static StaticTask_t TimerTaskTCB;// 空闲任务所需内存 void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) {*ppxIdleTaskTCBBuffer = &IdleTaskTCB;*ppxIdleTaskStackBuffer = IdleTaskStack;*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } // 定时器任务所需内存 void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) {*ppxTimerTaskTCBBuffer = &TimerTaskTCB;*ppxTimerTaskStackBuffer = TimerTaskStack;*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; }
  • 静态创建任务 //start_task 任务 void start_task(void *pvParameters); // 任务函数 #define start_task_zise 50 // 任务堆栈的大小 #define start_task_prio 1 // 任务优先级 StackType_t start_task_stack[start_task_zise]; // 任务控制块大小 StaticTask_t start_task_TCB; // 任务堆栈大小 TaskHandle_t start_task_handler; // 任务句柄//led1_task 任务 void led1_task(void *pvParameters); // 任务函数 #define led1_task_zise 50 // 任务堆栈的大小 #define led1_task_prio 2 // 任务优先级 StackType_t led1_task_stack[start_task_zise]; // 任务控制块大小 StaticTask_t led1_task_TCB; // 任务堆栈大小 TaskHandle_t led1_task_handler; // 任务句柄//led2_task 任务 void led2_task(void *pvParameters); // 任务函数 #define led2_task_zise 50 // 任务堆栈的大小 #define led2_task_prio 3 // 任务优先级 StackType_t led2_task_stack[start_task_zise]; // 任务控制块大小 StaticTask_t led2_task_TCB; // 任务堆栈大小 TaskHandle_t led2_task_handler; // 任务句柄int main(void) {NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200);delay_init();LED_Init();// 创建一个开始任务start_task_handler = xTaskCreateStatic( (TaskFunction_t )start_task,(char *)"start_task",(uint32_t )start_task_zise,(void * )NULL,(UBaseType_t )start_task_prio,(StackType_t * )start_task_stack, // 任务控制块大小(StaticTask_t * )&start_task_TCB ); // 任务堆栈大小 vTaskStartScheduler(); // 开启任务调度return 0; }void start_task( void * pvParameters ) {led1_task_handler = xTaskCreateStatic( (TaskFunction_t )led1_task,(char *)"led1_task",(uint32_t )led1_task_zise,(void * )NULL,(UBaseType_t )led1_task_prio,(StackType_t * )led1_task_stack, // 任务控制块大小(StaticTask_t * )&led1_task_TCB ); // 任务堆栈大小 led2_task_handler = xTaskCreateStatic( (TaskFunction_t )led2_task,(char *)"led2_task",(uint32_t )led2_task_zise,(void * )NULL,(UBaseType_t )led2_task_prio,(StackType_t * )led2_task_stack, // 任务控制块大小(StaticTask_t * )&led2_task_TCB ); // 任务堆栈大小 vTaskDelete(start_task_handler); } void led1_task( void * pvParameters ) {for( ;; ){LED0 = ~LED0;vTaskDelay(200);} } void led2_task( void * pvParameters ) {for( ;; ){LED1 = ~LED1;vTaskDelay(1000);} }

4.删除任务

  • void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;

5.任务挂起

  •  void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;

6.任务恢复

  •  void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
  • 挂起、恢复代码如下: //key_task 任务 void key_task(void *pvParameters); // 任务函数 #define key_task_zise 50 // 任务堆栈的大小 #define key_task_prio 4 // 任务优先级 TaskHandle_t key_task_handler; // 任务句柄void start_task( void * pvParameters ) {taskENTER_CRITICAL(); // 创建临界区// 创建按键检查任务 xTaskCreate((TaskFunction_t )key_task,(const char * )"key_task",(uint16_t )key_task_zise,(void * )NULL,(UBaseType_t )key_task_prio,(TaskHandle_t * )&key_task_handler);......vTaskDelete(start_task_handler); //删除开始任务taskEXIT_CRITICAL(); // 退出临界区 }//key任务函数 void key_task( void * pvParameters ) {char key;for( ;; ){key = KEY_Scan(0);switch(key){case KEY0_PRES:vTaskSuspend(led1_task_handler);printf("led1_task Suspended.\n");break;case KEY1_PRES:vTaskResume(led1_task_handler);printf("led1_task Resumed.\n");break;case KEY2_PRES:vTaskSuspend(led2_task_handler);printf("led2_task Suspended.\n");break;case WKUP_PRES:vTaskResume(led2_task_handler);printf("led2_task Resumed.\n");break;}vTaskDelay(10); //延时10ms } }

7.FreeRTOS开关中断

  • freeRTOS管理的中断优先级为 5~15,这是在freeRTOSConfig.h中设置的。 #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)
  • 设置好宏后,低于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断可以安全的调用FreeRTOS的API函数(xxFromISR()函数);
  • 高于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断不能被FreeRTOS禁止,中断服务函数也不能调用FreeRTOS的API函数。
  • 由于高于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY的优先级不会被FreeRTOS内核屏蔽,因此那些对实时性要求严格的任务可以使用这些优先级(0~4),比如四轴飞行器中的避障检测; //start_task 任务 void start_task(void *pvParameters); // 任务函数 #define start_task_zise 50 // 任务堆栈的大小 #define start_task_prio 1 // 任务优先级 TaskHandle_t start_task_handler; // 任务句柄//interrupt_task 任务 void interrupt_task(void *pvParameters); // 任务函数 #define interrupt_task_zise 50 // 任务堆栈的大小 #define interrupt_task_prio 2 // 任务优先级 TaskHandle_t interrupt_task_handler; // 任务句柄int main(void) {NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200);delay_init();LED_Init();TIM3_Int_Init(10000-1,7200-1); //设置定时器3的抢占优先级为 4TIM5_Int_Init(10000-1,7200-1); //设置定时器5的抢占优先级为 5// 创建一个任务xTaskCreate((TaskFunction_t )start_task, // 任务函数 (const char * )"start_stask", // 任务名 (uint16_t )start_task_zise, // 任务堆栈的大小(void * )NULL, // 传递给任务函数的参数(UBaseType_t )start_task_prio, // 任务优先级(TaskHandle_t * )&start_task_handler); // 任务句柄 vTaskStartScheduler(); // 开启任务调度return 0; }void start_task( void * pvParameters ) {taskENTER_CRITICAL(); // 创建临界区// 创建led1任务 xTaskCreate((TaskFunction_t )interrupt_task,(const char * )"interrupt_task",(uint16_t )interrupt_task_zise,(void * )NULL,(UBaseType_t )interrupt_task_prio,(TaskHandle_t * )&interrupt_task_handler);// 创建led2任务 vTaskDelete(start_task_handler); //删除开始任务taskEXIT_CRITICAL(); // 退出临界区 } //interrupt任务函数 void interrupt_task( void * pvParameters ) {int i = 0;for( ;; ){if(i == 5){printf("关闭中断!!!.\n");portDISABLE_INTERRUPTS();delay_xms(5000); // delay_xms执行的时候不会执行任何任务调度printf("开中断!!!.\n");portENABLE_INTERRUPTS();}printf("interrupt task is %d runing.\n", i);LED0 = ~LED0;vTaskDelay(1000);i++;} }

8.临界段

  •  临界段是指:那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。FreeRTOS在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。
  • FreeRTOS中与临界段有关的函数有4个,定义于task.h中: #define taskENTER_CRITICAL() portENTER_CRITICAL() #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()#define taskEXIT_CRITICAL() portEXIT_CRITICAL() #define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
  • taskENTER_CRITICAL():进入任务级的临界区;     
  • taskEXIT_CRITICAL():退出任务级的临界区; void start_task( void * pvParameters ) {taskENTER_CRITICAL(); // 进入临界区// 创建led1任务 xTaskCreate((TaskFunction_t )interrupt_task,(const char * )"interrupt_task",(uint16_t )interrupt_task_zise,(void * )NULL,(UBaseType_t )interrupt_task_prio,(TaskHandle_t * )&interrupt_task_handler);// 创建led2任务 vTaskDelete(start_task_handler); //删除开始任务taskEXIT_CRITICAL(); // 退出临界区 }
  • taskEXIT_CRITICAL_FROM_ISR():进入中断级临界区;
  • taskENTER_CRITICAL_FROM_ISR():退出中断级临界区; //定时器3中断服务程序 void TIM3_IRQHandler(void) //TIM3中断 {int status_value;if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否 {status_value = taskENTER_CRITICAL_FROM_ISR(); //进入临界区printf("定时器3发生中断.\n");LED1=!LED1;TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志 taskEXIT_CRITICAL_FROM_ISR(status_value); //退出临界区 } }//定时器3中断服务程序 void TIM5_IRQHandler(void) //TIM3中断 {int status_value;if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) //检查TIM5更新中断发生与否 { status_value = taskENTER_CRITICAL_FROM_ISR(); //进入临界区printf("定时器5发生中断.\n");LED1=!LED1;TIM_ClearITPendingBit(TIM5, TIM_IT_Update ); //清除TIMx更新中断标志 taskEXIT_CRITICAL_FROM_ISR(status_value); //退出临界区 } }

     

     

 

转载于:https://www.cnblogs.com/icefree/p/8684859.html

总结

以上是生活随笔为你收集整理的2、FreeRTOS任务相关API函数的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。