📄 portmacro.s
字号:
;作者nuaa.tedden 2008-12-6 导航研究中心
;描述: 改文件是FreeRTOS移植代码的CPU支持部分,ADS1.2编译器
;主要的函数有
;portRESTORE_CONTEXT (任务堆栈恢复)
;portSAVE_CONTEXT (任务堆栈保护)
;portDISABLE_INTERRUPTS (全局中断关闭)
;portENABLE_INTERRUPTS (全局中断打开)
;
;
;
;
;
;
;
;
;
;
;
;
NoInt EQU 0x80
SVC32Mode EQU 0x13
SYS32Mode EQU 0x1f
CODE32 ;32位ARM代码
AREA OsSupport, CODE, READONLY
;引入外部变量
IMPORT pxCurrentTCB ;当前任务TCB的指针
IMPORT ulCriticalNesting ;中断嵌套层数全局变量
EXPORT portRESTORE_CONTEXT ;堆栈内容恢复
EXPORT portSAVE_CONTEXT ;保存寄存器内容
EXPORT portDISABLE_INTERRUPTS ;禁止中断
EXPORT portENABLE_INTERRUPTS ;打开中断
portRESTORE_CONTEXT
;进入SVC异常模式
MSR CPSR_c, #(NoInt | SVC32Mode)
;Set the LR to the task stack.
;将LR指向当前任务堆栈顶
LDR R0, =pxCurrentTCB ;获取当前任务TCB结构体指针
LDR R0, [R0] ;获取指向存储栈顶数据的指针
LDR LR, [R0] ;取出栈顶指针数据到LR中
; The critical nesting depth is the first item on the stack.
; Load it into the ulCriticalNesting variable.
;弹出栈顶的中断层数到全局变量中
LDR R0, =ulCriticalNesting
LDMFD LR!, {R1}
STR R1, [R0]
; Get the SPSR from the stack.
;弹出保存的SPSR
LDMFD LR!, {R0} ;栈顶的首个数据是保存的SPSR
MSR SPSR_cxsf, R0 ;将SPSR恢复
; Restore all system mode registers for the task.
; 恢复R0~R14
LDMFD LR, {R0-R14}^ ;依次恢复R0-R14,LR不会被改写。^表示更改的是用户模式的寄存器,因此将恢复用户模式的
;LR.要进行任务切换有两种情况.一是在中断的时候处于中断模式;或是处于SWI中断中,在特权模式
NOP
; Restore the return address.
; 获取返回地址
LDR LR, [LR, #+60] ;获取存放在栈底的返回地址
; And return - correcting the offset in the LR to obtain the
; correct address.
;设置PC,执行跳转
MOVS PC, LR ;返回地址,返回任务断点
portSAVE_CONTEXT ;保护任务现场,在这里实际并没有调用
; Push R0 as we are going to use the register.
STMDB SP!, {R0} ;先将R0压入栈底,后面要用到R0
; Set R0 to point to the task stack pointer.
STMDB SP,{SP}^ ;
NOP
SUB SP, SP, #4 ;
LDMIA SP!,{R0} ;
; Push the return address onto the stack.
STMDB R0!, {LR} ;将返回地址压栈,从堆栈的结构来看应该压在栈底
; Now we have saved LR we can use it instead of R0.
MOV LR, R0
; Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0}
; Push all the system mode registers onto the task stack.
STMDB LR,{R0-LR}^
NOP
SUB LR, LR, #60
; Push the SPSR onto the task stack.
MRS R0, SPSR
STMDB LR!, {R0}
LDR R0, =ulCriticalNesting
LDR R0, [R0]
STMDB LR!, {R0}
; Store the new top of stack for the task.
LDR R0, =pxCurrentTCB
LDR R0, [R0]
STR LR, [R0]
;以下两个函数被C函数调用
portDISABLE_INTERRUPTS
STMDB SP!, {R0} ; Push R0.将R0入栈
MRS R0, CPSR ; Get CPSR.获取CPSR
ORR R0, R0, #0xC0 ; Disable IRQ, FIQ.FIQ,IRQ禁止
MSR CPSR_cxsf, R0 ; Write back modified value.
LDMIA SP!, {R0} ; Pop R0.R0恢复
MOV PC, LR ; 函数返回
portENABLE_INTERRUPTS
STMDB SP!, {R0} ; Push R0.
MRS R0, CPSR ; Get CPSR.
BIC R0, R0, #0xC0 ; Enable IRQ, FIQ.
MSR CPSR_cxsf, R0 ; Write back modified value.
LDMIA SP!, {R0} ; Pop R0.
MOV PC, LR ; 函数返回
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -