点击上方"蓝字"关注我们
RTOS | 那么什么是RTOS?三大操作系统?(第十四天) |
---|
FreeRTOS | 原理介绍和资源get(第十四天) |
FreeRTOS | STM32F407 FreeRTOS移植(第十四天) |
FreeRTOS | 任务管理(第十四天) |
>>> 1、函数 taskYIELD 此函数用于进行任务切换,此函数本质上是一个宏。 2、函数 taskENTER_CRITICAL 进入临界区,用于任务函数中,此函数本质上是一个宏。 3、函数 taskEXIT_CRITICAL 退出临界区,用于任务函数中,此函数本质上是一个宏。 4、函数 taskENTER_CRITICAL_FROM_ISR 进入临界区,用于中断服务函数中,此函数本质上是一个宏。 5、函数 taskEXIT_CRITICAL_FROM_ISR 退出临界区,用于中断服务函数中,此函数本质上是一个宏。 6、函数 taskDISABLE_INTERRUPTS 关闭可屏蔽的中断,此函数本质上是一个宏。 7、函数 taskENABLE_INTERRUPTS 打开可屏蔽的中断,此函数本质上是一个宏。 8、函数 vTaskStartScheduler 启动任务调度器。 9、函数 vTaskEndScheduler 关闭任务调度器。 10、函数 vTaskSuspendAll 挂起任务调度器,调用此函数不需要关闭可屏蔽中断即可挂起任务调度器。 11、函数 xTaskResumeAll 此函数用于将任务调度器从挂起状态恢复。
>>>1.vTaskDelay 在UCOSIII 中延时函数OSTimeDly()可以设置为三种模式:相对模式、周期模式和绝对模式。在FreeRTOS中延时函数只有相对模式和绝对模式,在FreeRTOS中不同的模式用的函数不同,其中函数 vTaskDelay()是相对模式(相对延时函数),函数 vTaskDelayUntil()是绝对模式(绝对延时函数)。函数vTaskDelay()在文件 tasks.c中有定义,要使用此函数的话宏INCLUDE_vTaskDelay必须为1,函数代码如下: void vTaskDelay( const TickType_t xTicksToDelay ) 参数: xTicksToDelay:要延时的时间节拍数,该数值须大于0。否则直接调用函数portYIELD()进行任务切换。 时间节拍数:在这个FreeRTOS系统中为1ms 决定时间节拍数的宏 #define configTICK_RATE_HZ( ( TickType_t ) 1000 ) 时钟节拍时间:1/configTICK_RATE_HZ = 0.001s = 1ms
>>> 2.vTaskDelayUntil 函数 vTaskDelayUntil()会阻塞任务,阻塞时间是一个绝对时间,那些需要按照一定的频率运行的任务可以使用函数vTaskDelayUntil()。 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,const TickType_t xTimeIncrement ) 参数: pxPreviousWakeTime:上一次任务延时结束被唤醒的时间点,任务中第一次调用函数vTaskDelayUntil 的话需要将pxPreviousWakeTime初始化进入任务的 while()循环体的时间点值。在以后的运行中函数vTaskDelayUntil()会自动更新pxPreviousWakeTime。 xTimeIncrement:任务需要延时的时间节拍数(相对于pxPreviousWakeTime本次延时的节拍数)。 (1)挂起任务调度器。 (2)记录进入函数vTaskDelayUntil)的时间点值,并保存在xConstTickCount中。 (3)根据延时时间xTimeIncrement来计算任务下一次要唤醒的时间点,并保存在xTimeToWake中。可以看出这个延时时间是相对于pxPreviousWakeTime的,也就是上一次任务被唤醒的时间点。pxPreviousWakeTime、xTimeToWake、xTimeIncrement和xConstTickCount的关系如下图。
>>> 上图为任务主体,也就是任务真正要做的工作,(2)是任务函数中调用vTaskDelayUntil()对任务进行延时,(3)为其他任务在运行。任务的延时时间是xTimeIncrement,这个延时时间是相对于pxPreviousWakeTime的,可以看出任务总的执行时间一定要小于任务的延时时间xTimeIncrement!也就是说如果使用vTaskDelayUntil()的话任务相当于任务的执行周期永远都是xTimeIncrement,而任务一定要在这个时间内执行完成。这样就保证了任务永远按照一定的频率运行了,这个延时值就是绝对延时时间,因此函数 vTaskDelayUntil()也叫做绝对延时函数。
>>>2.1 微秒延时
void delay_us(uint32_t nus){ uint32_t told,tnow,tcnt=0; uint32_t temp=0; uint32_t reload=SysTick->LOAD; //系统定时器的重载值 uint32_t ticks=nus*(SystemCoreClock/1000000); //总共要等待的滴答数目 told=SysTick->VAL; //刚进入时的计数器值 //挂起所有任务[可选] vTaskSuspendAll(); while(1) { //获取当前计数值 tnow=SysTick->VAL; if(tnow!=told) { //SYSTICK是一个递减的计数器 if(tnow<told) tcnt+=told-tnow; else tcnt+=reload-tnow+told; told=tnow; //时间超过/等于要延迟的时间,则退出. if(tcnt>=ticks) break; } temp=SysTick->CTRL; //若定时器中途关闭了,跳出循环 if((temp & 0x01)==0) break; } //恢复所有任务[可选] xTaskResumeAll();}
2.2 毫秒延时
void delay_ms(u32 nms){ if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行 { if(nms>=fac_ms) //延时的时间大于OS的最少时间周期 { vTaskDelay(nms/fac_ms); //FreeRTOS延时 } nms%=fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时 } delay_us((u32)(nms*1000)); //普通方式延时}
注意:
1、项目中尽量使用系统提供的延时函数,如果需要us延时,尽量少用。
>>>内容有点多,下节公布源码。喜欢就支持一下。已发布资源网盘自取 通过网盘分享的文件:FreeRTOS 链接: https://pan.baidu.com/s/1UTJ0TdXkExIBauOeeINy9A?pwd=iuc6 提取码: iuc6
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。