📄 os_cpu_asm.s
字号:
;// Description:
;// This handles all the Timer0(INT_TIMER0) interrupt which is used to generate the uC/OS-II tick.
;//*********************************************************************************************************/
OSTickISR
MOV R5,LR
MOV R1, #1
MOV R1, R1, LSL #10 ;// Timer0 Source Pending Reg.
LDR R0, =SRCPND
LDR R2, [R0]
ORR R1, R1,R2
STR R1, [R0]
LDR R0, =INTPND
LDR R1, [R0]
STR R1, [R0]
;//----------------------------------------------------------------------------------
;// OSTimeTick();//
;//----------------------------------------------------------------------------------
BL OSTimeTick
MOV PC, R5 ;// Return
;//*********************************************************************************************************
;// PERFORM A CONTEXT SWITCH (From an ISR)
;// void OSIntCtxSw(void)
;//
;// Description: 1) This code performs a context switch if a higher priority task has been made ready-to-run
;// during an ISR.
;//
;// 2) The stack frame of the task to suspend looks as follows:
;//
;// PC (High memory)
;// LR(R14)
;// R12
;// R11
;// R10
;// R9
;// R8
;// R7
;// R6
;// R5
;// R4
;// R3
;// R2
;// R1
;// R0
;//
;// OSTCBCur->OSTCBStkPtr ----> CPSR (Low memory)
;//
;//
;// 3) The stack frame of the task to resume looks as follows:
;//
;// PC (High memory)
;// LR(R14)
;// R12
;// R11
;// R10
;// R9
;// R8
;// R7
;// R6
;// R5
;// R4
;// R3
;// R2
;// R1
;// R0
;// OSTCBHighRdy->OSTCBStkPtr ----> CPSR (Low memory)
;//*********************************************************************************************************/
OSIntCtxSw
;//----------------------------------------------------------------------------------
;// Call OSTaskSwHook();//
;//----------------------------------------------------------------------------------
BL OSTaskSwHook
;//----------------------------------------------------------------------------------
;// OSTCBCur = OSTCBHighRdy;//
;//----------------------------------------------------------------------------------
LDR R0, =OSTCBHighRdy
LDR R1, =OSTCBCur
LDR R0, [R0]
STR R0, [R1]
;//----------------------------------------------------------------------------------
;// OSPrioCur = OSPrioHighRdy;//
;//----------------------------------------------------------------------------------
LDR R0, =OSPrioHighRdy
LDR R1, =OSPrioCur
LDRB R0, [R0]
STRB R0, [R1]
;//----------------------------------------------------------------------------------
;// SP = OSTCBHighRdy->OSTCBStkPtr;//
;//----------------------------------------------------------------------------------
LDR R0, =OSTCBHighRdy
LDR R0, [R0]
LDR SP, [R0]
;//----------------------------------------------------------------------------------
;// Restore New Task context
;//----------------------------------------------------------------------------------
LDMFD SP!, {R0} ;//POP CPSR
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^
OS_CPU_IRQ_ISR
STMFD SP!, {R1-R3} ;// We will use R1-R3 as temporary registers
;//----------------------------------------------------------------------------
;// R1--SP
;// R2--PC
;// R3--SPSR
;//------------------------------------------------------------------------
MOV R1, SP
ADD SP, SP, #12 ;//Adjust IRQ stack pointer
SUB R2, LR, #4 ;//Adjust PC for return address to task
MRS R3, SPSR ;// Copy SPSR (Task CPSR)
MSR CPSR_cxsf, #SVCMODE|NOINT ;//Change to SVC mode
;// SAVE TASK''S CONTEXT ONTO OLD TASK''S STACK
STMFD SP!, {R2} ;// Push task''s PC
STMFD SP!, {R4-R12, LR} ;// Push task''s LR,R12-R4
LDMFD R1!, {R4-R6} ;// Load Task''s R1-R3 from IRQ stack
STMFD SP!, {R4-R6} ;// Push Task''s R1-R3 to SVC stack
STMFD SP!, {R0} ;// Push Task''s R0 to SVC stack
STMFD SP!, {R3} ;// Push task''s CPSR
LDR R0,=OSIntNesting ;//OSIntNesting++
LDRB R1,[R0]
ADD R1,R1,#1
STRB R1,[R0]
CMP R1,#1 ;//if(OSIntNesting==1){
BNE %F1
LDR R4,=OSTCBCur ;//OSTCBHighRdy->OSTCBStkPtr=SP;//
LDR R5,[R4]
STR SP,[R5] ;//}
1
MSR CPSR_c,#IRQMODE|NOINT ;//Change to IRQ mode to use IRQ stack to handle interrupt
LDR R0, =INTOFFSET
LDR R0, [R0]
LDR R1, IRQIsrVect
MOV LR, PC ;// Save LR befor jump to the C function we need return back
LDR PC, [R1, R0, LSL #2] ;// Call OS_CPU_IRQ_ISR_handler();//
MSR CPSR_c,#SVCMODE|NOINT ;//Change to SVC mode
BL OSIntExit ;//Call OSIntExit
LDMFD SP!,{R4} ;//POP the task''s CPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC}^ ;//POP new Task''s context
IRQIsrVect DCD HandleEINT0
;//*********************************************************************************************************
;// CRITICAL SECTION METHOD 3 FUNCTIONS
;//
;// Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you
;// would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
;// disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II''s functions that need to
;// disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr'
;// into the CPU''s status register.
;//
;// Prototypes : OS_CPU_SR OSCPUSaveSR(void);//
;// void OSCPURestoreSR(OS_CPU_SR cpu_sr);//
;//
;//
;// Note(s) : 1) These functions are used in general like this:
;//
;// void Task (void *p_arg)
;// {
;// #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
;// OS_CPU_SR cpu_sr;//
;// #endif
;//
;// :
;// :
;// OS_ENTER_CRITICAL();// /* cpu_sr = OSCPUSaveSR();// */
;// :
;// :
;// OS_EXIT_CRITICAL();// /* OSCPURestoreSR(cpu_sr);// */
;// :
;// :
;// }
;//
;// 2) OSCPUSaveSR() is implemented as recommended by Atmel''s application note:
;//
;// "Disabling Interrupts at Processor Level"
;//*********************************************************************************************************
OSCPUSaveSR
MRS R0, CPSR ;// Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1, R0, #0xC0
MSR CPSR_c, R1
MRS R1, CPSR ;// Confirm that CPSR contains the proper interrupt disable flags
AND R1, R1, #0xC0
CMP R1, #0xC0
BNE OSCPUSaveSR ;// Not properly disabled (try again)
MOV PC, LR ;// Disabled, return the original CPSR contents in R0
OSCPURestoreSR
MSR CPSR_c, R0
MOV PC, LR
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -