RTOS任务调度思想汇总_2(任务时间管理)

1、任务是独立的,并且初始化后进入死循环(格式像主函数);
2、① 任务的任务控制块:首先要定义每个任务的任务控制块变量,任务控制块只是一个数据类型(数据结构),
其数据结构定义的元素有任务堆栈栈顶地址,任务堆栈大小,任务优先级,任务时间计数值,前后任务控制块的指针变量(地址),任务当前状态值等;用于连入/连出链表,查表等;
② 任务堆栈:存放断点pc指针,cpu内部寄存器组值;
③ 任务代码:要实现的逻辑,时间管理;
以上①②③每个任务都有属于自己的一套任务控制块,任务堆栈,任务代码;
3、任务创建时,调用任务堆栈初始化函数,将任务的入口地址及堆栈栈顶地址,堆栈大小等内容相继存入其任务堆栈,赋值给事先定义好的其任务控制块变量,使其被该任务独有化;
4、任务时间管理,一般每个任务死循环最后有个OSTimeDly(时间)函数;
上下文切换时会将该任务的断点指针(当前pc指针,注意是断点地址,不是该任务初始化堆栈时的任务入口地址),任务堆栈栈顶指针及相关寄存器值等内容存入其任务堆栈里,保存起来亦保护现场
(从cpu内部寄存组相关寄存器出栈到其任务堆栈/赋值给其任务控制块变量);
而cpu内部寄存器组,pc程序计数器,sp内存堆栈指针会被存入(压入)将要切换去执行的任务的那一套东西(上次它自己被别人切换掉时的现场数据值)–入栈;
所以除了最开始上电第一次切换调用到该任务时从任务函数入口地址执行一遍任务函数中的初始化外,剩下的时间在各就绪任务切换中都是在执行各任务的 for(;;)/while(1) 死循环部分
5、rtos有专门的时基,一般为systick硬件定时器,1ms(时间用户可设置)周期性执行systick中断ISR(周期性中断),通过该中断主要是为了执行遍历所有任务中OSTimeDly中的延时时间变量递减,
【任务调度函数被调用的地方】
第一个地方:
void OSTimeDly(任务定时时间)
{
if(任务定时时间 == 0)
{
OSSched(); //任务调度函数 该函数调用OSCtxSw()进行任务切换
}
}
———————————————————————————
void Task1(任务参数)
{
OSTimeDly(任务定时时间);//定时时间到执行任务调度函数
}
———————————————————————————
第二个地方:
void OSIntExit()
{
//任务优先级查表,获取最高优先级任务相关变量
if(调度器未锁 && 中断无嵌套&&任务最高优先级不是当前被中断的任务优先级)
{
OSIntCtxSw(); //中断级任务调度函数,执行任务调度
}
}
———————————————————————————
void OS_SysTickISR() // 系统定时器ISR函数
{
OSIntEnter() ; // 进入中断ISR函数
OSTimeTick() ; //该函数作用是遍历各任务延时定时边量递减,判断定时没到的任务不进入就绪态,到的使能就绪态;
。。。
OSIntExit(); // 退出中断ISR函数
}
———————————————————————————
【注意】系统定时器中断和其他中断都会调用退出中断ISR函数OSIntExit()进行中断级任务调度;
只是其他中断没有OSTimeTick()的处理

遍历所有创建的任务的延时时间变量清0,使任务重回就绪态(除了被用户悬挂的任务);
6、rtos的任务时间管理,抢占型(参考下图),死循环内核特点,为保证cpu不被高优先级任务独占,除空闲任务外,其余任务都必须使用OSTimeDly延时函数,
作用使当前任务延时一段时间并进行一次上下文切换即任务调度,具体实现逻辑是通过判断延时变量>0时(即延时没到),就将该任务的优先级从任务就绪表中注销,使其不被就绪,
下次自然就不会被调度器执行;
然后调用任务调度函数OSSched(),进行上下文切换;
并将延时变量值赋值给其任务控制块中的延时变量元素,然后通过系统systick定时器执行周期性中断ISR来递减;
7、注意任哲的μcos-ii中OSTimeDly函数中逻辑是把任务切换函数放到延时变量>0的条件里面了,放外面还是放条件里面,其实不太影响;
总归是进入该任务后,任务按顺序执行,执行到该判断时,延时变量>0,清就绪状态,进行任务调度;独立的延时变量会在systick的周期性ISR中递减(遍历所有创建的任务)并重新使该任务就绪标志置1,那么调度器通过查任务就绪表,也就会重新执行该任务;
8、假如创建有3个任务,task0(prio = 0,time = 3s),task1(prio = 1,time = 1s),那么执行结果:011101110 。。。。。
所以理论上该任务设置延时多久,该任务就会等多久才执行一次(任务自身的代码执行时间很短情况下);
9、任务调度分两种:
① 任务级调度:高优先级任务能正常执行完,然后进入延时函数注销就绪,再调用上下文切换到低优先级任务执行,延时时间到恢复就绪,低优先级任务调度后会重新切换到高优先级任务执行;
② 中断级调度:响应异常/中断后执行其ISR(这里区别于用来作为时基定时器systick的中断响应,因为它们的作用是不同的),并在其ISR中调用任务调度函数,保护现场等逻辑,执行完该中断ISR后
不一定返回被该中断打断的任务,而是会查任务就绪表执行任务级别最高的就绪任务;
中断级调度器和任务级调度器的逻辑有所不同,但是大体思想是相同的;

https://blog.csdn.net/gtkknd/article/details/52215495

在这里插入图片描述
在这里插入图片描述
【注意】当某一任务执行时间过久,超过定时延时时间,虽然不影响任务间正常切换,但是对于该任务而言就从一个定时延时时间就可以执行完一遍(执行一次,从头开始执行),变成多个定时延时时间才可以执行完一遍(进入该任务执行,任务中间某处),该任务中相关函数参数变量时基不准,不能再依靠该定时延时时间来作为其时基;??????
示例:假设sysTick配置1ms时基,
************ Time10msHandle start systickCnt=21933
************ Time10msHandle end systickCnt=21937
************ SignalHandle start systickCnt=21942
************ SignalHandle end systickCnt=21947
************ KeyHandle start systickCnt=21951
************ KeyHandle end systickCnt=21956
************ Time20msHandle start systickCnt=21960
************ Time20msHandle end systickCnt=21964
************ SignalHandle start systickCnt=21969
************ SignalHandle end systickCnt=21974
************ KeyHandle start systickCnt=21979
************ KeyHandle end systickCnt=21983
************ Time10msHandle start systickCnt=21987
************ Time10msHandle end systickCnt=21992
************ SignalHandle start systickCnt=21996
************ SignalHandle end systickCnt=22001
************ KeyHandle start systickCnt=22006
************ KeyHandle end systickCnt=22010
************ Time20msHandle start systickCnt=22014
************ Time20msHandle end systickCnt=22019
************ SignalHandle start systickCnt=22023
************ SignalHandle end systickCnt=22028
************ KeyHandle start systickCnt=22033
************ KeyHandle end systickCnt=22037
************ Time10msHandle start systickCnt=22042
************ Time10msHandle end systickCnt=22046
************ SignalHandle start systickCnt=22051
************ SignalHandle end systickCnt=22056
************ KeyHandle start systickCnt=22060
************ KeyHandle end systickCnt=22065
************ Time20msHandle start systickCnt=22069
************ Time20msHandle end systickCnt=22073
************ SignalHandle start systickCnt=22078
************ SignalHandle end systickCnt=22083
************ KeyHandle start systickCnt=22088
************ KeyHandle end systickCnt=22092
************ Time10msHandle start systickCnt=22096
************ Time10msHandle end systickCnt=22101
************ SignalHandle start systickCnt=22105
************ SignalHandle end systickCnt=22110

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
RTOS(Real-Time Operating System)任务调度是实时操作系统中非常重要的一部分,它负责协调多个任务的执行,使得它们能够按照一定的优先级、时间片或其他算法在 CPU 上运行。RTOS 任务调度的实现方式可以分为两种:抢占式和非抢占式。 1. 抢占式任务调度 抢占式任务调度是指当一个优先级更高的任务就绪时,它可以抢占当前正在运行的任务并立即执行。在抢占式任务调度中,每个任务都有一个优先级,调度器会根据任务的优先级来决定其执行顺序。当一个高优先级任务就绪时,调度器会立即抢占当前正在执行的任务并执行高优先级任务。抢占式任务调度实现的关键在于中断处理,当一个中断发生时,调度器会暂停当前正在执行的任务并执行中断服务程序,然后在中断服务程序执行完毕后恢复原来的任务继续执行。 2. 非抢占式任务调度 非抢占式任务调度是指任务只有在自己执行完毕或主动放弃 CPU 时才会被其他任务抢占。在非抢占式任务调度中,每个任务也有一个优先级,但是任务的执行顺序只能由任务本身控制。当一个任务执行完毕或主动放弃 CPU 时,调度器会根据任务的优先级来选择下一个任务执行。非抢占式任务调度实现的关键在于任务的协作,每个任务需要在执行过程中主动让出 CPU,以便其他任务得到执行的机会。 无论是抢占式还是非抢占式任务调度,都涉及到任务的上下文切换,即保存当前任务的上下文,以便在任务再次执行时恢复其状态。上下文切换需要保存任务的 CPU 寄存器、堆栈指针等信息,并修改当前任务的状态(如就绪、阻塞等),然后切换到下一个任务的上下文。任务的上下文切换是一个比较耗时的操作,因此在任务调度的实现中需要尽量减少上下文切换的次数,提高任务的执行效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUR0608

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值