• 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 文件中添加中添加宏后,编译报错:
      .ObjectsfreeRTOS_sCreate_task.axf: Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory(referred from tasks.o).
      .ObjectsfreeRTOS_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.
      ");
                      break;
                  case KEY1_PRES:
                      vTaskResume(led1_task_handler);
                      printf("led1_task Resumed.
      ");
                      break;
                  case KEY2_PRES:
                      vTaskSuspend(led2_task_handler);
                      printf("led2_task Suspended.
      ");
                      break;
                  case WKUP_PRES:
                      vTaskResume(led2_task_handler);
                      printf("led2_task Resumed.
      ");
                      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的抢占优先级为 4
          TIM5_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("关闭中断!!!.
      ");
                  portDISABLE_INTERRUPTS();
                  delay_xms(5000);            // delay_xms执行的时候不会执行任何任务调度
                  printf("开中断!!!.
      ");
                  portENABLE_INTERRUPTS();
              }
              printf("interrupt task is %d runing.
      ", 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发生中断.
      ");
                  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发生中断.
      ");
                  LED1=!LED1;
                  TIM_ClearITPendingBit(TIM5, TIM_IT_Update  );    //清除TIMx更新中断标志 
                  taskEXIT_CRITICAL_FROM_ISR(status_value);    //退出临界区
              }
      }
  • 相关阅读:
    idea中svn代码冲突
    数据库表的连接(Left join , Right Join, Inner Join)用法详解
    @Param注解的用法解析
    spring @Transactional注解参数详解
    数据库的DDL、DML和DCL的区别与理解
    Mybatis:resultMap的使用总结
    Maps.newHashMap 和 new HashMap的区别
    php 个推的例子
    fidder 调接口 的 小常识
    php Memcached
  • 原文地址:https://www.cnblogs.com/icefree/p/8684859.html
Copyright © 2020-2023  润新知