⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu_a.s

📁 uc/fs文件系统
💻 S
字号:
	AREA	|subr|, CODE, READONLY
  
AIC_BASE	EQU	0xFFFFF000
AIC_IVR 	EQU	0x94

AIC_EOICR		EQU		0x130
TC1_BASE 		EQU     0xFFFE0040

ARM_MODE_USER   EQU    0x10
ARM_MODE_FIQ    EQU    0x11
ARM_MODE_IRQ    EQU    0x12
ARM_MODE_SVC    EQU    0x13
ARM_MODE_ABORT  EQU    0x17
ARM_MODE_UNDEF  EQU    0x1B
ARM_MODE_SYS    EQU    0x1F
 
I_BIT           EQU     0x80
F_BIT           EQU     0x40
T_BIT           EQU     0x20 
;-------------------------------------------------------------------------------------
; Function: OSStartHighRdy
; Purpose:
; 	   To start the task with the highest priority during OS startup
; Notes:
;   Called once during OSStart()
;-------------------------------------------------------------------------------------  	
	EXPORT  OSStartHighRdy
	IMPORT	OSTaskSwHook
    IMPORT	OSTCBCur
	IMPORT	OSTCBHighRdy
	IMPORT 	OSRunning

OSStartHighRdy
	BL 	OSTaskSwHook			; Call user-defined hook function
	
	LDR	r4,=OSRunning			; Indicate that multitasking has started
	MOV	r5,#1
	STRB	r5,[r4]				; OSRunning = true
	
	LDR	r4, =OSTCBCur			; Get current task TCB address
	LDR	r5, =OSTCBHighRdy		; Get highest priority task TCB address
	LDR	r5, [r5]				; get stack pointer
	LDR	sp, [r5]				; switch to the new stack
	STR	r5, [r4]				; set new current task TCB address

	LDMFD	sp!, {r4}		
	MSR	SPSR_cxsf, r4
	LDMFD	sp!, {r4}			; get new state from top of the stack
	MSR	CPSR_cxsf, r4			; CPSR should be SVC32Mode
	LDMFD	sp!, {r0-r12, lr, pc }	

;-------------------------------------------------------------------------------------
; Function: OSCtxSw
; Purpose:
; 	To perform a context switch from the Task Level.
; Notes:
;	The whole function is executed in CRITICAL state. See OSSched().
;-------------------------------------------------------------------------------------
	EXPORT  OSCtxSw
  	IMPORT	OSTCBCur
	IMPORT	OSTCBHighRdy
	IMPORT	OSPrioCur
	IMPORT	OSPrioHighRdy

OSCtxSw
    STMFD	sp!, {lr}			; save lr
	STMFD	sp!, {r0-r12}		; save registers and ret address
	mrs 	r4, CPSR                ; load current psr to r4
  	stmfd 	sp!, {r4}               ; save current PSR to stack
  	mrs 	r4, SPSR                ; load saved psr to r4
  	stmfd 	sp!, {r4}               ; saved saved psr to stack

  ;OSPrioCur = OSPrioHighRdy
  	ldr 	r4, =OSPrioCur          ; load the current priority pointer
  	ldr 	r5, =OSPrioHighRdy      ; load address of highest prio task
  	ldrb  	r6, [r5]                ; load value of highest prio task
  	strb  	r6, [r4]                ; store value of highest in current

  ; Get current task TCB address
  	ldr 	r4, =OSTCBCur           ; load pointer
  	ldr 	r5, [r4]                ; load current tcb sp
  	str 	sp, [r5]                ; store sp in preempted tasks's TCB

  ; Get highest priority task TCB address
  	ldr	r6, =OSTCBHighRdy
  	ldr 	r6, [r6]                ; get highrdy's sp
  	ldr 	sp, [r6]                ; set sp = highrdy[sp]

  ; OSTCBCur = OSTCBHighRdy
 	str 	r6, [r4]                ; set new current task TCB address
  
  	ldmfd 	sp!, {r4}               ; load saved SPSR from stack
  	msr 	SPSR_c, r4                ; spsr = saved spsr
  	ldmfd 	sp!, {r4}               ; load saved cpsr from stack
  	msr 	CPSR_c, r4                ; cpsr = saved cpsr
  	ldmfd 	sp!, {r0-r12, r14}      ; restore r0-r12 and lr interworking
  	bx  	r14                     ; interworking branch on lr
;--------------------------------------------------------------------------------------

;--------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------
; Function: OSIntCtxSw
; Purpose:
; 	To perform a context switch from the interrupt level.
; Notes:
;   Sets up the stacks and registers to call the task level context switch
;-------------------------------------------------------------------------------------
	EXPORT  OSIntCtxSw
	IMPORT OSTaskSwHook
	IMPORT	OSTCBCur
	IMPORT	OSTCBHighRdy
	IMPORT	OSPrioCur
	IMPORT	OSPrioHighRdy

OSIntCtxSw
	
; Interrupt Exit if higher priority task ready to run
; New Task Context switch 

	add	sp,sp, #8              ; adjust sp to compensate for the call to OSIntExit       
	msr     CPSR_c, #0x92           ; switch to IRQ mode and disable IRQ's                                      ; the following 2 lines keep the stack
                                      
  	ldmfd   sp!, {r12, r14}         ; restore the stack 
	ldmfd   sp!, {r12}   

	ldr     r12, =AIC_BASE
    str	r12, [r12, #AIC_EOICR]  ; write any value to EOICR to signal end of int
   	msr     CPSR_c, #ARM_MODE_SYS   ; switch back to system mode with IRQ and FIQ enabled
       
	
	mrs 	r4, CPSR                ; load current psr to r4
  	stmfd 	sp!, {r4}               ; save current PSR to stack
  	mrs 	r4, SPSR                ; load saved psr to r4
  	stmfd 	sp!, {r4}               ; saved saved psr to stack

  ;OSPrioCur = OSPrioHighRdy
  	ldr 	r4, =OSPrioCur          ; load the current priority pointer
  	ldr 	r5, =OSPrioHighRdy      ; load address of highest prio task
  	ldrb  	r6, [r5]                ; load value of highest prio task
  	strb  	r6, [r4]                ; store value of highest in current

  ; Get current task TCB address
  	ldr 	r4, =OSTCBCur           ; load pointer
  	ldr 	r5, [r4]                ; load current tcb sp
  	str 	sp, [r5]                ; store sp in preempted tasks's TCB

  ; Get highest priority task TCB address
  	ldr	r6, =OSTCBHighRdy
  	ldr 	r6, [r6]                ; get highrdy's sp
  	ldr 	sp, [r6]                ; set sp = highrdy[sp]

  ; OSTCBCur = OSTCBHighRdy
 	str 	r6, [r4]                ; set new current task TCB address
  
  	ldmfd 	sp!, {r4}               ; load saved SPSR from stack
  	msr 	SPSR_c, r4                ; spsr = saved spsr
  	ldmfd 	sp!, {r4}               ; load saved cpsr from stack
  	msr 	CPSR_c, r4                ; cpsr = saved cpsr
  	ldmfd 	sp!, {r0-r12, r14}      ; restore r0-r12 and lr interworking
  	bx  	r14                     ; interworking branch on lr

;-------------------------------------------------------------------------------------
; Function: OSISR
; Purpose:
; 	   The IRQ interrupt handler	   EXPORT	OSTickISR
;-------------------------------------------------------------------------------------
	   EXPORT   OSTickISR
	   IMPORT	OSIntEnter
	   IMPORT	OSTimeTick
	   IMPORT	OSIntExit
    


OSTickISR
 	;- Adjust and save LR_irq in IRQ stack
        sub     r14, r14, #4
        stmfd   sp!, {r14}

;- Save SPSR and r0 in IRQ stack
        mrs     r14, SPSR
        stmfd   sp!, {r12, r14}
   
;read the interrupt status reg to clear it
        ldr     r12,=TC1_BASE       	; load tc0  base address
        ldr     r12,[r12, #0x020]   	; read from status register offse

;- Enable Interrupt and Switch in SYS Mode
        mrs     r12, CPSR
        bic     r12, r12, #I_BIT
        orr     r12, r12, #ARM_MODE_SYS
        msr     CPSR_c, r12              

;- Save scratch/used registers and LR in SYS Stack
        stmfd   sp!, { r0-r12,r14}
	    
	    bl    OSIntEnter   
	    bl 	  OSIntExit
      
; Interrupt Exit if no higher priority task ready to run
         
; restore interrupted task  
;- Restore scratch/used registers and LR from System Stack
        ldmfd   sp!, { r0-r12, r14}
                    
;- Disable Interrupt and switch back in IRQ mode
        mrs	r12, CPSR
        bic     r12, r12, #ARM_MODE_SYS
        orr     r12, r12, #I_BIT:OR:ARM_MODE_IRQ
        msr     CPSR_c, r12
        
;- Mark the End of Interrupt on the AIC
        ldr     r12, =AIC_BASE
        str	r12, [r12, #AIC_EOICR]
;- Restore SPSR_irq and r0 from IRQ stack
        ldmfd   sp!, {r12, r14}
        msr     SPSR_c, r14
;- Restore adjusted  LR_irq from IRQ stack directly in the PC
        ldmfd   sp!, {pc}^
;-------------------------------------------------------------------------------------
; Functions: ARMDisableInt  ARMEnableInt
; Purpose:
;    Disable and enable IRQ and FIQ preserving current CPU mode.
;-------------------------------------------------------------------------------------	
	EXPORT 	ARMDisableInt
ARMDisableInt
	mrs	  r0,cpsr           			; current CSR
    mov   r1, r0           				; make a copy for masking
    orr   r1, r1, #0xC0     			; mask off int bits
    msr   CPSR_cxsf, r1         		; disable ints (IRQ and FIQ)
    and   r0, r0, #0x80     			; return FIQ bit from original CSR
    mov   pc,lr     

	EXPORT 	ARMEnableInt 
ARMEnableInt
	mrs   r0, cpsr          			; current CSR
    bic   r0, r0, #0x80     			; mask on ints
    msr   CPSR_cxsf, r0     			; enable ints (IRQ and FIQ)
    mov   pc,lr             			; return
           
           END
                    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -