中断函数特别是Tmr_TickISR_Handler 中断退出时必须加OSIntExit ()函数吗?
但是我看到许多别人写的中断根本就没加,也就是中断后不做任何调度。
void Tmr_TickISR_Handler (void)
{
OSTimeTick(); /* Call uC/OS-II's OSTimeTick(). */
T0CLRI = 0xFF; /* Clear timer #0 interrupt. */
}
那么就两个延时的任务而言,一个延时10ms(高优先级),一个延时50ms执行一次(低优先级),
高优先级执行1ms后,挂起本身后调度一下,准备延时10ms,调度引起低优先级任务执行,低优先级
执行2ms后,调度一下,准备延时50ms,之后我觉得如果时钟中断里不含调度的话任务都被挂起了,任务
从此就一直idle了。
问题1:我理解是否错误?
问题2:如果理解正确,是否有别的方法使任务调度回来(除了中断调度)。
经过调试终于发现问题了。
OS_CPU_ARM_EXCEPT_HANDLER
MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR)
; DETERMINE IF WE INTERRUPTED A TASK OR ANOTHER LOWER PRIORITY EXCEPTION
; SPSR.Mode = FIQ, IRQ, SVC, ABT, UND : Other exception
; SPSR.Mode = SYS : Task
; SPSR.Mode = USR : *unsupported state*
AND R2, R1, #OS_CPU_ARM_MODE_MASK
CMP R2, #OS_CPU_ARM_MODE_SYS//答案在这个地方,之前是系统模式,不跳转,顺序执行。
如果不是系统模式,就是进行嵌套处理。
BNE OS_CPU_ARM_EXCEPT_HANDLER_BreakExcept
;********************************************************************************************************
; EXCEPTION HANDLER: TASK INTERRUPTED
;********************************************************************************************************
OS_CPU_ARM_EXCEPT_HANDLER_BreakTask
MRS R2, CPSR ; Save exception's CPSR
MOV R4, SP ; Save exception's stack pointer
; Change to SYS mode & disable interruptions
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; SAVE TASK'S CONTEXT ONTO TASK'S STACK
STMFD SP!, {R3} ; Push task's PC
STMFD SP!, {LR} ; Push task's LR
STMFD SP!, {R5-R12} ; Push task's R12-R5
LDMFD R4!, {R5-R9} ; Move task's R4-R0 from exception stack to task's stack
STMFD SP!, {R5-R9}
TST R3, #1 ; See if called from Thumb mode
ORRNE R1, R1, #OS_CPU_ARM_CONTROL_THUMB ; If yes, Set the T-bit
STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR)
; if (OSRunning == 1)
LDR R1, ?OS_Running
LDRB R1, [R1]
CMP R1, #1
BNE OS_CPU_ARM_EXCEPT_HANDLER_BreakTask_1
; HANDLE NESTING COUNTER
LDR R3, ?OS_IntNesting ; OSIntNesting++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
LDR R3, ?OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP;
LDR R4, [R3]
STR SP, [R4]
OS_CPU_ARM_EXCEPT_HANDLER_BreakTask_1
MSR CPSR_cxsf, R2 ; RESTORE INTERRUPTED MODE
LDR R1, ?OS_EXCEPT_HANDLER ; OS_EXCEPT_HANDLER();
MOV LR, PC
BX R1
; Adjust exception stack pointer. This is needed because
; exception stack is not used when restoring task context.
ADD SP, SP, #(14*4)
; Change to SYS mode & disable interruptions.
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; Call OSIntExit(). This call MAY never return
; if a ready task with higher priority than
; the interrupted one is found.
LDR R0, ?OS_IntExit
MOV LR, PC
BX R0
; RESTORE NEW TASK'S CONTEXT
LDMFD SP!, {R0} ; Pop new task's CPSR
MSR CPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC} ; Pop new task's context
;********************************************************************************************************
; EXCEPTION HANDLER: EXCEPTION INTERRUPTED
;********************************************************************************************************
OS_CPU_ARM_EXCEPT_HANDLER_BreakExcept
MRS R2, CPSR ; Save exception's CPSR
; Change to SYS mode & disable interruptions
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; HANDLE NESTING COUNTER
LDR R3, ?OS_IntNesting ; OSIntNesting++;
LDRB R4, [R3]
ADD R4, R4, #1
STRB R4, [R3]
MSR CPSR_cxsf, R2 ; RESTORE INTERRUPTED MODE
LDR R3, ?OS_EXCEPT_HANDLER ; OS_EXCEPT_HANDLER();
MOV LR, PC
BX R3
; Change to SYS mode & disable interruptions
MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SYS)
; HANDLE NESTING COUNTER
LDR R3, ?OS_IntNesting ; OSIntNesting--;
LDRB R4, [R3]
SUB R4, R4, #1
STRB R4, [R3]
MSR CPSR_cxsf, R2 ; RESTORE INTERRUPTED MODE
LDMFD SP!, {R0-R12, PC}^ ; Pull working registers and return from exception.