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

📄 serlasm.s

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 S
📖 第 1 页 / 共 2 页
字号:
                ; Reset the SVC Stack Pointer (if the new task is an SVC task,        ; the correct sp will be set later)        LDR   sp, =Angel_StackBase        LDR   sp, [sp]        ADD   sp, sp, #Angel_SVCStackOffset        angel_StartTask_NonSVCEntry        ; Put CPSR, r8-r12, r14, (SPSR), r0, r1, PC on the Appl stack        ; Note that SPSR is only VALID if moving to non USR mode        LDR   r1, [r0, #Angel_RegBlock_R0offset + (13*4)] ; Appl sp        LDR   r2, [r0, #Angel_RegBlock_CPSRoffset]        ADD   r0, r0, #Angel_RegBlock_R0offset + (8*4)        LDMIA r0, {r3,r4,r5,r6,r7}      ; r8-r12 go in r3-r7        SUB   r0, r0, #Angel_RegBlock_R0offset + (8*4)        LDR   r8, [r0, #Angel_RegBlock_R0offset + (14*4)]        LDR   r9, [r0, #Angel_RegBlock_SPSRoffset]        LDR   r10, [r0, #Angel_RegBlock_R0offset]        LDR   r11, [r0, #Angel_RegBlock_R0offset + (1*4)]        LDR   r12, [r0, #Angel_RegBlock_R0offset + (15*4)]        STMFD r1!, {r2-r12}        ; Restore r2-r7 from regblock        ADD   r0, r0, #Angel_RegBlock_R0offset + (2*4)        LDMFD r0, {r2-r7}      ; Get r2-r7 from regblock        ; Now we have lost the ptr to regblock, but still have stuff        ; on the Appl stack.        LDMFD r1, {r0}          ; Get CPSR from Application stack        IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0          BIC   r0, r0, #Tbit   ; Ensure T bit is never set here!        ENDIF        ; If we need to start a USR mode task, we cannot disable interrupts        ; to set up USR sp safely, as we won't be able to reenable interrupts        ; later.        ; Instead we must set up USR sp now, before switching to USR mode.        AND   r14, r0, #ModeMask        CMP   r14, #USRmode        BNE   ProtectAndChangeMode        MOV   r14, r1        STMFD r1!, {r14}        ; save USR sp        LDMFD r1, {sp}^         ; get USR sp        ADD   r1, r1, #4        ; reset r1        B     ChangeMode        ProtectAndChangeMode        ; We are in a privileged mode.        ; Disable interrupts until the last minute to give us a chance        ; to set up the stack pointer safely for our new task        IF (FIQ_SAFETYLEVEL >= FIQ_NeverUsesSerialiser_DoesNotReschedule)          ORR r0, r0, #IRQDisable        ELSE          ORR r0, r0, #IRQDisable + FIQDisable        ENDIF        ChangeMode        ; Change mode        ; Also set up Appl sp and r8-12, r14        MSR   CPSR_cxsf, r0        NOP        MOV   sp, r1            ; already done if USR mode, but that's okay        LDMFD sp!, {r0}         ; Get CPSR from Application stack        LDMFD sp!, {r8-r12,r14} ; restore r8-r12 + r14        ; Decide whether to restore SPSR (not in USR / SYS mode)        ; But don't forget this corrupts the flag bits in CPSR!        AND   r1, r0, #ModeMask        CMP   r1, #USRmode        CMPNE r1, #SYSmode        ADDEQ sp, sp, #4        ; If USR or SYS skip over SPSR on stack        LDMNEFD sp!, {r1}       ; Do next (NE) instrs only if not SYS or USR        MSRNE SPSR_cxsf, r1        IF :DEF: THUMB_SUPPORT :LAND: THUMB_SUPPORT<>0          TST   r0, #Tbit          BEQ   ResumeARM          BIC   r0, r0, #Tbit          MSR   CPSR_cxsf, r0  ; Restore flags & IF bits corrupted since mode change          ADR   r0, NextInstructionLabel+1          BX    r0              ; Switch into Thumb state !NextInstructionLabel          CODE16          NOP          POP  {r0, r1, pc}           ; And the application executes in Thumb state !          CODE32          ALIGN        ENDIFResumeARM        AND   r1, r0, #ModeMask        CMP   r1, #USRmode        BEQ   UserResumeARM        CMP   r1, #SYSmode        BEQ   UserResumeARM        ; Privileged Mode resume - we must not enable interrupts until        ; the very last instruction!        MSR   SPSR_cxsf, r0        ADD   sp, sp, #(3 * 4)        LDMDB sp, {r0, r1, pc}^        ; and the task resumes ...        UserResumeARM        MSR   CPSR_cxsf, r0      ; Restore the flags & IF bits corrupted above        NOP        LDMFD sp!, {r0, r1, pc}        ; And the task executes!                ; ****************************************************************        EXPORT Angel_Yield        IMPORT Angel_YieldCore        ; For the interface details of this pseudo function refer to        ; serlock.h        ; Note that this an APCS conformant fn from the callers point        ; of view, so we (only) have to preserve r4-r11, r13 and the        ; mode we were called in.Angel_Yield        ; See what mode we are in and get into SVC and disable interrupts        MRS   r0, CPSR        AND   r0, r0, #ModeMask        CMP   r0, #USRmode        BNE   NotEnteredInUSR        STMFD sp!, {r0, r14}         ; Save the original CPSR and r14        BL    Angel_EnterSVC         ; This keeps the stacks the same        LDMFD sp!, {r0, r14}        B     InSVCInterruptsDisabledNotEnteredInUSR        CMP   r0, #SVCmode        BEQ   YieldInUsrOrSvcMode                ; Not USR or SVC - Oh dear!!!        ADR   a1, serlusrsvcmsg        B     __rt_asm_fatalerrorserlusrsvcmsg        DCB  "Yield not USR or SVC mode\n"        ALIGNYieldInUsrOrSvcMode        IF (FIQ_SAFETYLEVEL >= FIQ_NeverUsesSerialiser_DoesNotReschedule)          ORR r1, r0, #IRQDisable        ELSE          ORR r1, r0, #IRQDisable + FIQDisable        ENDIF        MSR   cpsr_cxsf, r1                ; Now in SVC with interrupts disabled, r0 = original CPSRInSVCInterruptsDisabled        ; Save the caller's regs into our shared regblock        ; We only have to save r4-r11, r13, cpsr, pc (says the APCS)        LDR   r1, =Angel_MutexSharedTempRegBlocks        STR   r0,  [r1, #Angel_RegBlock_CPSRoffset]        ; cpsr        STR   r13, [r1, #Angel_RegBlock_R0offset + (13*4)] ; sp        STR   r14, [r1, #Angel_RegBlock_R0offset + (15*4)] ; pc        ADD   r1, r1, #Angel_RegBlock_R0offset + (4*4)        STMIA r1, {r4-r11}        SUB   r0, r1, #Angel_RegBlock_R0offset + (4*4)         ; Now prepare to call Angel_SerialiseTask        ; r0 = called_by_yield        ; r1 = fn        ; r2 = state                  ; r3 = empty_stack        MOV   r0, #1        LDR   r1, =Angel_YieldCore        MOV   r2, #0        LDR   r3, =Angel_StackBase  ; Empty SVC Stack         LDR   r3, [r3]        ADD   r3, r3, #Angel_SVCStackOffset        B     Angel_SerialiseTask        ; and Angel_YieldCore will execute when SerialiseTask allows it to        ; ****************************************************************        IMPORT angel_SelectNextTask        EXPORT angel_NextTask        angel_NextTask        ; This can be "called" from SVC or USR.  It must get into SVC and        ; disable interrupts and grab the empty SVC stack.        ; Then it must call angel_SelectNextTask with no arguments.        ;        ; See what mode we are in and get into SVC and disable interrupts        MRS   r0, CPSR        AND   r0, r0, #ModeMask        CMP   r0, #USRmode        BNE   NotEnteredInUSR2        BL    Angel_EnterSVC         ; This keeps the stacks the same        B     InSVCInterruptsDisabled2NotEnteredInUSR2        CMP   r0, #SVCmode        BEQ   NextTaskUsrOrSvcMode                ; Not USR or SVC - Oh dear!!!        ADR  a1, serlusrsvcmsg        B    __rt_asm_fatalerrorntusrsvcmsg        DCB  "NextTask not USR or SVC mode\n"        ALIGN        NextTaskUsrOrSvcMode        IF (FIQ_SAFETYLEVEL >= FIQ_NeverUsesSerialiser_DoesNotReschedule)          ORR r1, r0, #IRQDisable        ELSE          ORR r1, r0, #IRQDisable + FIQDisable        ENDIF        MSR   cpsr_cxsf, r1                ; Now in SVC with interrupts disabledInSVCInterruptsDisabled2        ; Grab an empty SVC stack and call angel_SelectNextTask        LDR   sl, =Angel_StackBase        LDR   sl, [sl]        ADD   sp, sl, #Angel_SVCStackOffset        ADD   sl, sl, #Angel_SVCStackLimitOffset        LDR   r0, =angel_SelectNextTask        MOV   pc, r0        ; ****************************************************************        EXPORT angel_IdleLoopangel_IdleLoop        ; Reset the SVC stack        LDR   sp, =Angel_StackBase        LDR   sp, [sp]        ADD   sp, sp, #Angel_SVCStackOffset        ; Reenable interrupts        MRS   r0, CPSR        BIC   r0, r0, #IRQDisable + FIQDisable        MSR   CPSR_cxsf, r0        ; Repeatedly call Angel_YieldIdleLoop        BL    Angel_Yield        B     IdleLoop        ENDIF                   ; ... else not minimal angel ...                        END

⌨️ 快捷键说明

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