📄 kern600.s
字号:
TTL uC/OS ARM kernel routines > kern600.s ; --------------------------------------------------------------------- ; This file provides the lo-level machine dependant ARM ; support for the uC/OS system. ; ; $Revision: 0.1 $ ; $Author: jsmith $ ; $Date: 941103 $ ; ; Original author: Geary Chopoff. ; ; Copyright (c) 1993-1994, VLSI Technology Inc. All Rights Reserved. ; --------------------------------------------------------------------- ; NOTEs: ; ; There is a lot of ARM magic in this file to do deal with ; preserving register state over interrupts and context ; switches. All of the features are fully documented in the ; ARM data-sheet though, and most of the complication arises ; just from the various options depending on the state of the ; ARM at the instance of the event. ; ; All threads are started in USR mode. If a thread needs to ; execute in a particular processor mode then it should use ; the Demon SWIs available. This includes the "main" ; application entry point started from the C-Demon world. ; ; The uC/OS ARM system *ONLY* supports threads that conform to ; the APCS-3 (ARM Procedure Calling Standard version 3). Part ; of this standard dictates that there is always a FD (Full ; Descending) stack available in r13, with *NO* information ; stored beneath it. ; ; The uC/OS ARM system *NEEDS* to provide its own IRQ and FIQ ; vector handlers to deal with the magic of providing clean ; context switches. To perform a context switch cleanly the ; interrupt code needs to have access to *ALL* of the ; processor state at the instance of the ; interrupt. Unfortunately this limits the coding of the main ; interrupt handler to assembler since if we use the special ; __irq compiler feature, and code the handler in C then we ; will not have access to the initial stack and register ; contents. There is no frame-pointer support with the __irq ; option, so it would not be possible to decode the stack ; frame to recover the required information (plus scanning the ; frame would be slow). We cannot code the interrupt handler ; as a normal C function (with call frame support) since IRQ ; and FIQ require special processing to perform the return, ; plus they have some private (banked) registers. ; ; This ARM6x0 targetted version of uC/OS does *NOT* provide ; any FIQ support. The standard C-Demon FIQ handler is left ; intact. If FIQ support is required, then similar processing ; to the "IRQHandler" code below needs to be provided for FIQ ; interrupts. ; ; Only the following uC/OS routines can safely be called from ; an ARM uC/OS ISR: ; ; OSIntEnter ; performed by the system interrupt handler ; OSIntExit ; performed by the system interrupt handler ; OSTimeTick ; to increment the scheduling clock ; IRQMboxPost ; to post a message to a mailbox ; ; The actions of calling a routine *NOT* listed above is ; undefined, and will probably result in a system crash. ; --------------------------------------------------------------------- INCLUDE modes_h.s ; support for ARM600 modes INCLUDE swis_h.s ; support for SWI functions INCLUDE driver_h.s ; target architecture specific definitions ; --------------------------------------------------------------------- IMPORT OSIntEnter ; void OSIntEnter(void) ; IMPORT OSIntExit ; int OSIntExit(void) ; IMPORT OSTimeTick ; void OSTimeTick(void) ; IMPORT OSTCBCur ; OS_TCB *OSTCBCur ; IMPORT OSTCBHighRdy ; OS_TCB *OSTCBHighRdy ; IMPORT IRQvectors ; IRQHandlerFn IRQvectors[NUMIRQS] ; IMPORT FIQvectors ; FIQHandlerFn FIQvectors[NUMFIQS] ; ; --------------------------------------------------------------------- EXPORT IRQHandler ; non APCS-3 conforming routine EXPORT DummyIRQ ; IRQHandlerFn DummyIRQ ; EXPORT DummyFIQ ; FIQHandlerFn DummyFIQ ; EXPORT OSStartHighRdy ; void OSStartHighRdy(void) ; EXPORT OSCtxSw ; void OSCtxSw(void) ; EXPORT InitTask ; unsigned int *InitTask(uint *pstk) ; ; --------------------------------------------------------------------- ; The following manifests *ASSUME* the shape of the uC/OS ; OS_TCB structure. At the moment there is no build- or ; run-time check that these match the "ucos.h" master ; definitions. ^ 0 ; shape of OS_TCB structureOSTCB_OSTCBStkPtr # 4 ; a pointer to the active stack pointer ; We are not interested in any other OS_TCB fields for this ; code so this is not a complete definition of the structure. ; --------------------------------------------------------------------- ; The following manifests define the shape of a stored thread ; context. These contexts are stored on the stack at the ; instance of a context switch. The manifests are given as ; offsets from the stack pointer after the context space has ; been allocated. ; ; If we were desperate to shave a few more cycles off the ; context switch time we could re-order these fields to better ; match the instruction sequences needed to load and save the ; context (i.e. to make optimium use of writeback, etc.). ; ^ 0 ; offsets within stacked contextCtx_a1 # 4 ; r0Ctx_a2 # 4 ; r1Ctx_a3 # 4 ; r2Ctx_a4 # 4 ; r3Ctx_v1 # 4 ; r4Ctx_v2 # 4 ; r5Ctx_v3 # 4 ; r6Ctx_v4 # 4 ; r7Ctx_v5 # 4 ; r8Ctx_v6 # 4 ; r9 (possibly the static-base)Ctx_sl # 4 ; r10 stack-limit or v7Ctx_fp # 4 ; r11 frame-pointerCtx_ip # 4 ; r12 temporaryCtx_sp # 4 ; r13 stack-pointerCtx_lr # 4 ; r14 link registerCtx_pc # 4 ; Program Counter of de-scheduled threadCtx_CPSR # 4 ; PSR describing de-scheduled threadCtx_SPSR # 4 ; Saved PSR (if priviledged mode)Ctx_USR_v5 # 4 ; USR mode r8 (if required)Ctx_USR_v6 # 4 ; USR mode r9 (if required)Ctx_USR_sl # 4 ; USR mode r10 (if required)Ctx_USR_fp # 4 ; USR mode r11 (if required)Ctx_USR_ip # 4 ; USR mode r12 (if required)Ctx_USR_sp # 4 ; USR mode stack pointer (if required)Ctx_USR_lr # 4 ; USR mode link register (if required)Ctx_sizeof # 0 ; size of a stacked context ; --------------------------------------------------------------------- AREA |ucos$$kern600|,CODE,READONLY ; --------------------------------------------------------------------- ; The following macros provide code to save a context and to ; startup the highest priority pending task. We use macros to ; provide multiple in-line versions of this code to gain ; performance. If size becomes an issue then a single version ; of each routine could be created, with the macro calls ; changed to branches to the required single version: MACRO$label SAVECONTEXT$label ; sp = current task stack pointer SUB sp,sp,#Ctx_sizeof ; create context structure STR lr,[sp,#Ctx_pc] ; the return address we want MOV lr,sp ; take a copy of the context pointer STMIA lr,{a1-ip} ; and stack most of the state MRS a1,CPSR ; get the current PSR STR a1,[sp,#Ctx_CPSR] ; and store into the context ANDS a1,a1,#SubModeMask ; check for USR mode task BEQ %FT01 ; no more work for USR mode task MRS a2,SPSR ; get the saved PSR STR a2,[sp,#Ctx_SPSR] ; and store it TEQ a1,#(FIQmode :AND: SubModeMask) ; check for FIQ mode ADDEQ a2,sp,#Ctx_USR_v5 ; reference the USR register hold slots ADDNE a2,sp,#Ctx_USR_sp ; reference the USR register hold slots STMEQIA a2,{v5-lr}^ ; force USR mode transfer STMNEIA a2,{sp-lr}^ ; force USR mode transfer01 ; sp = pointer to newly created context on current task stack ; All the other registers are now available as work registers: LDR a1,=OSTCBCur ; point at current TCB LDR a2,[a1,#0x00] ; get pointer to context pointer save location STR sp,[a2,#0x00] ; save sp (context pointer) MEND MACRO$label STARTNEXTTASK$label ; This code assumes that all the registers are available for ; its use with the following exceptions: MRS a1,CPSR ; get current PSR TST a1,#SubModeMask ; check for USR mode SWIEQ EnterOS ; get SVC mode for USR thread ; We execute the rest of the restore context code in a ; priviledged mode: ; LDR a2,=OSTCBHighRdy ; reference the highest priority task holder LDR a2,[a2] ; and get the OS_TCB pointer for the pending task LDR a1,=OSTCBCur ; point at current context holder location STR a2,[a1,#0x00] ; make the new task the current LDR a1,[a2,#0x00] ; get the context pointer ; ; NOTE: If we have interrupts enabled we cannot update the ; stack-pointer until *AFTER* we have loaded all the context, ; since we may be interrupted by code that attempts to save a ; new context under the stack-pointer. ; LDR a2,[a1,#Ctx_CPSR] ; get destination PSR ANDS a3,a2,#SubModeMask ; check if destination is USR BEQ %FT01 ; no need to do much if starting USR ; ; We know we are starting a priviledged mode: MSR CPSR,a2 ; switch to destination mode TEQ a3,#(FIQmode :AND: SubModeMask) ; check if FIQ ADDNE a3,a1,#Ctx_USR_sp ; reference USR banked registers LDMNEIA a3,{sp-lr}^ ; force USR mode transfer for SVC,IRQ,ABT and UND ADDEQ a3,a1,#Ctx_USR_v5 ; reference USR banked registers LDMEQIA a3,{v5-lr}^ ; force USR mode transfer for FIQ ; We have now restored the banked USR registers. ; LDR a3,[a1,#Ctx_SPSR] ; recover SPSR for this mode MSR SPSR,a3 ; and reload it01 ; We branch here if re-starting a USR thread. ; This next MSR is for the benefit of USR threads being ; started. If we are starting a privilidged mode we will ; already be in the correct mode, however this doesn't hurt ; and makes the code simpler: MSR CPSR,a2 ; switch to destination mode ; We are now *DEFINATELY* executing in the destination mode ; with the desired IRQ and FIQ state. MOV sp,a1 ; reference the context LDMFD sp,{a1-ip} ; load most of the register state LDR lr,[sp,#Ctx_pc] ; recover the desired PC ; All the other state has now been loaded from the stacked ; context: ADD sp,sp,#Ctx_sizeof ; dump the context allocation MOV pc,lr ; and continue with the new task MEND ; --------------------------------------------------------------------- ; -- interrupt handling ----------------------------------------------- ; --------------------------------------------------------------------- ; This routine should be attached to the ARM IRQ vector. It ; provides the lo-level uC/OS interrupt handling, and deals ; with context switching as a result of the application ; attached ISR routines.IRQHandler ; in: IRQ32 mode; IRQs disabled; FIQs undefined. ; r13 = FD stack ; r14 = (return address + 4)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -