读书人

uCOSV2.52在mini2440下的移植解析1:O

发布时间: 2012-11-09 10:18:48 作者: rapoo

uCOSV2.52在mini2440上的移植解析1:OS_CPU_A.S

uCOSV2.52在mini2440上的移植解析1:OS_CPU_A.S

uCOS-II的移植实例要求用户编写4个简单的汇编语言函数:

OSStartHighRdy();

OSCtxSw();

OSIntCtxSw();

OSTickISR();

下面就开始分析uCOS-II在mini2440开发板上的ADS环境运行的移植细节。

/*关于mini2440的中断设置和ARM处理器工作的七种模式*/

SRCPND EQU 0x4a000000 ; Source pending
INTPND EQU 0x4a000010 ; Interrupt request status

rEINTPEND EQU 0x560000a8
INTOFFSET EQU 0x4a000014


USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0

;*********************************************************************************************************
; 引入外部的函数

;*********************************************************************************************************/
IMPORT OSRunning
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSIntNesting


IMPORT OSIntEnter
IMPORT OSIntExit
IMPORT OSTaskSwHook
IMPORT OSTimeTick

IMPORT HandleEINT0

EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSTickISR
EXPORT OSIntCtxSw

EXPORT OSCPUSaveSR
EXPORT OSCPURestoreSR

EXPORT OS_CPU_IRQ_ISR


AREA UCOS_ARM, CODE, READONLY

;*********************************************************************************************************
; 开始多任务
; void OSStartHighRdy(void)
;
; The stack frame is assumed to look as follows:
;
; Entry Point(Task Name) (High memory)
; LR(R14)
; R12
; R11
; R10
; R9
; R8
; R7
; R6
; R5
; R4
; R3
; R2
; R1
; R0 : argument
; OSTCBHighRdy->OSTCBStkPtr --> CPSR (Low memory)
;
; Note : OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;********************************************************************************************************** */
OSStartHighRdy
;----------------------------------------------
; OSRunning = TRUE;
;----------------------------------------------

MSR CPSR_cxsf,#SVCMODE|NOINT ;切换至SVC模式并使FIQ,IRQ无效

BL OSTaskSwHook ;调用用户钩子函数OSTaskSwHook ,带返回地址(存至LR寄存器中)
LDR R0, =OSRunning ; 初始化时置OSRunning = true

MOV R1, #1
STRB R1, [R0]

;----------------------------------------------
; SP = OSTCBHighRdy->OSTCBStkPtr;
;----------------------------------------------
LDR R0, =OSTCBHighRdy
LDR R0, [R0]
LDR SP, [R0]

;----------------------------------------------
; 准备返回合适的模式

;----------------------------------------------
LDMFD SP!, {R0} ; 向下压栈
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^ ;spsr的值复制到cpsr


;**********************************************************************************************************
; 任务切换

; void OSCtxSw(void)
;
; Note(s): 1) Upon entry:
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
; 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)
;*********************************************************************************************************/
OSCtxSw

STMFD SP!, {LR} ;PC
STMFD SP!, {R0-R12, LR} ;R0-R12 LR
MRS R0, CPSR ;Push CPSR
STMFD SP!, {R0}

;----------------------------------------------
; OSTCBCur->OSTCBStkPtr = SP
;----------------------------------------------
LDR R0, =OSTCBCur
LDR R0, [R0]
STR SP, [R0]

;----------------------------------------------
; 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]

;----------------------------------------------
; OSTCBHighRdy->OSTCBStkPtr;
;----------------------------------------------
LDR R0, =OSTCBHighRdy
LDR R0, [R0]
LDR SP, [R0]

;----------------------------------------------
;恢复下一个新任务的寄存器信息
;----------------------------------------------
LDMFD SP!, {R0} ;POP CPSR
MSR SPSR_cxsf, R0
LDMFD SP!, {R0-R12, LR, PC}^


;*********************************************************************************************************
; TICK HANDLER

;uCOS要求用户提供一个周期性的时钟源以实现时间的延迟和超时功能
;
; 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

;*********************************************************************************************************
; 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 R4-R6 from IRQ stack
STMFD SP!, {R4-R6} ; Push Task''s R4-R6 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 ;向后搜索lable为1的行

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

uCOSV2.52在mini2440下的移植解析1:OS_CPU_A.S

读书人网 >操作系统

热点推荐