IMPORT OSTCBCur
IMPORT OSTCBNext
EXPORT OS_ENTER_CRITICAL
EXPORT OS_EXIT_CRITICAL
EXPORT OSStart
EXPORT PendSV_Handler
EXPORT OSCtxSw
NVIC_INT_CTRL EQU 0xE000ED04 ; Address of NVIC Interruptions Control Register
NVIC_PENDSVSET EQU 0x10000000 ; Enable PendSV
NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14).
NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest).
PRESERVE8 ; align 8
AREA |.text|, CODE, READONLY
THUMB
;/******************OS_ENTER_CRITICAL************/
OS_ENTER_CRITICAL
CPSID I ; Enable interruptions(Change Processor States: Interrupts Disable)
BX LR ; Return
;/******************OS_EXIT_CRITICAL************/
OS_EXIT_CRITICAL
CPSIE I ; Disable interruptions
BX LR ; Return
;/******************OSStart************/
OSStart
; disable interruptions
CPSID I ; OS_ENTER_CRITICAL();
; initialize PendSV
; Set the PendSV exception priority
LDR R0, =NVIC_SYSPRI14 ; R0 = NVIC_SYSPRI14;
LDR R1, =NVIC_PENDSV_PRI ; R1 = NVIC_PENDSV_PRI;
STRB R1, [R0] ; *R0 = R1;
; initialize PSP as 0
; MOV R4, #0
LDR R4, =0x0 ; R4 = 0;
MSR PSP, R4 ; PSP = R4;
; trigger PendSV
LDR R4, =NVIC_INT_CTRL ; R4 = NVIC_INT_CTRL;
LDR R5, =NVIC_PENDSVSET ; R5 = NVIC_PENDSVSET;
STR R5, [R4] ; *R4 = R5;
; enable interruptions
CPSIE I ; OS_EXIT_CRITICAL();
; should never get here
; a endless loop
OSStartHang
B OSStartHang
;/******************PendSV_Handler************/
PendSV_Handler
CPSID I ; OS_ENTER_CRITICAL();
; judge if PSP is 0 which means the task is first invoked
MRS R0, PSP ; R0 = PSP;
CBZ R0, PendSV_Handler_NoSave ; if(R0 == 0) goto PendSV_Handler_NoSave;
; R12, R3, R2, R1
SUB R0, R0, #0x20 ; R0 = R0 - 0x20;
; store R4
STR R4 , [R0] ; *R0 = R4;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
; store R5
STR R5 , [R0] ; *R0 = R5;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
; store R6
STR R6 , [R0] ; *R0 = R6;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
; store R7
STR R7 , [R0] ; *R0 = R7;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
; store R8
STR R8 , [R0] ; *R0 = R8;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
; store R9
STR R9, [R0] ; *R0 = R4;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
; store R10
STR R10, [R0] ; *R0 = R10;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
; store R11
STR R11, [R0] ; *R0 = R11;
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;
SUB R0, R0, #0x20 ; R0 = R0 - 0x20;
; easy method
;SUB R0, R0, #0x20
;STM R0, {R4-R11}
LDR R1, =OSTCBCur ; R1 = OSTCBCur;
LDR R1, [R1] ; R1 = *R1;(R1 = OSTCBCur->OSTCBStkPtr)
STR R0, [R1] ; *R1 = R0;(*(OSTCBCur->OSTCBStkPrt) = R0)
PendSV_Handler_NoSave
LDR R0, =OSTCBCur ; R0 = OSTCBCur;
LDR R1, =OSTCBNext ; R1 = OSTCBNext;
LDR R2, [R1] ; R2 = OSTCBNext->OSTCBStkPtr;
STR R2, [R0] ; *R0 = R2;(OSTCBCur->OSTCBStkPtr = OSTCBNext->OSTCBStkPtr)
LDR R0, [R2] ; R0 = *R2;(R0 = OSTCBNext->OSTCBStkPtr)
; LDM R0, {R4-R11}
; load R4
LDR R4, [R0] ; R4 = *R0;(R4 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
; load R5
LDR R5, [R0] ; R5 = *R0;(R5 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
; load R6
LDR R6, [R0] ; R6 = *R0;(R6 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
; load R7
LDR R7 , [R0] ; R7 = *R0;(R7 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
; load R8
LDR R8 , [R0] ; R8 = *R0;(R8 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
; load R9
LDR R9 , [R0] ; R9 = *R0;(R9 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
; load R10
LDR R10 , [R0] ; R10 = *R0;(R10 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
; load R11
LDR R11 , [R0] ; R11 = *R0;(R11 = *(OSTCBNext->OSTCBStkPtr))
ADD R0, R0, #0x4 ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
MSR PSP, R0 ; PSP = R0;(PSP = OSTCBNext->OSTCBStkPtr)
; P42
; P139 (key word: EXC_RETURN)
; use PSP
ORR LR, LR, #0x04 ; LR = LR | 0x04;
CPSIE I ; OS_EXIT_CRITICAL();
BX LR ; return;
OSCtxSw ;OS context switch
PUSH {R4, R5}
LDR R4, =NVIC_INT_CTRL ; R4 = NVIC_INT_CTRL
LDR R5, =NVIC_PENDSVSET ; R5 = NVIC_PENDSVSET
STR R5, [R4] ; *R4 = R5
POP {R4, R5}
BX LR ; return;
align 4
end