μC/OS中高优先级任务一旦处于就绪态总能获得C

μCOS的任务切换时间:1.任务创建时 2.任务挂起时 3.任务恢复 4.任务延时时 6.任务释放信号量时 7.任务释放互斥信号量时 8.任务请求消息邮箱时 9.任务释放消息队列时 10 中断退出时(OSINTEXIT()函数中) 

任务之前的切换应该就是利用时钟中断来实现,当OS运行完一个时钟片后会产生一个中断(定时器的中断)异常,PC指针立即跳转到异常向量表执行处理异常的代码,随后会导致OS执行一次任务调度。整个过程分析如下:

产生异常后执行的第一条指令

b     HandlerIRQ

跳转到HandlerIRQ,而HandlerIRQ是一条宏命令,定义如下

HandlerIRQ    HANDLER HandleIRQ

宏体如下:

MACRO

$HandlerLabel HANDLER $HandleLabel

$HandlerLabel

       sub  sp,sp,#4

       stmfd      sp!,{r0}                //后面代码需要使用R0寄存器,所以先将其入栈。

ldr     r0,=$HandleLabel    //此处是将HandeIRQ的地址赋给寄存器R0Handler中存放是中断服务函数汇编部分的入口地址,此汇编用来计算中断服务函数的入口地址,所有IRQ中断通用。HandeIRQ的赋值操作在后面。

       ldr     r0,[r0]                    //此处读取R0中的内容,即中断服务函数汇编部分的入口地址

       str     r0,[sp,#4]       

       ldmfd   sp!,{r0,pc}            //出栈,栈中R0的值重新赋给R0,中断服务函数汇编入口地址复制给PC。相当于跳转到汇编入口地址处。

       MEND

HandeIRQ中存放汇编入口地址的代码如下。

ldr   r0,=HandleIRQ               //HandeIRQ地址

       ldr   r1, =OS_CPU_IRQ_ISR              //OS_CPU_IRQ_ISR地址

       str   r1,[r0]                                 //OS_CPU_IRQ_ISR地址赋值给HandeIRQ

 

       执行完宏体的结果应该是跳转到OS_CPU_IRQ_ISR

OS_CPU_IRQ_ISR      

 

       STMFD   SP!, {R1-R3}                   //后面会皆用这三个寄存器,所以先将其入栈

       MOV     R1, SP                              //IRQ模式下的当前SP指针保存到R1

       ADD     SP, SP, #12             //调整SP,使其指向R1~R3入栈前的地址

       SUB     R2, LR, #4              //LR保存的是返回值的地址,但是不同的异常产生的LR不同。IRQ异常时,LR保存的是下一条将被执行的指令+4。所以此处需要LR-4。来调整。

       MRS     R3, SPSR                          ; Copy SPSR (Task CPSR)  

 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/c891583336a3126b64689d39989d88e0.html