FreeRTOS任务控制API函数介绍

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任务控制
文章出处:【微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。


全功能报警控制主机的功能介绍
特斯拉“国产化”落下实锤 建年产50万超级工厂
触发器的输出状态由什么决定
拆解:公牛67W氮化镓快充插座,采用智融SW3516P主控芯片!
跨足边缘AI芯片成重要策略 芯片亦为台厂面对边缘运算AI趋势之主要切入点
FreeRTOS任务控制API函数介绍
联想大数据平台与银河麒麟服务器操作系统已完成兼容性测试
怎样去发挥工业数据优势发展人工智能
TikTok再次上诉美国政府 请求审查CFIUS的行动
物联网成无锡发展新名片,中国标准引导国际物联网发展
贸泽备货Laird Connectivity FlexPIFA 6E Wi-Fi三频天线
2019中国(深圳)集成电路峰会成功举办 深圳IC产业数据亮眼
4G芯片厂商以价换量 多模多频研制成重点
物联网在改变世界之前我们应该准备什么
RFID分类是怎么样的情况
第三代半导体材料有何优势
MA5680T全光接入平台
苹果13pormax内存
LMZ20502SILR替换解决方案
史上最强Mac出现 苹果WWDC宣布6大重点!