嵌入式开发交流网论坛
标题:
任务调度的汇编实现
[打印本页]
作者:
Iq37di7
时间:
2018-11-7 12:55
标题:
任务调度的汇编实现
[attach]16028[/attach]
0x01
摘要
前面对任务调度系统的主要内容进行了详细的介绍,剩下任务调度的最后一部分,也就是任务调度的汇编实现,这部分和具体的平台有关,也是
ucos
移植需要修改的地方。一般这部分都有别人已经移植成功的,如果大家只是拿来用的,不是具体研究其实现的机理的话,可以不必深究,因为这部分涉及到具体的平台。本文以
stm32
为例。
0x02
引言
汇编是最接近芯片工作原理的部分,也是最难学习的部分,对于汇编大家只需要根据自己需要进行学习,不必完整学习,因为完整学习花费的代价很高。
因为汇编语言的高效性,所以一般对于像任务调度这种很频繁的操作才建议使用汇编来实现,这样可以极大的提高系统的效率。对于汇编的分析涉及到芯片的具体工作方式,这里我们仅对汇编的功能进行分析,其涉及到的芯片深层工作原理大家自行翻阅芯片手册。
0x03
原理
首先我们看一下任务调度函数
OS_CPU_PendSVHandler
,这是
PendSV
的中断函数,前面我们说了,
ucos
是通过出发
PendSV
中断实现的任务调度。因为
PendSV
在所有芯片级的中断中级别最小,不会对芯片级的其他中断造成影响,以便等到芯片其他的重要中断完成后才进行调度,保证了芯片工作的稳定性和可靠性。我们对其代码进行分段讲解
OS_CPU_PendSVHandler
CPSID I
MRS R0, PSP
CBZ R0, OS_CPU_PendSVHandler_nosave
这一段是关闭系统的中断避免在任务切换时被其他中断打扰,并将
PSP
中的内容加载到
R0
中,判断
R0
是否为零,若为零则表示第一次切换任务,直接跳转到
OS_CPU_PendSVHandler_nosave
而不需要进行下面的寄存器存储操作。
SUBS R0, R0, #0x20
STM R0, {R4-R11}
LDR R1, =OSTCBCur
LDR R1, [R1]
STR R0, [R1]
这一段表示对当前任务的寄存器
R4-R11
进行存储,这里
R0
~
R3
、
LR
、
PC
指针会自动存储到
PSP
指向的堆栈,这是由芯片自动完成的,无需进行人工操作。然后将当前堆栈的栈顶指针存放到
TCB
中的
OSTCBStkPtr
变量中。
OS_CPU_PendSVHandler_nosave
PUSH {R14}
LDR R0, =OSTaskSwHook
BLX R0
POP {R14}
这一段主要是为了实现
systick
的钩子函数
OSTaskSwHook
的实现,现将
R14
入栈然后执行函数,返回,将
R14
出栈。
LDR R0, =OSPrioCur
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
这一段主要是将最高优先级赋值给当前优先级。
LDR R0, =OSTCBCur
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
这一段是将最够优先级的任务
TCB
赋值给当前任务的
TCB
。
LDR R0, [R2]
LDM R0, {R4-R11}
ADDS R0, R0, #0x20
MSR PSP, R0
ORR LR, LR, #0x04
CPSIE I
BX LR
这一段将最高优先级任务的
R4-R11
寄存器内容恢复,然后将
R0
地址跳过芯片自动存储的区域,并将地址赋值给
PSP
,然后将
LR
寄存器
4
字节对其,打开全局中断,跳转到调用函数的位置。
0x04
结论
这一篇将
ucos
任务切换的汇编实现进行了详细的讲解,这些汇编代码和具体的平台有关,有时候相同的芯片代码可能也不同,但是其思路是一样的,都是存储当前任务的寄存器值,然后恢复将要调用任务的寄存器值。
OS
你的努力
我的付出
大家的支持
终将化作生命辉煌
如有任何疑问请后台回复
或添加
作者
Waiting_B_H
知识传播是一种美德
让更多人少走弯路
才能有更多人与你携手前进
欢迎扫码一起分享经验
[attach]16029[/attach]
欢迎光临 嵌入式开发交流网论坛 (http://www.dianzixuexi.com/bbs/)
Powered by Discuz! X3.2