FreeRTOS是如何工作的--AVR 上下文切换
The AVR Context
上下文切换要求保存完整的上下文。在AVR MCU中,上下文包括
1. 32位通用寄存器。Gcc开发工具假定寄存器R1设定为0
2. 状态寄存器。状态寄存器的值影响指令的执行,必须通过上下文切换保存(preserved)
3. 程序计数器(PC).恢复执行后,一个任务必须从上次被挂起的地方继续执行。(a task must continue execution from the instruction that was about to be executed immediately prior to its suspension.)
4. 两个stack指针寄存器

Saving the Context
每个时实任务都有它自己的stack 内存区域,所以上下文可 简单的通过将寄存器压入到任务栈 来保存上下文。保存AVR的上下文是一个不可避免的要使用到汇编语言的地方。
portSAVE_CONTEXT() 是作为一个宏来实现的,源代码在下面给出
#define portSAVE_CONTEXT() \
asm volatile ( \
"push r0 \n\t" \ (1)
"in r0, __SREG__ \n\t" \ (2)
"cli \n\t" \ (3)
"push r0 \n\t" \ (4)
"push r1 \n\t" \ (5)
"clr r1 \n\t" \ (6)
"push r2 \n\t" \ (7)
"push r3 \n\t" \
"push r4 \n\t" \
"push r5 \n\t" \
:
:
:
"push r30 \n\t" \
"push r31 \n\t" \
"lds r26, pxCurrentTCB \n\t" \ (8)
"lds r27, pxCurrentTCB + 1 \n\t" \ (9)
"in r0, __SP_L__ \n\t" \ (10)
"st x+, r0 \n\t" \ (11)
"in r0, __SP_H__ \n\t" \ (12)
"st x+, r0 \n\t" \ (13)
);
在上面的源代码中:
1. 寄存器R0首先被保存,因为当状态寄存器被保存时,它会被用到。所以必须先把它的原始值保存下来。
2. 状态寄存器被搬移到 R0 (2),所以它能保存到stack (4)
3. 禁止处理器中断。如果portSAVE_CONTEXT(),只是从ISR中调用,就不需要明确的禁止中断,因为AVR已经这么做了。portSAVE_CONTEXT()宏用在中断服务程序的外部(一个任务自己挂起自己的时候),中断应该尽可能早的明确清除(也就是禁止中断 CLI)
4. 从ISR 的C源代码中,由编译器生成的代码假定R1被设置为0。R1的原始值 在
R1被清除(6)前保存(5)
5. 在(7)和(8),所有寄存器都被按顺序保存
6. 现在被挂起的任务的栈中还有一个任务执行上下文的拷贝。内核保存任务的栈指针,所以 当任务恢复执行时,上下文可以取得并恢复。The X processor register is loaded with the address to which the stack pointer is to be saved (8 and 9). 载入栈指针
7. 栈指针保存,先低位(10,11)后高位(12 13)
Restoring the Context
portRESTORE_CONTEXT()是portSAVE_CONTEXT().的逆过程。要恢复执行的任务的上下文被预先存储到任务栈中。实时内核为该任务取得栈指针,然后弹出POP上下文到 正确的寄存器中。
#define portRESTORE_CONTEXT() \
asm volatile (
"lds r26, pxCurrentTCB \n\t" \ (1)
"lds r27, pxCurrentTCB + 1 \n\t" \ (2)
"ld r28, x+ \n\t" \
"out __SP_L__, r28 \n\t" \ (3)
"ld r29, x+ \n\t" \
"out __SP_H__, r29 \n\t" \ (4)
"pop r31 \n\t" \
"pop r30 \n\t" \
:
:
:
"pop r1 \n\t" \
"pop r0 \n\t" \ (5)
"out __SREG__, r0 \n\t" \ (6)
"pop r0 \n\t" \ (7)
);
上面的代码中:
1. pxCurrentTCB含有任务栈指针被取得的地址。这被载入到X寄存器(1和2)
2. 被恢复的任务的栈指针 载入到AVR的stack pointer,先低字节(3),后高半字节nibble(4)
3.寄存器以相反的顺序从栈中,一直到R1
4.状态寄存其保存在stack中的位置是在R1和R0之间,所以,它在R0(7)前重新恢复(6)
===最后一节:上下文切换的完整例子===
作者:Gavin Lee 更新日期:2006-04-24
来源:upsdn.net
浏览次数:
相关文章
相关评论 发表评论
- No Comments