Cortex-M3/M4的基礎
不同於A系列的, M系列只有一組暫存器R0~R15; M4相對於M3多了一個浮點單元FPU, 其他的基本與M3是一樣的。
一、從指令集方面看:
某些ARM處理器支援ARM和Thumb指令集,而Cortex-M3只使用Thumb-2指令集。ARM指令集是32位完整體系結構。Thumb指令可視為ARM指令壓縮形式的子集,為16位指令集。THumb指令只需要支援通用功能,必要時,可藉助完善的ARM指令集。
Thumb-2是一個突破性的指令集,是16位Thumb指令集的一個超集,在Thumb-2,16位指令首次與32位指令並存,這樣子在Thumb狀態下可以做的事情一下子豐富了許多,同樣的工作需要的指令週期數也明顯下降。因為它允許32位指令和16位指令水乳交融,程式碼密度和處理效能兩手抓。
在以前做ARM開發必須處理好ARM狀態和Thumb狀態,且這兩個狀態是井水不犯河水。
當處理器在ARM狀態下時,所有的指令均是32位的(哪怕只是個"NOP"指令),此時效能相當高。
而在Thumb狀態,所有的指令均是16位的,程式碼密度提高了一倍。但thumb狀態下的指令功能只是ARM下的一個子集,結果可能需要更多條的指令去完成相同的工作,導致處理效能下降。
取長補短,多數應用程式都混合使用ARM和Thumb程式碼段。---切換之際導致額外開銷(時間上和空間上)。
且ARM程式碼和Thumb程式碼需要以不同的方式編譯,這也增加了軟體開發管理的複雜度。
主程式程式碼在Thumb下執行----->BLX 跳轉到ARM態--->BX LR --->主程式程式碼在Thumb下執行。
Thumb-2指令集的出現,就可以在單一的操作模式下搞定所有處理了,沒有了來回切換。事實上,Cortex-M3 核心乾脆都不支援ARM指令,連中斷也在Thumb態下處理(before ARM總在ARM態下處理所有的中斷和異常)。這就使得CM3在多個方面比傳統的ARM處理器更先進。
Thumb-2指令集
二、從暫存器方面看:
Cortex-M3/M4系列的核心擁有通用處理器R0~R15以及一些特殊功能暫存器。
R0-R12:通用暫存器;R0‐R12 都是 32 位通用暫存器,用於資料操作。
16位Thumb指令只能訪問R0~R7(低組暫存器); 32為Thumb-2指令可以訪問所有暫存器(low Registers 和 hight Registers)。
R13(SP指標) 主堆疊指標MSP 程序堆疊指標PSP 兩個堆疊指標,即支援兩個堆疊。PUSH指令(入棧)和POP指令(出棧)預設使用SP。
MSP:復位後預設使用的堆疊指標,用於作業系統核心以及異常處理例程(包括中斷服務程式)以及所有需要特權訪問的應用程式程式碼
PSP:由使用者的應用程式程式碼使用。
注:在ARM程式設計領域中,凡是打斷程式順序執行的事件,都被稱為異常(exception).
除了外部中斷外,還有執行了"非法操作"、訪問被禁的記憶體區間、因各種錯誤產生的fault以及不可遮蔽中斷 事件s。
R14(連線暫存器)——當呼叫一個子程式時,由R14儲存返回地址
ARM為了減少訪問記憶體的次數(訪問記憶體的操作往往要3個以上指令指南,而帶MMU和cache的九不確定了),把返回地址直接儲存在暫存器中。只有1級子程式呼叫的程式碼無需訪問記憶體(堆疊記憶體),從而提高子程式的呼叫效率。
多於1級的,則需要把前一級的R14值壓倒堆疊裡。——濺出
在ARM上程式設計時,應儘量只是用暫存器儲存中間結果,迫不得已才訪問記憶體。
在使用BL指標(Branch and Link)時,就把PC+1自動填充LR的值。因為PC的LSB總是0(因為程式碼至少是字對齊的), 而LR的LSB(最低有效位)的可讀可寫,這是歷史遺留的產物。在before,用位0來指示ARM/Thumb狀態,這是因為某些ARM處理器支援ARM和Thumb狀態並存,為了方便彙編程式移植,CM3/CM4需要允許LSB可讀可寫。 實際使用時,並不看LSB,字對齊。
R15(PC)——程式計數暫存器 指向當前的程式地址。 如果修改它的值,就能改變程式的執行流(高階技巧)
特殊功能暫存器有預定義的功能,且必須通過專用的指令來訪問。
M3/M4內部使用了指令流水線,因此讀PC時返回的值是當前指令的地址+4
0x1000: MOV R0, PC; 此時R0 = 0x1004
CM3/CM4中的指令至少是半字對齊的,所以PC的LSB總是讀回0.
在分支時,無論是直接寫PC的值還是使用分支指令,都必須保證載入到PC的數值是奇數(即LSB=1),用以表明這是出於Thumb狀態下執行的。
如果PC載入的數值為偶數(即LSB=0),視為企圖轉入ARM模式,CM3將產生一個fault異常。
特殊功能暫存器組
Cortex-M3/M4有一個特殊功能暫存器組,
--->程式狀態暫存器組(PSRs/xPSR) 3個
--->中斷遮蔽暫存器組(PRIMASK, FAULTMASK,以及BASEPRI)
--->控制暫存器(CONTROL)
這7個暫存器只能被專用的MSR和MRS指令訪問,而且它們也沒有儲存器地址。
PSR包括應用程式PSR<APSR> 、中斷號PSR<IPSR>、執行PSR<EPSR> 三個程式狀態暫存器,
PRIMASK、FAULTMASK、MASEPRI這三個暫存器用於控制異常的使能和除能。
PRIMASK 這個暫存器只有一位,當該位為1時,就遮蔽所有可遮蔽的異常,除NMI和硬體fault可以響應。預設是0;
FAULTMASK這個暫存器也只有一位,置1時,只有NMI才能響應,所有其他異常均遮蔽。預設為0
BASEPRI 這個暫存器的有效位由表達優先順序的位數決定,最多9位。它定義了被遮蔽優先順序的閾值,當優先順序號大於等於此值的中斷均被關閉。預設為0,則不關閉任何中斷。
對於關鍵任務,暫時關閉中斷很重要,要處理PRIMASK和BASEPRI。
FAULTMASK則被OS用於暫時關閉fault處理機能。
開關中斷的方法M3/M4
CPSID I; PRIMASK=1, ;關中斷
CPSIE I; PRIMASK=0, ; 開中斷
CPSID F; FAULTMASK=1, ; 關異常
CPSIE F; FAULTMASK=0, ; 開異常
CONTROL(控制暫存器)
用於定義特權級別和堆疊指標的使用(MSP/PSP)
位[31~3] | 位[2] | 位[1] | 位[0] |
保留 | M4特有,0未使用浮點單元 1使用浮點單元 以此位來決定當處理異常時是否儲存浮點環境 |
堆疊指標選擇 0選擇住堆疊指標MSP 1選擇程序堆疊指標 線上程模式下,可用PSP亦可用MSP 在處理者handler模式下,只允許用MSP |
執行緒模式下訪問級別選擇 0特權級的執行緒模式 1使用者級的執行緒模式 |
可軟中斷進入異常處理,在進入異常服務程式後,LR(R14)暫存器的值被自動更新為特殊的EXC_RETURN。從EXC_RETURN, 我們可以獲知硬體對哪些暫存器進行自動壓棧和出棧處理。
位[31:28] | 位[27:5] | 位4 | 為3 | 位2 | 位1 | 位0 |
為0xF,作為EXC_RETURN的標識 | 保留,全為1 | 堆疊型別(硬體自動堆疊大小,單位字),M4特有 0:壓入26個字 1:硬體自動向堆疊中壓入8個字 在未使用FPU時,此位總為1 |
0=返回進入Handler模式 1=返回後進入執行緒模式 |
0=從主堆疊中做出棧操作,返回後使用MSP 1=從程序堆疊中做出棧操作,返回後使用PSP |
保留,必為0 | 0=返回ARM狀 態 1=返回Thumb狀態,在M3/M4中必須為1 |
舉個栗子:CONTROL為0xFFFFFFE1 ----使用FPU,返回時進入Handler模式
CONTROL為0xFFFFFFE9----使用FPU,返回時進入執行緒模式,並用MSP
CONTROL為0xFFFFFFFD----未使用FPU,返回時進入執行緒模式,並用PSP
三、從操作模式和特權級別 -------操作模式 和訪問特權級別。
Cortex-M3/CM4處理器支援兩種處理器的操作模式,還支援兩級特權操作。
兩種操作模式分別為處理者模式(handler mode)和執行緒模式(thread mode)。引入兩個模式本意是為了區別普通應用程式的程式碼和異常服務例程的程式碼----即中斷服務例程的程式碼。
執行緒模式----普通應用程式程式碼
處理者模式(handle mode)---異常服務例程的程式碼
Cotex-M3/M4的特權的分級----特權級和使用者級。這提供了一種儲存器訪問的保護機制(使得普通的使用者程式程式碼不能意外地,甚至惡意地執行涉及到要害的操作)。處理器支援兩種特權級
特權級下,程式可以訪問所有範圍的儲存器(如果有MPU,還要在MPU規定的禁地之外),並且可以執行所有指令。
在CM3/CM4執行主應用程式時(執行緒模式),既可以使用特權級,也可以使用使用者級;
但是異常服務例程必須在特權級下執行。
復位後,處理器預設進入執行緒模式,特權級訪問。 但一旦切換至使用者級,在想回到特權模式,就需要走"法律程式"——它必須先“申訴”----執行一條系統呼叫指令(SVC)---從而觸發SVC異常,然後由異常服務例程(這通常是作業系統的一部分)接管,如果批准了進入,則異常服務例程會修改CONTROL暫存器,如此才能在使用者級的執行緒模式下重新進入特權級。
從使用者級到特權級的唯一途徑就是異常。
復位進入-->特權級訪問,執行緒操作模式--->修改了CONTROL暫存器---->使用者級訪問,執行緒操作模式----觸發異常-->特權級訪問handler操作模式--->異常返回--->特權級訪問,執行緒操作模式/使用者級訪問,執行緒操作模式。
特權級和使用者級訪問級別,就能夠在硬體水平上限制某些不受信任的或者還沒有除錯好的程式,不讓它們隨便地配置涉及要害的暫存器。
配了MPU(儲存器保護單元)後,它還可以作為特權機制的補充——保護關鍵的儲存區域(作業系統的區域)不被破壞。
四、Cortex-M3/M4堆疊 R13(SP)
Cortex-M3/M4 使用的是"向下生長的滿棧"模型
滿棧——即堆疊指標SP指向最後一個被壓入堆疊的32為數值。
向下生長——在下一次壓棧時,SP先自減4,在存入新的數值。
PUSH{R0}——壓棧操作
POP{R0}——出棧操作:先從SP指標處讀出上一次被壓入的值,再把SP指標自增4。
5、中斷和異常
6、儲存器對映
Cortex-M3/M4 是32位處理器,可訪問4GB的儲存空間,它可被劃分為若干個區域。
Cortex-M3預先定義好了"粗線條的"儲存器對映。
通過把片上外設的暫存器對映到外設區(0x40000000~0x5FFFFFFF) 512MB,就可以簡單地以訪問記憶體的方式來訪問這些外設的暫存器,從而控制外設的工作。因此,片上外設可使用C語言來操作。
預定義的對映關係,也可使得訪問速度做到高度的優化,整合性更好。
從低到高 程式碼區--->片上SRAM--->片上外設---->片外RAM--->片外外設---->系統級儲存器
片外RAM、片外外設為1G大小的對映區,其他為512MB大小的對映區
處於最高地址對映區為系統級儲存區,是CM3用於藏"私房錢"的------包括中斷控制器、MPU以及各種除錯元件。
所有這些裝置均適用固定的地址,通過把基礎設施的地址定死,就至少在核心水平上,為應用程式的移植掃清障礙。
儲存器保護單元(Memory Protected Uint,MPU)
Cortex-M3有一個可選的儲存器保護單元。對MPU進行配置時,就可以對特權級訪問和使用者級訪問施加不同的訪問限制。
當檢測到violated(犯規)時,MPU就會長生一個fault(異常),可由fault異常的服務例程來分析該錯誤,並且在可能時改正它。
MPU玩法很多:
最常見:作業系統使用MPU,可使得特權級程式碼的資料(包括作業系統本身的資料不被其他程式弄壞)。
MPU在保護記憶體時是按區(region)管理的,即將某些記憶體region設定成只讀....。
7、匯流排介面
Cortex-M3內部有若干個匯流排介面,以使CM3能同時取址和訪內(訪問記憶體),它們是:
指令儲存區匯流排(兩條), 分別為I-Code匯流排和D-Code匯流排。 I-Code匯流排用於取指, D-Code用於查表等操作,它們按最佳執行速度進行優化。
系統匯流排,用於訪問記憶體和外設,可訪問的區域包括SRAM,片內外設,片外RAM,片外擴張裝置以及系統級儲存區的部分空間。
私有外設匯流排——負責一部分私有外設的訪問,主要就是訪問除錯元件,也是在系統級儲存區。
以晶片stm32f103的系統架構來看
STM32f103主系統由4個驅動單元和四個被動單元
核心: DCode-bus、 ICode-bus System-bus; 通用DMA匯流排
內部SRAM 內部Flash AHB到APB的橋 FSMC
1、ICode匯流排:該匯流排將M3核心指令匯流排和快閃記憶體指令介面相連,指令的預取在這總線上完成。1---flash介面-->7
2、DCode匯流排:該匯流排將M3核心的DCode匯流排和快閃記憶體儲存器的資料介面相連線,常量載入和除錯訪問在該總線上面完成。
3、系統匯流排:該匯流排連線M3核心的系統匯流排到匯流排矩陣,匯流排矩陣協調核心和DMA間訪問。2---->匯流排矩陣--->Flash介面
4、DMA匯流排:該匯流排將DMA的AHB主控介面與匯流排矩陣相連,匯流排矩陣協調CPU的DCode和DMA到SRAM、快閃記憶體和外設的訪問。2--->匯流排矩陣--->6/8/9 4--->匯流排矩陣---->6/8/9
5、匯流排矩陣:匯流排矩陣解調核心系統匯流排和DMA主控匯流排之間的訪問仲裁。仲裁利用輪換演算法
6、AHB/APB橋