Nucleus Task切换及中断之上下文保存

来源:互联网 发布:淘宝帐号管理在那里 编辑:程序博客网 时间:2024/05/20 01:36

MTK上用的实时操作系统是Nucleus操作系统。

1.操作系统自身调度

在Task切换(即操作系统调度,如当前msg queue为空,kal_retrieve_eg_events未获取到符合条件的事件,又或obtain semaphore失败等等)时,

操作系统会保存必要的上下文, 以供下次重新调度到该任务时,能继续执行,即实现了操作系统的基本功能, 多任务调度。

 

如接收消息形势如下:

void
mmi_task_main( task_entry_struct *task_entry_ptr)
{
......
 while (1) {

  ......
  receive_msg_ext_q();

  ...... 

 }

......
}

 

若当前Task queue中没有msg, 则该task就会挂起, 保存上下文, 并切换到操作系统调度。

可参考如下call stack:

TCT_Control_To_System()

TCC_Suspend_Task()

QUC_Receive_From_Queue()

QUCE_Receive_From_Queue()

kal_deque_msg()

receive_msg_ext_q()

mmi_task_main()

 

参看TCT_Control_To_System汇编

TCT_Control_To_System:   

                           ;禁止fiq和irq

                           mrs     r0,cpsr
                           orr     r0,r0,#0xC0
                           msr     cpsr_cxsf,r0

                           ;保存最少的必要的上下文
                           stmdb   r13!,{r4-r12,r14}

                           ;保存r14的状态,最后一位为0还是1
                           mov     r2,r14
                           mov     r2,r2,lsl #0x1F
                           mov     r2,r2,lsr #0x1A
                           str     r2,[r13,#-0x4]!

                           ;操作系统调度的上下文切换,栈顶最后flag置为0
                           mov     r2,#0x0
                           str     r2,[r13,#-0x4]!

                           ........

                            ;之后会保存该r13, 并且切换到系统堆栈进行os调度(即_TCT_Schedule)

 

即os调度模式下切换task时保存的上下文为

Status = 0
r14.last bit <<5
R4
R5
R6
R7
R8
R9
R10
R11
R12
R15 (PC)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Q:为何os调度只需要保存以上这些context?R0-R3以及R14不需要吗?
A:R0~R3是用作函数传参, TCT_Control_To_System是一个空参函数, 故无需保存R0~R3?
 
Q:为何保存r14的最后一位左移5位后的值(即如果r14最后一位为1的话,保存0x20,如果r14最后一位为0的话, 保存0)?
A:见函数TCT_No_Start_TS_1
......
         MRS     r0,CPSR                     ; Pickup current CPSR
......
         LDR     r2,[r13], #4               ; Pop off the state mask
         ORR     r0,r0,r2                   ; Set appropriate state
......
即若r14最后一位为1, 当任务调度回来时,将CPSR的T位置为1,否则为0。
即保存的为当前函数的状态, 为ARM态还是Thumb态。
ARM代码和Thumb代码的切换是以bx和blx实现的,blx label形式必定会改变处理器状态,即当前是ARM的切换到Thumb,当前是Thumb的切换到ARM。
blx Rm或bx Rm则根据Rm[0]推算目标状态,若Rm[0]为0, 则处理器状态会切换到(保持住)ARM态, 若Rm[0]为1, 则处理器状态会切换到(保持住)Thumb态。
运行在Thumb模式下,在函数调用过程中, r14存放的为函数返回地址, 即trace32当前指令的下一行汇编, 但最后一位是根据当前CPU状态设定。
 
2.中断调度(异常)
中断的优先级比Task高,故当中断来时,会将当前Task挂起, 去跑中断处理函数, 故此类情况也需要保存上下文。
此类改变PC的行为是由硬件的中断口实现的。
MTK的中断实现其实是ARM本身异常机制中的IRQ模式。
参看bootarm.s的中断向量表:
INT_Initialize_Addr  DCD   INT_Initialize
Undef_Instr_Addr     DCD   Undef_Instr_ISR
SWI_Addr             DCD   SWI_ISR
Prefetch_Abort_Addr  DCD   Prefetch_Abort_ISR
Data_Abort_Addr      DCD   Data_Abort_ISR
Undefined_Addr       DCD   0              ; NO LONGER USED
IRQ_Handler_Addr     DCD   INT_IRQ_Parse
FIQ_Handler_Addr     DCD   INT_FIQ_Parse
 
其中INT_IRQ_Parse即为普通中断解析函数, 其中部分代码如下:
    BL      TCT_Interrupt_Context_Save      ; Call context save routine
    BL      isrC_Main
    B       TCT_Interrupt_Context_Restore
参考函数TCT_Interrupt_Context_Save
该函数即实现中断保存上下文功能。