1. 程式人生 > >stm32標頭檔案學習之Core_cm3.c(h)

stm32標頭檔案學習之Core_cm3.c(h)

CMSIS是Cortex微控制器軟體介面標準(CortexMicroController Software Interface Standard)的縮寫,這個是ARM定製的一個用於Cortex-M系列的一個標準,主要是為了提供通用api介面來訪問核心和一些片上外設,提高程式碼的可移植性。

CMSIS有三個層:核內外設訪問層CorePeripheral Access Layer(CPAL),中介軟體訪問層Middleware Access Layer(MWAL),裝置訪問層(DevicePeripheral Access Layer)。

CPAL用於訪問核心的暫存器和元件,如NVIC,除錯系統等。該層是由ARM實現的。

MWAL用於對中介軟體的訪問,現在該層還未實現。(也不知道所謂的中介軟體是什麼東西)。

DPAL用於定義一些硬體暫存器的地址和一些外設訪問函式,由晶片製造商實現。

CPAL層的實現就是Core_cm3.c檔案,DPAL層的實現就是system_stm32f10x.c檔案(似乎還應該加上外設的函式庫)。

接下來就來了解一下Core_cm3.c裡面有什麼東東:

首先是彙編關鍵字__ASM和__INLINE的巨集定義,支援不同的編譯器。由於使用的是Keil,所以就只看第一種,__CC_ARM。

這裡面的函式呼叫都只符合ARM過程呼叫標準的,如R0到R3用作引數和返回值傳遞,這也是這裡面唯一用到的。

此外,在Keil中使用了__asm關鍵字後,編譯器不會為函式增加返回指令,所以需要自己編寫返回命令,也就是每個函式後面的  bx lr。

1.     __ASM uint32_t__get_PSP(void):獲取程序堆疊指標PSP。

2.     __ASM void__set_PSP(uint32_t topOfProcStack):設定PSP。

3.     __ASM uint32_t__get_MSP(void):獲取主堆疊指標MSP。

4.     __ASM void__set_MSP(uint32_t mainStackPointer):設定MSP。

5.     __ASM uint32_t__REV16(uint16_t value):反轉半字中位元組順序,如0xABCD反轉後得到0xCDAB。

6.     __ASM int32_t__REVSH(int16_t value):反轉位元組順序,並做符號拓展。就是在__REV16函式得到的結果上再進行一次符號拓展。這兩個函式主要是方便進行大小端的切換。

7.     __ASM void__CLREX(void):清除由LDREX指令造成的互斥鎖。LDREX和STREX是Cortex用來實現互斥訪問,保護臨界資源的指令,LDREX執行後,只有離它最近的一條儲存指令(STR,STREX)才能執行,其他的儲存指令都會被駁回,而CLREX就是用於清除互斥訪問狀態的標記。

8.     __ASMuint32_t  __get_BASEPRI(void):獲取BASEPRI暫存器的值,優先順序號高於該暫存器的中斷都會被遮蔽(優先順序號越大,優先順序越低),為零時不遮蔽任何中斷。

9.     __ASM void__set_BASEPRI(uint32_t basePri):設定BASEPRI的值。

10.  __ASM uint32_t__get_PRIMASK(void):PRIMASK是一個只有一位的暫存器,置位時遮蔽絕大部分的異常中斷,只剩下NMI和HardFault可以響應。

11.  __ASM void __set_PRIMASK(uint32_tpriMask):設定PRIMASK的值。

12.  __ASM uint32_t __get_FAULTMASK(void):FAULTMASK也是一個只有一位的暫存器,為1時只有NMI才能響應,其他異常與中斷全部被遮蔽。

13.  __ASM void __set_FAULTMASK(uint32_tfaultMask):設定FAULTMASK的值。

14.  __ASM uint32_t__get_CONTROL(void):獲取CONTROL的值。暫存器CONTROL只有兩位。CONTROL[0]選擇特權級別,0為特權級,1為敵使用者級。CONTROL[1]用於選擇堆疊指標,0為MSP,1為PSP。

15.  __ASM void __set_CONTROL(uint32_tcontrol):設定CONTROL暫存器的值。

BASEPRI,PRIMASK,FAULTMASK,CONTROL都只能在特權模式下被修改。

還有兩個檔案,一個是Core_cmFunc.h 和 Core_cmInstr.h  這兩個檔案是幹嘛的,第一個檔案是不同編譯器下的一些系統級的彙編函式,第二個檔案是不同編譯器下的指令,我猜Keil公司這樣做是為了相容不同的編譯器做設計的。把這兩個標頭檔案在Core_cm3.h標頭檔案裡註釋掉也是可以的。說明這兩個標頭檔案對於keil開發環境是不需要的。

最後剩下Core_cm3.h檔案了,這個檔案是核心檔案,就是定義了一些Cortex-M3的暫存器和一些函式,包括NVIC,MPU,SCB,SysTick,Debug暫存器。

最近在看LPC17XX系列的東東,發現這個文章說得有一些不對(上面是複製別人的),我用的是MDK4.14版本的開發環境。

說說我對這幾個檔案的理解:core_cm3.c和core_cm3.h,Core_cmFunc.h 和 Core_cmInstr.h

第一個:core_cm3.c是定義了一些相容各個開發環境的一些內嵌彙編函式,都是關於M3核心暫存器操作的函式。其實這個函式在工程中根本沒有使用到,用的是Core_cmFunc.h的彙編函式,因為Core_cmFunc.h裡的函式和core_cm3.c差不多是一樣的。不信自己建一個工程,除錯一下就知道不是進去core_cm3.c,而是去Core_cmFunc.h執行的。所以core_cm3.h包含了Core_cmFunc.h 和 Core_cmInstr.h標頭檔案。

第二個:core_cm3.h定義了相容各種編譯器的關於debug和NVIC的一些函式,這些函式在中斷設定中是很好用的。其中還有系統節拍器函式。我覺得core_cm3.h和core_cm3.c是一點關係都沒有的,雖然他們同名。擔不是標頭檔案和原始檔的關係。當然這個檔案一開頭還有核心暫存器的定義。下面才能用操作核心暫存器。

第三個:Core_cmInstr.h定義了很多核心指令的函式,這個應該不常用,先不管。

第四個:Core_cmFunc.h和core_cm3.c是非常相似的,大多數函式連函式名都一樣的,不知道為什麼要這樣做,實際用函式是在Core_cmFunc.h裡的函式,甚至把core_cm3.c從工程裡刪除,都沒有問題的。但是遮蔽core_cm3.h裡的Core_cmFunc.h 和 Core_cmInstr.h,就不行了。說明這個core_cm3.c是沒什麼用的,起碼在Keil開發環境下是沒用的。

暫時研究到這裡,後面開始實踐咯,就是使用幾個檔案中的各種函式試試。