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

📄 os_cpu_a.asm

📁 实现了UCOS-II在AT91SAM7S64上的移植,并建立了加法程序验证了移植的成功
💻 ASM
字号:
// os_cpu.asm
            EXTERN  OSRunning                    ; 外部参考
            EXTERN  OSPrioCur
            EXTERN  OSPrioHighRdy
            EXTERN  OSTCBCur
            EXTERN  OSTCBHighRdy
            EXTERN  OSIntNesting
            EXTERN  OSIntExit
            EXTERN  OSTaskSwHook
            EXTERN  OS_CPU_IRQ_ISR_Handler
            EXTERN  OS_CPU_FIQ_ISR_Handler

            PUBLIC  OS_CPU_SR_Save               ; 本文件中定义的函数
            PUBLIC  OS_CPU_SR_Restore
            PUBLIC  OSStartHighRdy
            PUBLIC  OSCtxSw
            PUBLIC  OSIntCtxSw
            PUBLIC  OS_CPU_IRQ_ISR
            PUBLIC  OS_CPU_FIQ_ISR


NO_INT      EQU     0xC0                         ; 用于禁止FIQ和IRQ中断的屏蔽码
SVC32_MODE  EQU     0x13
FIQ32_MODE  EQU     0x11
IRQ32_MODE  EQU     0x12

;*********************************************************************************************************
;                                         方式3函数的临界部分
; 说明:通过保存中断状态来禁止/允许中断。一般来说应该将中断禁止标志保存在变量cpu_sr中,然后禁止中断。
;       将cpu_sr复制回CPU的状态寄存器即可恢复中断禁止状态。
;
; 原型:OS_CPU_SR  OS_CPU_SR_Save(void);
;       void       OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;
; 注意::1) 函数一般使用方法容下:
;                 void Task (void *p_arg) {
;                 #if OS_CRITICAL_METHOD == 3          // 分配CPU状态寄存器存储单元
;                     OS_CPU_SR  cpu_sr;
;                 #endif
;                          :
;                          :
;                     OS_ENTER_CRITICAL();             // cpu_sr = OS_CPU_SaveSR();
;                          :
;                          :
;                     OS_EXIT_CRITICAL();              // OS_CPU_RestoreSR(cpu_sr);
;                          :
;                          :
;                 }
;
;              2) OS_CPU_SaveSR()                      // 禁止中断
;*********************************************************************************************************
        RSEG CODE:CODE:NOROOT(2)
        CODE32

OS_CPU_SR_Save
        MRS     R0,CPSR                     ; 设置CPSR中的IRQFIQ位以禁止所有中断
        ORR     R1,R0,#NO_INT
        MSR     CPSR_c,R1
        MRS     R1,CPSR                     ; 确认CPSR中包含了合适的中断禁止标志
        AND     R1,R1,#NO_INT
        CMP     R1,#NO_INT
        BNE     OS_CPU_SR_Save              ; 没有恰当禁止,重试
        BX      LR                          ; 已禁止

OS_CPU_SR_Restore
        MSR     CPSR_c,R0
        BX      LR

;*********************************************************************************************************
;                                            启动多任务
; 原型:void OSStartHighRdy(void)
;
; 注意:1) OSStartHighRdy()函数必须:
;              a) 调用 OSTaskSwHook(),
;              b) 然后将 OSRunning 设置为 TRUE,
;              c) 切换到最高优先级任务
;*********************************************************************************************************
        RSEG CODE:CODE:NOROOT(2)
        CODE32

OSStartHighRdy
        LDR     R0, ??OS_TaskSwHook     ; OSTaskSwHook();
        MOV     LR, PC
        BX      R0
        MSR     CPSR_cxsf, #0xD3        ; 切换到管理模式,禁止 IRQ 和 FIQ
        LDR     R4, ??OS_Running        ; OSRunning = TRUE
        MOV     R5, #1
        STRB    R5, [R4]
                                        ; 切换到最高优先级任务
        LDR     R4, ??OS_TCBHighRdy     ; 获得最高优先级任务的TCB地址
        LDR     R4, [R4]                ; 获得堆栈指针
        LDR     SP, [R4]                ; 切换到新堆栈

        LDR     R4,  [SP], #4           ; 弹出新任务的 CPSR
        MSR     SPSR_cxsf,R4
        LDMFD   SP!, {R0-R12,LR,PC}^    ; 弹出新任务的上下文(context)

;*********************************************************************************************************
;                                     执行任务切换(任务级) - OSCtxSw()
;
; 注意:1) OSCtxSw() 应在禁止FIQ和IRQ中断的条件下以系统模式调用
;
;       2) OSCtxSw() 的伪代码如下:
;              a) 将当前任务的上下文(context)保存到当前任务的堆栈中
;              b) OSTCBCur->OSTCBStkPtr = SP;
;              c) OSTaskSwHook();
;              d) OSPrioCur             = OSPrioHighRdy;
;              e) OSTCBCur              = OSTCBHighRdy;
;              f) SP                    = OSTCBHighRdy->OSTCBStkPtr;
;              g) 从新任务的堆栈中恢复新任务的上下文(context)
;              h) 返回到新任务的代码中
;
;           3) 入口:
;              OSTCBCur      指向要挂起任务的 OS_TCB
;              OSTCBHighRdy  指向要恢复任务的 OS_TCB
;*********************************************************************************************************
        RSEG CODE:CODE:NOROOT(2)
        CODE32
OSCtxSw
                                        ; 保存当前任务的上下文(CONTEXT)
        STMFD   SP!, {LR}               ; 当前地址压栈
        STMFD   SP!, {LR}
        STMFD   SP!, {R0-R12}           ; 寄存器压栈
        MRS     R4,  CPSR               ; 当前CPSR压栈
        TST     LR, #1                  ; 测试是否从Thumb模式下调用
        ORRNE   R4,  R4, #0x20          ; 是,置1 T 标志
        STMFD   SP!, {R4}

        LDR     R4, ??OS_TCBCur         ; OSTCBCur->OSTCBStkPtr = SP;
        LDR     R5, [R4]
        STR     SP, [R5]

        LDR     R0, ??OS_TaskSwHook     ; OSTaskSwHook();
        MOV     LR, PC
        BX      R0

        LDR     R4, ??OS_PrioCur        ; OSPrioCur = OSPrioHighRdy
        LDR     R5, ??OS_PrioHighRdy
        LDRB    R6, [R5]
        STRB    R6, [R4]

        LDR     R4, ??OS_TCBCur         ; OSTCBCur  = OSTCBHighRdy;
        LDR     R6, ??OS_TCBHighRdy
        LDR     R6, [R6]
        STR     R6, [R4]

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

                                        ; 恢复新任务的上下文(CONTEXT)
        LDMFD   SP!, {R4}               ; 新任务的CPSR出栈
        MSR     SPSR_cxsf, R4

        LDMFD   SP!, {R0-R12,LR,PC}^    ; 新任务的下文(CONTEXT)出栈

;*********************************************************************************************************
;                                执行任务切换(中断级) - OSIntCtxSw()
;
; 注意: 1) OSIntCtxSw()  应在禁止FIQ和IRQ中断的条件下以系统模式调用
;
;        2) OSCtxSw() 的伪代码如下:
;              a) OSTaskSwHook();
;              b) OSPrioCur             = OSPrioHighRdy;
;              c) OSTCBCur              = OSTCBHighRdy;
;              d) SP                    = OSTCBHighRdy->OSTCBStkPtr;
;              e) 从新任务的堆栈中恢复新任务的上下文(context)
;              f) 返回到新任务的代码中
;
;           3) 入口:
;              OSTCBCur      指向要挂起任务的 OS_TCB
;              OSTCBHighRdy  指向要恢复任务的 OS_TCB
;*********************************************************************************************************
        RSEG CODE:CODE:NOROOT(2)
        CODE32
OSIntCtxSw
        LDR     R0, ??OS_TaskSwHook     ; OSTaskSwHook();
        MOV     LR, PC
        BX      R0

        LDR     R4,??OS_PrioCur         ; OSPrioCur = OSPrioHighRdy
        LDR     R5,??OS_PrioHighRdy
        LDRB    R6,[R5]
        STRB    R6,[R4]

        LDR     R4,??OS_TCBCur          ; OSTCBCur  = OSTCBHighRdy;
        LDR     R6,??OS_TCBHighRdy
        LDR     R6,[R6]
        STR     R6,[R4]

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

                                        ; 恢复新任务的上下文(CONTEXT)
        LDMFD   SP!, {R4}               ; 新任务的CPSR出栈
        MSR     SPSR_cxsf, R4

        LDMFD   SP!, {R0-R12,LR,PC}^    ; 新任务的上下文(context)出栈

;*********************************************************************************************************
;                                            IRQ 中断服务子程序
;*********************************************************************************************************
        RSEG CODE:CODE:NOROOT(2)
        CODE32
OS_CPU_IRQ_ISR

        STMFD   SP!, {R1-R3}                   ; 工作寄存器压入IRQ堆栈
        MOV     R1, SP                         ; 保存IRQ堆栈指针
        ADD     SP, SP,#12                     ; 调整IRQ堆栈指针
        SUB     R2, LR,#4                      ; 调整PC返回地址

        MRS     R3, SPSR                       ; 将SPSR(即中断任务的CPSR)复制到R3
        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; 切换到管理模式

                                               ; 将任务的上下文(CONTEXT)保存到任务堆栈
        STMFD   SP!, {R2}                      ; 任务的返回地址压栈
        STMFD   SP!, {LR}                      ; 任务的LR压栈
        STMFD   SP!, {R4-R12}                  ; 任务的R12-R4压栈

        LDMFD   R1!, {R4-R6}                   ; 将任务的R1-R3从IRQ堆栈移动到管理堆栈
        STMFD   SP!, {R4-R6}
        STMFD   SP!, {R0}                      ; 任务的R0压入任务堆栈
        STMFD   SP!, {R3}                      ; 任务的CPSR(即IRQ's SPSR)压栈

                                               ; 处理嵌套计数器
        LDR     R0, ??OS_IntNesting            ; OSIntNesting++;
        LDRB    R1, [R0]
        ADD     R1, R1,#1
        STRB    R1, [R0]

        CMP     R1, #1                         ; if (OSIntNesting == 1) {
        BNE     OS_CPU_IRQ_ISR_1
        LDR     R4, ??OS_TCBCur                ;   OSTCBCur->OSTCBStkPtr = SP
        LDR     R5, [R4]
        STR     SP, [R5]                       ; }

OS_CPU_IRQ_ISR_1
        MSR     CPSR_c, #(NO_INT | IRQ32_MODE) ; 切换到IRQ模式(使用IRQ堆栈处理中断)

        LDR     R0, ??OS_CPU_IRQ_ISR_Handler   ; OS_CPU_IRQ_ISR_Handler();
        MOV     LR, PC
        BX      R0

        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; 切换到管理模式

        LDR     R0, ??OS_IntExit               ; OSIntExit();
        MOV     LR, PC
        BX      R0

                                               ; 恢复新任务的上下文(CONTEXT)
        LDMFD   SP!, {R4}                      ; 新任务的CPSR出栈
        MSR     SPSR_cxsf, R4

        LDMFD   SP!, {R0-R12,LR,PC}^           ; 新任务的上下文(context)出栈

;*********************************************************************************************************
;                                           FIQ 中断服务子程序
;*********************************************************************************************************
        RSEG CODE:CODE:NOROOT(2)
        CODE32
OS_CPU_FIQ_ISR

        STMFD   SP!, {R1-R3}                   ; 工作寄存器压入FIQ堆栈
        MOV     R1, SP                         ; 保存FIQ堆栈指针
        ADD     SP, SP,#12                     ; 调整FIQ堆栈指针
        SUB     R2, LR,#4                      ; 调整PC返回地址

        MRS     R3, SPSR                       ; 将SPSR(即中断任务的CPSR)复制到R3
        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; 切换到管理模式

                                               ; 将任务的上下文(CONTEXT)保存到任务堆栈
        STMFD   SP!, {R2}                      ; 任务的返回地址压栈
        STMFD   SP!, {LR}                      ; 任务的LR压栈
        STMFD   SP!, {R4-R12}                  ; 任务的R12-R4压栈
        LDMFD   R1!, {R4-R6}                   ; 将任务的R1-R3从IRQ堆栈移动到管理堆栈
        STMFD   SP!, {R4-R6}
        STMFD   SP!, {R0}                      ; 任务的R0压入任务堆栈
        STMFD   SP!, {R3}                      ; 任务的CPSR(即FIQ's SPSR)压栈

                                               ; 处理嵌套计数器
        LDR     R0, ??OS_IntNesting            ; OSIntNesting++;
        LDRB    R1, [R0]
        ADD     R1, R1,#1
        STRB    R1, [R0]

        CMP     R1, #1                         ; if (OSIntNesting == 1) {
        BNE     OS_CPU_FIQ_ISR_1
        LDR     R4, ??OS_TCBCur                ;     OSTCBCur->OSTCBStkPtr = SP
        LDR     R5, [R4]
        STR     SP, [R5]                       ; }

OS_CPU_FIQ_ISR_1
        MSR     CPSR_c, #(NO_INT | FIQ32_MODE) ; 切换到FIQ模式(使用FIQ堆栈处理中断)
        LDR     R0, ??OS_CPU_FIQ_ISR_Handler   ; OS_CPU_FIQ_ISR_Handler();
        MOV     LR, PC
        BX      R0

        MSR     CPSR_c, #(NO_INT | SVC32_MODE) ; 切换到管理模式
        LDR     R0, ??OS_IntExit               ; OSIntExit();
        MOV     LR, PC
        BX      R0

                                               ; 恢复新任务的上下文(CONTEXT)
        LDMFD   SP!, {R4}                      ; 新任务的CPSR出栈
        MSR     SPSR_cxsf, R4
        LDMFD   SP!, {R0-R12,LR,PC}^           ; 新任务的上下文(context)出栈

;*********************************************************************************************************
;                                               变量的指针
;*********************************************************************************************************
        DATA
??OS_TaskSwHook:
        DC32    OSTaskSwHook
??OS_CPU_IRQ_ISR_Handler:
        DC32    OS_CPU_IRQ_ISR_Handler
??OS_CPU_FIQ_ISR_Handler:
        DC32    OS_CPU_FIQ_ISR_Handler
??OS_IntExit:
        DC32    OSIntExit
??OS_IntNesting:
        DC32    OSIntNesting
??OS_PrioCur:
        DC32    OSPrioCur
??OS_PrioHighRdy:
        DC32    OSPrioHighRdy
??OS_Running:
        DC32    OSRunning
??OS_TCBCur:
        DC32    OSTCBCur
??OS_TCBHighRdy:
        DC32    OSTCBHighRdy

        END

⌨️ 快捷键说明

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