Free RTOS:任务状态,任务管理与调度理论
目录1.任务状态1.1 FreeRTOS的任务状态1.2 阻塞状态(Blocked)1.3 暂停状态(Suspended)原型如下1.4 就绪状态(Ready)1.5 完整的状态转换图1.6 代码2.任务管理与调度理论2.1 调度2.2 FreeRTOS调度STM32CubeMXFreeRTOS源码代码理解图同优先级的任务之后FreeRTOS系统里面有一个Tick中断1ms一次中断理解图代码理解图不同优先级的任务3.空闲任务3.1 空闲任务的特点3.2 空闲任务(Idle 任务)的作用一个场景3.3 空闲任务不够4.Delay 函数4.1 两个 Delay 函数这 2 个函数原型如下4.2 vTaskDelay原理例如vTaskDelay(5)例子假设函数A第一次运行1ms第二次运行10ms第三次运行5ms假设1个Tick为1ms4.3 vTaskDelayUntil原理例子假设函数A第一次运行1ms第二次运行10ms第三次运行5ms假设1个Tick为1ms1.任务状态代码在09_task_suspend里这个代码相较于08_task_priority添加音乐暂停/恢复功能1.1 FreeRTOS的任务状态运行(Runing)非运行(Not Running)然后非运行状态分为三种阻塞状态(Blocked)暂停状态(Suspended)就绪状态(Ready)1.2 阻塞状态(Blocked)在日常生活的例子中母亲在电脑前跟同事沟通时如果同事一直没回复那么母亲的工作就被卡住了、被堵住了、处于阻塞状态(Blocked)。重点在于母亲在等待阻塞状态会将程序一直卡在一个地方等待如果有设置等待时间比如超时时间到达了这个时间就会结束阻塞状态1.3 暂停状态(Suspended)在日常生活的例子中母亲正在电脑前跟同事沟通母亲可以暂停好烦啊我暂停一会领导说你暂停一下当前执行的任务调用vTaskSuspend函数让自己暂停或是其他任务调用vTaskSuspend函数让当前运行的函任务暂停原型如下vTaskResume恢复函数让暂停的任务从暂停的位置开始运作1.4 就绪状态(Ready)这个任务完全准备好了随时可以运行只是还轮不到它。这时它就处于就绪态(Ready)当任务被创建出来时就进入了就绪状态了1.5 完整的状态转换图1.6 代码2.任务管理与调度理论优先级、链表管理、任务切换、tick空闲任务代码在10_idle_task里2.1 调度相同优先级的任务轮流运行最高优先级的任务优先级运行高优先级的任务未执行完低优先级的任务无法运行一旦高优先级任务处于就绪状态马上就会运行最高优先级的任务有多个会轮流运行2.2 FreeRTOS调度STM32CubeMXFreeRTOS源码代码理解图同优先级的任务当前的两个任务的优先级为24且同级一个优先级可以有多个任务创建完这三个任务之后创建一个优先级为0的空闲任务然后就启动调度器在创建第一个任务的时候会先放到对于优先级的链表中的就绪链表中有一个全局指针pxCurrentTCB然后这个全局指针会在同优先级的链表中继续指向后续创建的任务直至最后一个创建的任务当真正启动调度器的时候最在全局指针指向的任务开始所以最后创建的任务反而最先开始执行之后FreeRTOS系统里面有一个Tick中断1ms一次中断在Tick中断里会执行以下1.计时累加作为时钟基准2.发起一次调度遍历ReadyTasksLists从高优先级到低优先级空链表就下一个找到第一个非空的链表把全局指针pxCurrentTCB指向下一个任务最开始创建的任务计时累加达到1ms时再次进行计时累加再发一次任务调度遍历ReadyTasksLists从高优先级到低优先级找到非空的链表把全局指针pxCurrentTCB指向当前任务的下一个任务循环往复如此理解图代码理解图不同优先级的任务假设正在进行默认的任务优先级为24Tick中断为1ms在还没到1ms的时候有一个优先级25的任务C创建了那么任务C会在就绪链表ReadyTasksLists中里立马执行然后任务C里面又有一个等待函数为2个Tick这个时候任务C会从就绪状态变为阻塞状态从ReadyTasksLists中被移出到DelayTasksLists中之后任务的调度会继续会调度默认任务的下一个任务ATick中断又到了继续进行调度执行任务B这个时候2个Tick了那么这个时候的Tick中断相比于之前的Tick中断会多一个过程判断任务C是否到了时间然后从DelayTasksLists移出到ReadyTasksLists任务C从阻塞状态变为就绪状态之后立马执行任务C如果任务C还调用了暂停函数vTaskSuspend任务C从就绪状态或阻塞状态进入了暂停状态那么这个时候任务C不论是在ReadyTasksLists还是在DelayTasksLists都会进入xSuspendedTaskLists只要任务C调用了恢复函数vTaskResume才会从xSuspendedTaskLists进入ReadyTasksLists从暂停状态进入就绪状态之后立马执行任务C3.空闲任务3.1 空闲任务的特点空闲任务优先级为 0它不能阻碍用户任务运行空闲任务要么处于就绪态要么处于运行态永远不会阻塞3.2 空闲任务(Idle 任务)的作用空闲任务(Idle 任务)的作用之一释放被删除的任务的内存一个场景这个时候想要退出整个程序卡死的状态就需要使用vTaskDelete函数自杀vTaskDeleteNULL空闲任务收尸空闲任务释放被删除任务的内存他杀vTaskDelete错误任务的句柄假设是任务A删除了任务B那么就是任务A来释放任务B的内存3.3 空闲任务不够但是如果ReadyTasksLists有太多任务“自杀”空闲任务就会不够来不及释放这些任务的内存那么就是造成内存不够分配的现象就需要良好的编程习惯来防止ReadyTasksLists有太多任务“自杀”的现象1.事件驱动2.在需要延时的地方使用FreeRTOS中的内置延时函数vTaskDelay()不要使用死循环也就是当前vTaskDelay()会使得该任务释放CPU资源进入DelayTasksLists中这样ReadyTasksLists中就不会有太多的“自杀任务”空闲任务就有更多的时间去释放那些没有用到延时函数的任务的内存简而言之就是让这个任务放弃调度4.Delay 函数4.1 两个 Delay 函数vTaskDelay至少等待指定个数的 Tick Interrupt 才能变为就绪状态vTaskDelayUntil等待到指定的绝对时刻才能变为就绪状态这 2 个函数原型如下vTaskDelay和 vTaskDelayUntil都是以Tick为单位4.2 vTaskDelay原理vTaskDelay(n个Tick)例如vTaskDelay(5)例子假设函数A第一次运行1ms第二次运行10ms第三次运行5ms假设1个Tick为1ms可以发现vTaskDelay延时函数是规定了多少时间延时就是阻塞函数A多少时间可见函数A每次运行间隔的时间不是周期的4.3 vTaskDelayUntil原理vTaskDelayUntil(当前计数值n个Tick)一般要配合xTaskGetTickCount()函数获取当前计数值例子假设函数A第一次运行1ms第二次运行10ms第三次运行5ms假设1个Tick为1ms可以发现vTaskDelayUntil延时函数是先给当前的计数值然后根据设定了15个Tick15个Tick缺多少就补多少将函数的两次运行时间规定为15个Tick以实现周期运行函数
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2491452.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!