解析ARM中OS_CPU_A.S(中断级方式)

 

MRS:Move PSR to register,将程序状态寄存器的值复制到通用寄存器

例:MRS R0,CPSR; 传送CPSR 的内容到 R0

MSR:Move Register to PSR,将通用寄存器的值复制到到程序状态寄存器

例:MSR CPSR_c,R0; 传送 R0 的内容到 SPSR,但仅仅修改 CPSR 中的控制位域

LDR:Load word,装载一个字数据(立即数/内容)到一个寄存器

例:LDR R0, [R1,R2]!; 将存储器地址为 R1+R2 的字数据读入R0,并将新地址R1+R2 写入 R1

LDRB:Load byte,装载一个字节数据(立即数/内容)到一个寄存器

例:LDRB R0,[R1,#8]; 将存储器地址为R1+8的字节数据读入R0,并将R0的高 24 位清零

STR:store,装载寄存器的字数据到地址的内容里

例:STR R0,[R1], #8; 将R0中的字数据写入R1为地址的存储器中,并将新地址R1+8 写入 R1

STRB:Store byte,装载寄存器的字节数据到地址的内容里

例:STRB R0, [RS#8] ;将寄存器 R0 中的字节数据写入以 R1+8 为地址的存储

器中

LDM:load multiple,将寄存器地址的内容顺序恢复(出栈)到一系列寄存器组中。

例:LDMFD R13!,{R0,R4-R12, PC}^;R13即SP。将堆栈内容顺序弹出(此时堆栈递增)到寄存器R0,R4-R12,LR。后缀!表示最后的地址写会到R13内,末尾^意味这cpsr的值将从spsr中得到恢复,这只有在pc同时也被装载的情况下才有效。如果pc没有被装载,那么^只恢复用户模式的备份寄存器组。

STM:store multiple,将一系列寄存器值顺序存入(压栈)到某一寄存器地址的内容中

STMFD R13!, {R0, R4-R12, LR}; 将寄存器列表中的寄存器LR, R12-R4, R0

顺序压入(此时堆栈递减)堆栈。后缀!表示最后的地址写回到R13中。

BL:Branch with link,带返回的跳转指令。

例:BL Label; 当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14(LR)中
 

1  把被中止任务的断点指针保存到任务堆栈中;

2  把CPU通用寄存器的内容保存到任务堆栈中;

3 把被中止任务的任务堆栈指针当前值保存到该任务的任务控制块的OSTCBStkPtr中;

4 获得待运行任务的任务控制块;

5  使CPU通过任务控制块获得待运行任务的任务堆栈指针;

6  把待运行任务堆栈中通用寄存器的内容恢复到CPU的通用寄存器中;

7  使CPU获得待运行任务的断点指针(该指针是待运行任务在上一次被调度器中止运行时保留在任务堆栈中的)。
 

 

以上的代码是在中断的方式进行代码的切换的

TickHandler
    STMDB    sp!,{r0-r12,lr}   //先保存当前的寄存器地址

    ;interrupt disable(not nessary)
;    mrs        r0, CPSR
;    orr        r0, r0, #0x80        ; and set IRQ disable flag
;    msr        CPSR_cxsf, r0
    
    ;End of interrupt
    ;(Clear pending bit of INTPEND that don't accessed it.)'
    ;    rI_ISPC= BIT_TIMER0;
    LDR    r0, =RSRCPND
    LDR    r1, =BIT_TIMER0
    STR    r1, [r0]

    LDR    r0, =RINTPND
    LDR    r1, =BIT_TIMER0
    STR    r1, [r0]   //将中断位清零
    
    BL    IrqStart
    BL    OSTimeTick
    BL    IrqFinish        ;a1= return value    0:not context switch, otherwise:context switch

    CMP        a1, #0
    LDRNE    pc, =_CON_SWAP
 

_NOT_CON_SWAP   //没有上下问切换的处理,直接返回原来的地址
    ;now context switching
    LDMIA    sp!,{r0-r12,lr}
    SUB        lr, lr, #4
    STR        lr, SAVED_LR        ;STR lr, [pc, #SAVED_LR-.-8]

_CON_SWAP   //要进行上下文的切换
    ;now context switching
    LDMIA    sp!,{r0-r12,lr}           ; // 先还原原来的寄存数值,准备进行交换
    SUB        lr, lr, #4
    STR        lr, SAVED_LR        ;//提前先把返回的地址算好了,保存在一个变量里面

//切换到特权模式

    MRS             lr, SPSR      
    ORR             lr,lr,#0x80    ;
    AND             lr, lr, #0xFFFFFFE0
    ORR             lr, lr, #0x13
    MSR             CPSR_cxsf, lr   

    STR        r12, [sp, #-8]    ; 现在R12存在当前偏移位置的第二个地址中
    LDR        r12, SAVED_LR    ;先把计算好的PC地址存在R12中
    STMFD    sp!, {r12}        ; 现在R12的值压入栈中,栈来到偏移的第一个地址
    SUB        sp, sp, #4        ; 对栈指针地址进行-4,来到了第二个偏移的地址
    LDMIA    sp!, {r12}        ; 把原来的值赋值给R12,又回到第一个地址中
    STMFD    sp!, {lr}        ; 存储到第一个地址中
    STMFD    sp!, {r0-r12}    ;再存储其他的位置
    MRS        r4, CPSR
    AND    r4, r4, #0xFFFFFF7F    ;added 0526
    STMFD    sp!, {r4}        ; save current PSR
    MRS        r4, SPSR        ; YYY+
    STMFD    sp!, {r4}        ; YYY+ save SPSR

    ; OSPrioCur = OSPrioHighRdy
    LDR    r4, addr_OSPrioCur
    LDR    r5, addr_OSPrioHighRdy
    LDRB    r6, [r5]
    STRB    r6, [r4]
    

    //addr_OSTCBCur  双重指针,指向任务快地址
    ; Get current task TCB address
    LDR    r4, addr_OSTCBCur
    LDR    r5, [r4]
    STR    sp, [r5]        ; 保存之前的指针

    ; Get highest priority task TCB address
    LDR    r6, addr_OSTCBHighRdy
    LDR    r6, [r6]
    LDR    sp, [r6]        ;//得到新的指针地址

    ; OSTCBCur = OSTCBHighRdy
    STR    r6, [r4]        ; 把当前要切换的任务块交给当前地址

    LDMFD    sp!, {r4}        ;当前任务指针赋值给SP
;    AND        r4, r4, #0xFFFFFF20 
;    ORR        r4, r4, #0x13
    MSR    SPSR_cxsf, r4        ; //还原状态寄存器
    LDMFD    sp!, {r4}        ; YYY+
;    AND        r4, r4, #0xFFFFFF20
;    ORR        r4, r4, #0x13
    MSR    CPSR_cxsf, r4        ; //还原状态寄存器
    LDMFD    sp!, {r0-r12, lr, pc}    ; //任务切换完成

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

任务切换的方式/

OSStartHighRdy  
    MSR     CPSR_cxsf,#SVCMODE|NOINT     ;Switch to SVC mode with IRQ&FIQ disable
    BL        OSTaskSwHook                 ;Call user define Task switch hook
    LDR        R0, =OSRunning               
    MOV        R1, #1
    STRB     R1, [R0]
    LDR     R0, =OSTCBHighRdy
    LDR     R0, [R0]         
    LDR     SP, [R0]         
    LDMFD     SP!, {R0}  
    MSR     SPSR_cxsf, R0
    LDMFD     SP!, {R0-R12, LR, PC}^
 

OSCtxSw
    ;// 旧栈的示意图 :
    ;// CPSR         
    ;// R12~R0         
    ;// LR                 
    ;// PC

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

    LDR        R0, =OSTCBCur
    LDR        R0, [R0]
    STR        SP, [R0]

     BL         OSTaskSwHook

    LDR        R0, =OSTCBHighRdy
    LDR        R1, =OSTCBCur
    LDR        R0, [R0]
    STR        R0, [R1]

    LDR        R0, =OSPrioHighRdy
    LDR        R1, =OSPrioCur
    LDRB    R0, [R0]
    STRB    R0, [R1]

    LDR        R0, =OSTCBHighRdy
    LDR        R0, [R0]
    LDR        SP, [R0]

    LDMFD     SP!, {R0}        ;POP CPSR
    MSR     SPSR_cxsf, R0
    LDMFD     SP!, {R0-R12, LR, PC}^    

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]         
    BL        OSTimeTick
    MOV    PC, R5                ; Return     

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

//代码的开中断和关中断,可以用来解决代码可重入的问题

ARMDisableInt
    STMDB    sp!, {r0}
    MRS        r0, CPSR
    ORR        r0, r0, #NoInt
    MSR        CPSR_cxsf, r0
    LDMIA    sp!, {r0}
    MOV    pc, lr


    EXPORT    ARMEnableInt
ARMEnableInt
    STMDB    sp!, {r0}
    MRS    r0, CPSR
    AND r0, r0, #0x1f
    CMP r0, #IRQ32Mode
    LDREQ pc, =ARMInIRQMode
    MRS r0, CPSR
    BIC    r0, r0, #NoInt
    MSR    CPSR_cxsf, r0
ARMInIRQMode    
    LDMIA    sp!, {r0}
    MOV    pc, lr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值