cotex單片機寄存器(cm3爲例)

 ARM單片機寄存器列表:

 

堆棧指針 R13
  R13 是堆棧指針。在 CM3 處理器內核中共有兩個堆棧指針,於是也就支持兩個堆棧。
當引用 R13(或寫作 SP)時,你引用到的是當前正在使用的那一個,另一個必須用特殊的指
令來訪問(MRS,MSR 指令)。這兩個堆棧指針分別是:
     主堆棧指針(MSP),或寫作 SP_main。這是缺省的堆棧指針,它由 OS 內核、異常服務
例程以及所有需要特權訪問的應用程序代碼來使用。
     進程堆棧指針(PSP),或寫作 SP_process。用於常規的應用程序代碼(不處於異常服
用例程中時)。

MSP和PSP 的含義是Main_Stack_Pointer 和Process_Stack_Pointer

堆棧的 PUSH 與 POP
  堆棧是一種存儲器的使用模型。它由一塊連續的內存,以及一個棧頂指針組成,用
 於實現“先進後出”的緩衝區。其最典型的應用,就是在數據處理前先保存寄存器的值,
再在處理任務完成後從中恢復先前保護的這些值。 

因此,在 PUSH 新數據時,堆棧指針先減一個單元。通常在進入一個子程序後,第一件事就是把寄存器的值先
PUSH 入堆棧中,在子程序退出前再 POP 曾經 PUSH 的那些寄存器。另外,PUSH 和 POP 還
能一次操作多個寄存器。

可以使用 SP 表示 R13。在程序代碼中,both MSP 和 PSP 都被稱爲 R13/SP

不過,我們可以通過 MRS/MSR 指令來指名道姓地訪問具體的堆棧指針。
 MSP,亦寫作 SP_main,這是復位後缺省使用堆棧指針,服務於操作系統內核和異常服
務例程
而 PSP,亦寫作 SP_process,典型地用於普通的用戶線程中

寄存器的 PUSH 和 POP 操作永遠都是 4 字節對齊的——也就是說他們的地址必須是
0x4,0x8,0xc,……。這樣一來,R13的最低兩位被硬線連接到0,並且總是讀出0 (Read As Zero)。

連接寄存器 R14
  R14 是連接寄存器(LR)。在一個彙編程序中,你可以把它寫作 both LR 和 R14。LR 用於
在調用子程序時存儲返回地址。例如,當你在使用 BL(分支並連接,Branch and Link)指令時,
就自動填充 LR 的值。

main ;主程序

BL     function1 ; 使用“分支並連接”指令呼叫 function1
; PC= function1,並且 LR=main 的下一條指令地址

                Function1
… ; function1 的代碼
BX LR ; 函數返回(如果 function1 要使用 LR,必須在使用前 PUSH,
                           ; 否則返回時程序就可能跑飛了——譯註)

程序計數器 R15
  R15 是程序計數器,在彙編代碼中你也可以使用名字“PC”來訪問它。因爲 CM3 內部
使用了指令流水線,讀 PC 時返回的值是當前指令的地址+4。
比如說:
0x1000: MOV R0, PC ; R0 = 0x1004 
  如果向 PC 中寫數據,就會引起一次程序的分支(但是不更新 LR 寄存器) )。CM3 中的指
令至少是半字對齊的,所以 PC 的 LSB 總是讀回 0。然而,在分支時,無論是直接寫 PC 的值
還是使用分支指令,都必須保證加載到 PC 的數值是奇數(即 LSB=1),用以表明這是在
Thumb 狀態(半字對齊)下執行。
若寫了 0,則視爲企圖轉入 ARM 模式,CM3 將產生一個 fault 異
常。

特殊功能寄存器組
Cortex‐M3 中的特殊功能寄存器包括:

  1.              程序狀態寄存器組(PSRs 或曰 xPSR)
  2.              中斷屏蔽寄存器組(PRIMASK, FAULTMASK,以及 BASEPRI)
  3.              控制寄存器(CONTROL)

它們只能被專用的 MSR 和 MRS 指令訪問,而且它們也沒有存儲器地址。

  1. MRS <gp_reg>, <special_reg> ;讀特殊功能寄存器的值到通用寄存器
  2. MSR <special_reg>, <gp_reg> ;寫通用寄存器的值到特殊功能寄存器

程序狀態寄存器(PSRs 或曰 PSR)
程序狀態寄存器在其內部又被分爲三個子狀態寄存器:

  1.            應用程序 PSR(APSR)
  2.            中斷號 PSR(IPSR)
  3.            執行 PSR(EPSR)

通過 MRS/MSR 指令,這 3 個 PSRs 即可以單獨訪問,也可以組合訪問(2 個組合,3 個組合都可以)。當使用三合一的方式訪問時,應使用名字“xPSR”或者“PSR”。

 

 

stmdb    sp!, {fp, ip, lr, pc} //sp=sp-4,sp=pc;先壓PC ,把內容壓入下一個內存地址即原地址-4.   
                               //sp=sp-4,sp=lr;再壓lr
                               //sp=sp-4,sp=ip;再壓ip
                               //sp=sp-4,sp=fp;再壓fp
ldmia    sp, {fp, sp, pc}       //和stmdb成對使用,  
                               //fp=sp,sp=sp+4;先彈fp    //出棧還原+4
                               //sp=sp,sp=sp+4;先彈sp,此處的彈出不會  影響sp,因爲ldmia是一個機器週期執行完的。
                               //pc=sp,sp=sp+4;先彈pc
LDRH           R0, [R13, #0xC] //加載無符號半字數據,即低16位
LDRB           R0, [R13, #0x4] //加載一字節數據,即低8位

 

在特權級下,可以指定具體的堆棧指針,而不受當前使用堆棧的限制

MRS R0, MSP ; 讀取主堆棧指針到 R0
MSR MSP, R0 ; 寫入 R0 的值到主堆棧中
MRS R0, PSP ; 讀取進程堆棧指針到 R0
MSR PSP, R0 ; 寫入 R0 的值到進程堆棧中 
         通過讀取 PSP 的值,OS 就能夠獲取用戶應用程序使用的堆棧,進一步地就知道了在發
生異常時,被壓入寄存器的內容,而且還可以把其它寄存器進一步壓棧(使用STMDB和LDMIA
的書寫形式)。OS 還可以修改 PSP,用於實現多任務中的任務上下文切換。

堆棧指針 SP 指向最後一個被壓入堆棧的 32
位數值。在下一次壓棧時,SP 先自減 4,再存入新的數值。

POP 操作剛好相反:先從 SP 指針處讀出上一次被壓入的值,再把 SP 指針自增 4。

常用加載指令

  1. MRS 加載特殊功能寄存器的值到通用寄存器
  2. MSR 存儲通用寄存器的值到特殊功能寄存器
  3. NOP 無操作
  4. SEV 發送事件
  5. WFE 休眠並且在發生事件時被喚醒
  6. WFI 休眠並且在發生中斷時被喚醒
  7. ISB 指令同步隔離(與流水線和 MPU 等有關——譯註)              //隔離指令
  8. DSB 數據同步隔離(與流水線、MPU 和 cache 等有關——譯註)   //隔離指令
  9. DMB 數據存儲隔離(與流水線、MPU 和 cache 等有關——譯註)   //隔離指令

常用的多重存儲器訪問方式

LDMIA Rd!, {寄存器列表} 從 Rd 處讀取多個字。     每讀一個字後 Rd 自增一次,16
位寬度
STMIA Rd!, {寄存器列表} 存儲多個字到 Rd 處。      每存一個字後 Rd 自增一次,16
位寬度
LDMIA.W Rd!, {寄存器列表} 從 Rd 處讀取多個字。   每讀一個字後 Rd 自增一次,32
位寬度
LDMDB.W Rd!, {寄存器列表} 從 Rd 處讀取多個字。   每讀一個字前 Rd 自減一次,32
位寬度
STMIA.W Rd!, {寄存器列表} 存儲多個字到 Rd 處。     每存一個字後 Rd 自增一次,32
位寬度
STMDB.W Rd!, {寄存器列表} 存儲多個字到 Rd 處。     每存一個字前 Rd 自減一次,32
位寬度

常用的存儲器訪問指令

示例                                                                功能描述
LDRB Rd, [Rn, #offset]                      從地址 Rn+offset 處讀取一個字節到 Rd
LDRH Rd, [Rn, #offset]                      從地址 Rn+offset 處讀取一個半字到 Rd
LDR Rd, [Rn, #offset]                         從地址 Rn+offset 處讀取一個字到 Rd
LDRD Rd1, Rd2, [Rn, #offset]            從地址 Rn+offset 處讀取一個雙字(64 位整數)到 Rd1(低32 位)和 Rd2(高 32 位)中。
STRB Rd, [Rn, #offset]                       把 Rd 中的低字節存儲到地址 Rn+offset 處
STRH Rd, [Rn, #offset]                       把 Rd 中的低半字存儲到地址 Rn+offset 處
STR Rd, [Rn, #offset]                          把 Rd 中的低字存儲到地址 Rn+offset 處
LDRD Rd1, Rd2, [Rn, #offset]             把 Rd1(低 32 位)和 Rd2(高 32 位)表達的雙字存儲到地址 Rn+offset 處

 
 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章