ucosII任务切换是怎样实现的
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
UC/OS-II学习笔记之——任务切换是怎样实现的问题是,
o Uc/OS-II如何切换任务?通过任务调度器OS_Sched(),那么谁在调用这个函数?
o CPU在这里肯定有作用,因为任务切换必然涉及到CPU寄存器的入栈和出栈,
那么这一块工作是如何完成的?
书上讲:为了做到任务切换,运行OS_TASK_SW(),人为模仿一次中断。中断服务子程序或陷阱处理(trap hardler),也称作事故处理(exception handler),必须给汇编语言函数OSCtxSw()提供中断向量[1.92]。
那么,“人为模仿一次中断”是什么意思?
是指:OS_TASK_SW()触发了一个中断,由中断完成了任务切换?
阅读源代码,查找答案……
#define OS_TASK_SW()OSCtxSw()//这是一个宏调用,定义在os_cpu.h,Os_cpu_a.asm中定义了OSCtxSw
NVIC_INT_CTRL EQU0xE000ED04
NVIC_PENDSVSET EQU0x10000000
;******************************************************************************
;PERFORM A CONTEXT SWITCH(From task level)
;void OSCtxSw(void)
;
;Note(s):1)OSCtxSw()is called when OS wants to perform a task context switch.This function
;triggers the PendSV exception which is where the real work is done.
;******************************************************************************
OSCtxSw
LDR R0,=NVIC_INT_CTRL;Trigger the PendSV exception(causes context switch) LDR R1,=NVIC_PENDSVSET
STR R1,[R0]
BX LR
注释说明该段汇编代码触发了一个PendSV的异常。
在《cortex-M3权威指南》中搜索关键词“PendSV”,可悬挂请求pend able request,在《2.9中断和异常》表7.1“系统异常清单”所列举的异常类型中,定义PendSV为“为系统设备而设的可悬挂请求”[2.109]
(中断优先级PendSV>SysTick>外部中断)
那么,这个PendSV异常的作用到底是什么?
PendSV典型使用场合是上下文切换(任务间切换)。上下文被触发的条件是:[2.125] o系统滴答定时器(SYSTICK)中断(轮转调度中需要)
o执行一个系统调用(TASK level code)
个中事件的流水账记录如下:
(1)任务A呼叫SVC来请求任务切换(例如,等待某些工作完成)
(2)OS接收到请求,做好上下文切换的准备,并且悬起一个PendSV异常。
(3)当CPU退出SVC后,它立即进入PendSV,从而执行上下文切换。
(4)当PendSV执行完毕后,将返回到任务B,同时进入线程模式。
(5)发生了一个中断,并且中断服务程序开始执行
(6)在ISR执行过程中,发生SysTick异常,并且抢占了该ISR。
(7)OS执行必要的操作,然后悬起PendSV异常以作好上下文切换的准备。
(当SysTick退出后,回到先前被抢占的ISR中,ISR继续执行
(9)ISR执行完毕并退出后,PendSV服务例程开始执行,并且在里面执行上下文切换
(10)当PendSV执行完毕后,回到任务A,同时系统再次进入线程模式
中断正在执行,禁止上下文切换。否则中断被延时,而延时时间不可预知——这是实时系统不能容忍的。
早期解决办法,无中断执行时,才执行上下文切换(切换期间无法响应中断)。弊端在于任务切换可能被拖延的很久。[2.126]
PendSv可以解决这个问题,OS会悬起一个PendSv,PendSv异常处理函数处理上下文切换请求——
(1).如果还有未处理完的ISR(图7.17后半段SysTick触发了上下文切换),PendSv被悬起,延迟上下文切换请求,直到处理完ISR后才执行上下文切换;
(2).如果没有任何ISR(图7.17前半段),则立刻调用PendSV异常处理函数完成上下文切换。
需要把PendSv编程为最低优先级的异常。也就是说,PendSv可以像普通中断一样被悬起,OS可以利用它缓期执行一个异常(PendSV)——在其它重要任务完成之后才执行动作(上下文切换)。
悬挂PendSv的方法是:往NVIC的PendSv悬起寄存器中写1。悬起后,如果优先级不够高,则将缓期执行。ICSR(Interrupt Control and State Register0xE000ED04)[bit28]
具体的程序调试:
执行系统函数(悬起PendSV异常的手段之一)OSTimeDlyHMSM(),调用OSTimeDly(),调用task scheduler OS_Sched(),终于执行这个宏调用,调用执行OSCtxSw(),(go to definition of OSCtxSw却不能跳转到汇编代码!),汇编代码把1写入中断控制及状态寄存器寄存器ICSR[bit28]从而悬起一个PendSV异常,这是上图7.17中的步骤2,
Void OS_Sched(void)//任务调度器
{
关中断;
if(没有中断&&没有关调度器)
OS_TASK_SW();//在这里悬起PendSV异常,开中断前先在PendSV Handler设置断点开中断;
}
执行完开中断语句后,程序立刻跳到PendSV异常处理函数PendSV Handler(在此处),这个跳转是如何完成的?具体的入栈、出栈涉及到CPU的哪些寄存器,操作是如何完成的?
执行完PendSV Handler后跳转到空闲任务,实现了任务切换: