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