马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
LBHIDDEN[0]LBHIDDEN[这个贴子最后由yangtch在 2003/09/10 08:44am 第 1 次编辑]
uC/OS上实现分离的中断栈示意图(转帖)
文中汇编为MSP430汇编
中断发生:
+----------+
| -- |
+----------+
| PC |
+----------+
SP | SR |
---> +----------+
| |
保存所有寄存器:
+----------+
| -- |
+----------+
| PC |
+----------+
| SR |
+----------+
~ ~
+----------+
SP | Rx |
---> +----------+
| |
保存当前任务的SP
TCBCurrent
+----------+ +-----------+
| -- | | SP |
+----------+ +-----------+
| PC | | |
+----------+
| SR |
+----------+
~ ~
+----------+
SP | Rx |
---> +----------+
| |
mov.w &TCBCurrent, Rx
mov.w SP, (Rx)
如果中断记数器 == 0,加载中断栈SP:
isrStack(全局变量)
+-----------+ 0x430 | -- |
| 0x430 | ---> +----------+
+-----------+ | |
+----------+
| |
if (intrCounter == 0) {
mov.w &isrStack, Rx
mov.w @Rx, SP
}
中断计数器加1
这里可以打开中断允许(允许中断嵌套)
调用中断处理函数:
0x430 +----------+
SP | | Routine return addr
---> +----------+
| |
call &routine
这里关闭中断允许
中断计数器减1
如果中断计数器 == 0,需要切换栈
if (intrCounter == 0) {
计算最高优先级任务
加载最高级任务栈SP:
mov.w &TCBHighRdy, Rx
mov.w @Rx, SP
TCBHighRdy
SP | Rx | +----------+
---> +----------+ | SP |
| | +----------+
+----------+ | |
| |
+----------+
}
恢复所有寄存器
+----------+
| -- |
+----------+
| PC |
+----------+
SP | SR |
---> +----------+
~ ~
+----------+
| Rx |
+----------+
| |
从中断中返回:
+----------+
SP | -- |
---> +----------+
| PC |
+----------+
| SR |
+----------+
| |
/////////////////////////////////////////////////////////////////////////////
汇编代码实现
#include "msp430x14x.h"
PUSHALL MACRO
push r4
push r5
push r6
push r7
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
ENDM
POPALL MACRO
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop r7
pop r6
pop r5
pop r4
ENDM
;tick isr
;
;
EXTERN tcbCurrent
EXTERN tcbHighRdy
EXTERN intCnt
EXTERN isrStack
EXTERN ticksAnnounce
EXTERN countHighRdy
;---------------------------------------------------------------------------
RSEG CODE ; Program code
PUBLIC WDT_ISR
WDT_ISR:
PUSHALL ; push all registers
bic.b #0x01, IE1 ; disable wd timer interrupt
cmp.b #0, &intCnt ; if (intCnt == 0) load interrupt stack
jne L1
mov.w &tcbCurrent, R13 ; save task stack
mov.w SP, 0(R13) ; load interrupt stack
mov.w &isrStack, SP ;
L1:
inc.b &intCnt ; increase intCnt
EINT ; enable general interrupt
call #ticksAnnounce ; call ticks routine
DINT ; disable general interrupt
dec.b &intCnt ; reduce intCnt
cmp.b #0, &intCnt ; if (intCnt == 0) restore task stack
jne L2
call #countHighRdy ; count highest ready task
mov.w &tcbHighRdy, R13 ; restore task stack SP
mov.w R13, &tcbCurrent ;
mov.w @R13, SP ;
L2:
bis.b #0x01, IE1 ; enable wd timer interrupt
POPALL ; pop all registers
reti ; return from interrupt
;*************************************************************************************************************
; WD TIMER INTVEC ; MSP430x11x1/MSP430F14x Interrupt vectors
;*************************************************************************************************************
ORG WDT_VECTOR
WDT_VEC DW WDT_ISR ; Watchdog/Timer, Timer mode
;---------------------------------------------------------------------------
END
|