0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FreeRTOS任务控制API函数介绍

安芯教育科技 来源:极术社区 作者:朱工 2021-03-19 10:19 次阅读

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 ); }}

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 ); // 需要周期性执行代码放在这里 } }

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 ) ) { // 当前优先级较高 } }

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. 任务挂起

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. 恢复挂起的任务

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. 恢复挂起的任务(在中断服务函数中使用)

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(); } }

原文标题:FreeRTOS系列第11篇---FreeRTOS任务控制

文章出处:【微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RTOS
    +关注

    关注

    22

    文章

    812

    浏览量

    119617
  • FreeRTOS
    +关注

    关注

    12

    文章

    484

    浏览量

    62159

原文标题:FreeRTOS系列第11篇---FreeRTOS任务控制

文章出处:【微信号:Ithingedu,微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    freertos最多支持多少个任务

    以下几个因素: 系统资源 :FreeRTOS能够支持的任务数量受到系统硬件资源的限制,特别是处理器的RAM大小和性能。RAM用于存储任务控制块(TCB)和
    的头像 发表于 09-02 14:21 875次阅读

    请问一下FREERTOS只能创建4个任务,修改哪个宏定义可以增加创建任务的数量?

    请问一下FREERTOS只能创建4个任务,修改哪个宏定义可以增加创建任务的数量?解决方法:增加FREERTOS的堆。
    发表于 05-13 06:44

    stm32在freertos中如何接收串口数据?

    之前STM32一致裸跑,最近使用FREERTOS感觉还不错。最近想把UART 弄成一个API,这样多个任务使用UART发送数据就不会乱码了。 发送数据的API已经写好了。数据接受用中断
    发表于 05-09 07:06

    求助,关于stm32f1使用freeRTOS和Fatfs时任务堆栈大小问题求解

    哪位使用过freeRTOS和Fatfs时,使用Fatfs系统的函数如f_open()等等时,此任务的堆栈大小大致需要多大,当前MAX_SS 定义为4096,我分配12K软件都跑飞了,请哪位使用分享一下经验,谢谢!~~?
    发表于 05-09 06:50

    用的cube生成的freertos工程,串口和任务通过邮箱通讯,结果任务反应很慢是怎么回事?

    初学freertos。用的cube生成的freertos工程,单片机型号位stm32f103vbt6。 建了三个人物,一个是串口任务,一个是LED每秒翻转一次,一个是空任务。 串口
    发表于 05-08 08:13

    freertos系统如何划分任务

    正在看freertos方面的教程,想请教下如何划分任务? 比如之前做的一个数据采集板,用到了单片机以下功能: 1,单片机通过SPI1和ADC芯片通讯,同时还要通过SPI控制ADC威廉希尔官方网站 部分的其他外围
    发表于 05-08 07:16

    freertos如何周期性的执行一个任务,比如200ms调用一次任务, 用定时器发消息?

    freertos如何周期性的执行一个任务,比如200ms调用一次任务, 用定时器发消息?有没有一个函数能直接实现
    发表于 05-07 08:21

    关于FreeRTOS任务划分及comsis_os函数使用的疑问求解

    当前任务挂起并唤醒下一个任务。比如在英国威廉希尔公司网站 ,接受到设置按键以后,就将当前任务——英国威廉希尔公司网站 任务挂起,resume设置英国威廉希尔公司网站 任务。 请问这样划分行吗?
    发表于 05-07 07:49

    FreeRTOS系统使用xTaskCreate产生的任务与osThreadDef 产生的线程有什么不同?

    请教下是要 FreeRTOS系统, 使用 xTaskCreate 产生的任务 与 osThreadDef产生的线程有什么不同?
    发表于 04-29 07:20

    freertos任务创建,每一个任务分配的内存是多大才好,怎么计算呢?

    小白刚刚接触freertos,想问一下就创建任务而言,每一个任务分配的内存是多大才好,怎么计算呢? 另外,每个任务的执行周期怎么确定?在任务
    发表于 04-23 06:39

    为什么CubeMX设计的FreeRTOS工程只能正常运行3个任务

    用CubeMX4.20设计的FreeRTOS工程有六个任务,出一个任务优先级较低外,另外几个都是较高优先级。发现只有3个任务是正常运行的,还有三个没有运行的迹象。用断点跟踪法在
    发表于 04-19 08:23

    FreeRTOS里在中断中挂起任务出错的原因?怎么解决?

    各位大佬,新手刚学习FreeRTOS,现在想在中断中挂起某个任务,我在教程里看到说有中断中的恢复函数xTaskResumeFromISR,但是没有在中断中的挂起函数,我搜了一下,有人说
    发表于 04-16 08:26

    FreeRTOS任务无故进入挂起状态的原因?

    请教大家一个问题,我子啊使用FreeRTOS的时候创建了一个以太网的任务任务在使用的过程中被无故挂起,请问一下出现这种现象有哪几种原因呢?
    发表于 04-09 07:20

    verilog中函数任务对比

    在verilog中,函数任务均用来描述共同的代码段,并且在模式内任意位置被调用,提高代码效率,让代码更加的直观,提高代码可读性。但是在实际使用的过程中,函数任务也存在诸多的不同,下
    的头像 发表于 02-12 18:43 885次阅读

    无法在AURIX™ Development Studio中调试freeRTOS任务怎么解决?

    我们正在开发 AURIX™ TriCore™ TC389 控制器。 你能否建议需要使用哪个 RTOS 以及首选 IDE调试器来进行开发过程? 此外,我无法在 AURIX™ Development Studio 中调试 freeRTOS
    发表于 01-18 07:41