打印
[应用相关]

FreeRTOS任务控制

[复制链接]
795|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keaibukelian|  楼主 | 2018-9-13 12:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原创地址为:https://blog.csdn.net/zhzht19861011/article/details/50454591

FreeRTOS任务控制API函数主要实现任务延时、任务挂起、解除任务挂起、任务优先级获取和设置等功能。

1.相对延时1.1函数描述

      void vTaskDelay( portTickTypexTicksToDelay )

      调用vTaskDelay()函数后,任务会进入阻塞状态,持续时间由vTaskDelay()函数的参数xTicksToDelay指定,单位是系统节拍时钟周期。常量portTICK_RATE_MS 用来辅助计算真实时间,此值是系统节拍时钟中断的周期,单位是毫秒。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelay 必须设置成1,此函数才能有效。

      vTaskDelay()指定的延时时间是从调用vTaskDelay()后开始计算的相对时间。比如vTaskDelay(100),那么从调用vTaskDelay()后,任务进入阻塞状态,经过100个系统时钟节拍周期,任务解除阻塞。因此,vTaskDelay()并不适用与周期性执行任务的场合。此外,其它任务和中断活动,会影响到vTaskDelay()的调用(比如调用前高优先级任务抢占了当前任务),因此会影响任务下一次执行的时间。API函数vTaskDelayUntil()可用于固定频率的延时,它用来延时一个绝对时间。

1.2参数描述
  • xTicksToDelay:延时时间总数,单位是系统时钟节拍周期。

1.3用法举例


  • voidvTaskFunction( void * pvParameters )



  • {



  •      /* 阻塞500ms. */



  •      constportTickType xDelay = 500 / portTICK_RATE_MS;







  •      for( ;; )



  •      {



  •          /* 每隔500ms触发一次LED, 触发后进入阻塞状态 */



  •          vToggleLED();



  •          vTaskDelay( xDelay );



  •      }



  • }



沙发
keaibukelian|  楼主 | 2018-9-13 12:40 | 只看该作者
2.绝对延时2.1函数描述

         void vTaskDelayUntil( TickType_t *pxPreviousWakeTime,

                      const TickType_txTimeIncrement );

      任务延时一个指定的时间。周期性任务可以使用此函数,以确保一个恒定的频率执行。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelayUntil 必须设置成1,此函数才有效。

      这个函数不同于vTaskDelay()函数的一个重要之处在于:vTaskDelay()指定的延时时间是从调用vTaskDelay()之后(执行完该函数)开始算起的,但是vTaskDelayUntil()指定的延时时间是一个绝对时间。

      调用vTaskDelay()函数后,任务会进入阻塞状态,持续时间由vTaskDelay()函数的参数指定,单位是系统节拍时钟周期。因此vTaskDelay()并不适用于周期性执行任务的场合。因为调用vTaskDelay()到任务解除阻塞的时间不总是固定的并且该任务下一次调用vTaskDelay()函数的时间也不总是固定的(两次执行同一任务的时间间隔本身就不固定,中断或高优先级任务抢占也可能会改变每一次执行时间)。

      vTaskDelay()指定一个从调用vTaskDelay()函数后开始计时,到任务解除阻塞为止的相对时间,而vTaskDelayUntil()指定一个绝对时间,每当时间到达,则解除任务阻塞。

      应当指出的是,如果指定的唤醒时间已经达到,vTaskDelayUntil()立刻返回(不会有阻塞)。因此,使用vTaskDelayUntil()周期性执行的任务,无论任何原因(比如,任务临时进入挂起状态)停止了周期性执行,使得任务少运行了一个或多个执行周期,那么需要重新计算所需要的唤醒时间。这可以通过传递给函数的指针参数pxPreviousWake指向的值与当前系统时钟计数值比较来检测,在大多数情况下,这并不是必须的。

      常量portTICK_RATE_MS 用来辅助计算真实时间,此值是系统节拍时钟中断的周期,单位是毫秒。

      当调用vTaskSuspendAll()函数挂起RTOS调度器时,不可以使用此函数。

2.2参数描述
  • pxPreviousWakeTime:指针,指向一个变量,该变量保存任务最后一次解除阻塞的时间。第一次使用前,该变量必须初始化为当前时间。之后这个变量会在vTaskDelayUntil()函数内自动更新。
  • xTimeIncrement:周期循环时间。当时间等于(*pxPreviousWakeTime + xTimeIncrement)时,任务解除阻塞。如果不改变参数xTimeIncrement的值,调用该函数的任务会按照固定频率执行。

2.3用法举例


  • //每10次系统节拍执行一次



  • void vTaskFunction( void * pvParameters )



  • {



  •      static portTickType xLastWakeTime;



  •      const portTickType xFrequency = 10;







  •      // 使用当前时间初始化变量xLastWakeTime



  •      xLastWakeTime = xTaskGetTickCount();







  •      for( ;; )



  •      {



  •          //等待下一个周期



  •          vTaskDelayUntil( &xLastWakeTime,xFrequency );







  •          // 需要周期性执行代码放在这里



  •      }



  • }



使用特权

评论回复
板凳
keaibukelian|  楼主 | 2018-9-13 12:40 | 只看该作者
3.获取任务优先级3.1函数描述

      UBaseType_t uxTaskPriorityGet(TaskHandle_t xTask );

      获取指定任务的优先级。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskPriorityGet必须设置成1,此函数才有效。

3.2参数描述
  • xTask:任务句柄。NULL表示获取当前任务的优先级。

3.3返回值

      返回指定任务的优先级。

3.4用法举例


  • voidvAFunction( void )



  • {



  •      xTaskHandlexHandle;



  •      // 创建任务,保存任务句柄



  •      xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );



  •      // ...



  •      // 使用句柄获取创建的任务的优先级



  •      if( uxTaskPriorityGet( xHandle ) !=tskIDLE_PRIORITY )



  •      {



  •          // 任务可以改变自己的优先级



  •      }



  •      // ...



  •      // 当前任务优先级比创建的任务优先级高?



  •      if( uxTaskPriorityGet( xHandle ) <uxTaskPriorityGet( NULL ) )



  •      {



  •          // 当前优先级较高



  •      }



  • }



使用特权

评论回复
地板
keaibukelian|  楼主 | 2018-9-13 12:41 | 只看该作者
4.设置任务优先级4.1函数描述

      void vTaskPrioritySet( TaskHandle_txTask,

                       UBaseType_tuxNewPriority );

      设置指定任务的优先级。如果设置的优先级高于当前运行的任务,在函数返回前会进行一次上下文切换。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskPrioritySet 必须设置成1,此函数才有效。

4.2参数描述
  • xTask:要设置优先级任务的句柄,为NULL表示设置当前运行的任务。
  • uxNewPriority:要设置的新优先级。

4.3用法举例


  • voidvAFunction( void )



  • {



  •      xTaskHandlexHandle;



  •      // 创建任务,保存任务句柄。



  •      xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );



  •      // ...



  •      // 使用句柄来提高创建任务的优先级



  •      vTaskPrioritySet( xHandle,tskIDLE_PRIORITY + 1 );



  •      // ...



  •      // 使用NULL参数来提高当前任务的优先级,设置成和创建的任务相同。



  •      vTaskPrioritySet( NULL, tskIDLE_PRIORITY +1 );



  • }



使用特权

评论回复
5
keaibukelian|  楼主 | 2018-9-13 12:41 | 只看该作者
5.任务挂起5.1函数描述

      void vTaskSuspend( TaskHandle_txTaskToSuspend );

      挂起指定任务。被挂起的任务绝不会得到处理器时间,不管该任务具有什么优先级。

      调用vTaskSuspend函数是不会累计的:即使多次调用vTaskSuspend ()函数将一个任务挂起,也只需调用一次vTaskResume ()函数就能使挂起的任务解除挂起状态。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必须设置成1,此函数才有效。

5.2参数描述
  • xTaskToSuspend:要挂起的任务句柄。为NULL表示挂起当前任务。

5.3用法举例


  • voidvAFunction( void )



  • {



  •      xTaskHandlexHandle;



  •      // 创建任务,保存任务句柄.



  •      xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );



  •      // ...



  •      // 使用句柄挂起创建的任务.



  •      vTaskSuspend( xHandle );



  •      // ...



  •      // 任务不再运行,除非其它任务调用了vTaskResume(xHandle )



  •      //...



  •      // 挂起本任务.



  •      vTaskSuspend( NULL );



  •      // 除非另一个任务使用handle调用了vTaskResume,否则永远不会执行到这里



  • }



使用特权

评论回复
6
keaibukelian|  楼主 | 2018-9-13 12:42 | 只看该作者
6.恢复挂起的任务6.1函数描述

      void vTaskResume( TaskHandle_txTaskToResume );

      恢复挂起的任务。

      通过调用一次或多次vTaskSuspend()挂起的任务,可以调用一次vTaskResume ()函数来再次恢复运行。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend必须置1,此函数才有效。

6.2参数描述
  • xTaskToResume:要恢复运行的任务句柄。

6.3用法举例


  • voidvAFunction( void )



  • {



  •          xTaskHandle xHandle;



  •      // 创建任务,保存任务句柄



  •      xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );



  •      // ...



  •      // 使用句柄挂起创建的任务



  •      vTaskSuspend( xHandle );



  •      // ...



  •      //任务不再运行,除非其它任务调用了vTaskResume(xHandle )   



  •           //...



  •      // 恢复挂起的任务.



  •      vTaskResume( xHandle );



  •      // 任务再一次得到处理器时间



  •      // 任务优先级与之前相同



  • }



使用特权

评论回复
7
keaibukelian|  楼主 | 2018-9-13 12:42 | 只看该作者
7.恢复挂起的任务(在中断服务函数中使用)7.1函数描述

      BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume );

      用于恢复一个挂起的任务,用在ISR中。

      通过调用一次或多次vTaskSuspend()函数而挂起的任务,只需调用一次xTaskResumeFromISR()函数即可恢复运行。

      xTaskResumeFromISR()不可用于任务和中断间的同步,如果中断恰巧在任务被挂起之前到达,这就会导致一次中断丢失(任务还没有挂起,调用xTaskResumeFromISR()函数是没有意义的,只能等下一次中断)。这种情况下,可以使用信号量作为同步机制。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskSuspend 和 INCLUDE_xTaskResumeFromISR 必须设置成1,此函数才有效。

7.2参数描述
  • xTaskToResume:要恢复运行的任务句柄。

7.3返回值

      如果恢复任务后需要上下文切换返回pdTRUE,否则返回pdFALSE。由ISR确定是否需要上下文切换。

7.4用法举例


  • xTaskHandlexHandle;               //注意这是一个全局变量







  • void vAFunction( void )



  • {



  •      // 创建任务并保存任务句柄



  •      xTaskCreate( vTaskCode, "NAME",STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );







  •      // ... 剩余代码.



  • }







  • void vTaskCode( void *pvParameters )



  • {



  •      for( ;; )



  •      {



  •          // ... 在这里执行一些其它功能







  •          // 挂起自己



  •          vTaskSuspend( NULL );







  •          //直到ISR恢复它之前,任务会一直挂起



  •      }



  • }







  • void vAnExampleISR( void )



  • {



  •      portBASE_TYPExYieldRequired;







  •      // 恢复被挂起的任务



  •      xYieldRequired = xTaskResumeFromISR(xHandle );







  •      if( xYieldRequired == pdTRUE )



  •      {



  •          // 我们应该进行一次上下文切换



  •          // 注:  如何做取决于你具体使用,可查看说明文档和例程



  •          portYIELD_FROM_ISR();



  •      }



  • }



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

4095

帖子

5

粉丝