函數嵌套時以及異常響應時,寄存器LR的作用存在顯著區別,理解這個問題對于理解freeRTOS底層代碼的實現大有幫助,具體使用過程如下:
一 函數嵌套時的LR使用的具體過程
在ARM架構(特別是M0處理器)中,函數嵌套調用時LR(Link Register)寄存器的處理過程如下:
1 基本調用機制
當使用BL指令調用函數時,處理器在進行跳轉之前,會將當前函數的下一條地址,即(PC+4)的地址,存入LR寄存器,
被調函數執行完畢函數返回時,通過MOV pc,lr 指令加載LR寄存器的值到PC寄存器,實現函數返回。
2 函數嵌套時的處理過程
每次BL調用時LR都會被新的返回值覆蓋,
內層函數調用前需要對原LR值進行保存,通常壓棧。以下是一個具體示例:
main:
? ? BL outer_func
? ? B .
outer_func:
? ? PUSH {LR} ? ? ? ; 保存返回地址
? ? BL inner_func
? ? POP {LR} ? ? ? ?; 恢復LR
? ? BX LR
inner_func:
? ? ; 函數體
? ? BX LR
從以上紅色字體可以看出,最后一層函數在返回時,是先執行BX lr指令返回,然后再執行出棧操作恢復包括上一層函數返回地址寄存器LR在內的所有棧內容。
二 異常發生時,LR的使用機制
以FreeRTOS操作系統為例,LR工作在異常返回機制狀態下:
?1. LR寄存器(R14)的作用
- ARM Cortex-M架構中,LR寄存器在觸發異常(如SVC)時會被自動設置為特殊的
EXC_RETURN
值。該值包含兩部分信息:- ?異常返回模式?:標識返回后使用MSP(主棧指針)還是PSP(進程棧指針);
- ?棧幀類型?:指示硬件需要恢復的寄存器集合。
- 在FreeRTOS任務切換場景中,
EXC_RETURN
通常設置為使用PSP,并觸發硬件自動從任務棧恢復上下文。
2.?BX R14的執行邏輯
中斷返回時,BX R14的執行邏輯,通常不是直接將LR寄存器的值賦值給PC寄存器,而是通過EXC_RETURN
觸發異常返回流程,此時處理器會:
- 根據
EXC_RETURN
確定使用PSP作為棧指針; - 從PSP指向的任務棧中彈出保存的寄存器(包括R0-R3、R12、LR、PC、xPSR);
- 將PC設置為任務入口地址(即任務函數指針)。
以下為freeRTOS代碼示例:
SVC異常:
PendSV異常: