STM32 M3 M0關於開關總中斷的問題

2021-09-25 09:41:49 字數 2489 閱讀 3210

nvic 共支援 1 至 240 個外部中斷輸入(通常外部中斷寫作 irqs)。 具體的數值由晶元廠商在設計晶元時決定。此外, nvic 還支援乙個「永垂不朽」的不可遮蔽中斷(nmi)輸入。nmi 的實際功能亦由晶元製造商決定。在某些情況下, nmi 無法由外部中斷源控制。

在 stm32/cortex-m3 中是通過改變 cpu 的當前優先順序來允許或禁止中斷。​  

異常掩蔽暫存器primask位只允許 nmi 和 hard  fault 異常,其他中斷/異常都被遮蔽(當前 cpu 優先順序=0,為可程式設計優先順序中的最高優先順序) 。 

該暫存器可以通過 mrs 和 msr 以下例方式訪問:

​1. 關中斷mov r0, #1

msr primask, r0

​2. 開中斷mov r0, #0

msr primask, r0 ​

此外,還可以通過cps指令快速完成上述功能:​

cpsid i;//primask=1 ; 關中斷

cpsie  i;//primask=0 ; 開中斷

cpsid f;//faultmask=1, ; 關異常

cpsie  f;//faultmask=0 ; 開異常

異常掩蔽暫存器faultmask位:只允許 nmi,其他所有中斷/異常都被遮蔽(當前 cpu 優先順序=-1)。注意的是,faultmask會在異常退出時自動清零。

掩蔽暫存器雖然能一手遮天,卻都動不了nmi,因為nmi是用在最危急的情況下的。因此系統為它開出單行道,無需**只是不要遲到。

​​在 stm32 韌體庫中(stm32f10x_nvic.c 和 stm32f10x_nvic.h) 定義了四個函式操作 primask 位和faultmask 位,改變 cpu 的當前優先順序,從而達到控制所有中斷的目的。   

​下面兩個函式等效於關閉總中斷:  

​void nvic_setprimask(void);   void nvic_setfaultmask(void);   

​下面兩個函式等效於開放總中斷:  

​void nvic_resetprimask(void);   void nvic_resetfaultmask(void);  

上面兩組函式要成對使用,不能交叉使用。 

例如: 第一種方法(常用): nvic_setprimask();   //關閉總中斷  

​nvic_resetprimask();//開放總中斷   

​第二種方法:  nvic_setfaultmask();      //關閉總中斷  

​      nvic_resetfaultmask();    //開放總中斷

在 3.0 的庫中上述庫函式已經沒有​,可以用下列方法實現:

​#define cli()      __set_primask(1)  

​#define sei()      __set_primask(0) 

或者在編譯器裡使用:

__disable_irq();   // 關閉總中斷

​__enable_irq();    // 開啟總中斷​

補充1:​異常掩蔽暫存器basepri

在更精巧的設計中,需要對中斷掩蔽進行更細膩的控制——只掩蔽優先順序低於某一閾值的中斷(它們的優先順序在數字上大於等於某個數)。那麼這個數儲存在**?就儲存在basepri中。

不過,如果往basepri中寫0,則另當別論——basepri將停止掩蔽任何中斷。

如果你需要掩蔽所有優先順序不高於0x60的中斷,則可以如下程式設計:

​mov r0, #0x60

msr basepri, r0

​如果需要取消 basepri 對中斷的掩蔽,則示例**如下:

​mov r0, #0

msr basepri, r0

補充2:關閉全域性中斷時需要注意的問題(未驗證是否確有此問題)

stm32在使用時有時需要禁用全域性中斷​。但測試發現乙個問題,在關閉總中斷後,如果有中斷觸發,雖然此時不會引發中斷,但在呼叫__enable_irq()開啟總中斷後,mcu會立即處理之前觸發的中斷。這說明__disable_irq()只是禁止cpu去響應中斷,沒有真正的去遮蔽中斷的觸發,中斷發生後,相應的暫存器會將中斷標誌置位,在__enable_irq()開啟中斷後,由於相應的中斷標誌沒有清空,因而還會觸發中斷。

所以要想禁止所有中斷,必須對逐個模組的中斷進行disable操作,由於每個模組中斷源有很多,對逐個中斷disable的話比較複雜,較為簡單的方法是通過***_clearitpendingbit()清除中斷標誌或者直接通過***_deinit()來清除暫存器的狀態。這樣在__enable_irq()開啟總中斷後,mcu就不會響應之前觸發的中斷了。

M0核心與M3核心比較

m3比m0效能更高,原因是 1 m0比m3少好多指令,m0只有56條指令,其中50條是16位的,因此好多m3一條指令就能完成的功能m0需要多條指令 2 m3的資料匯流排和指令匯流排是分開的,可以同時取指和取運算元,而m0取指和取運算元是同一條匯流排 m0相對於m3的優點是更小,所以 便宜。之所以用m...

STM32 F103 外部晶振8M改為12M

stm32 實現外部晶振變換有2種方法 第一種修改系統庫函式 第一步,開啟stm32f10x.h,將 define hse value uint32 t 8000000 修改為 define hse value uint32 t 12000000 重要必須做 第二步,開啟system stm32f1...

關於STM32的I2S通訊飛利浦協議和MSB協議

最近公司乙個專案要用到codec晶元來做語音的採集和輸出,驅動是用的stm32f405的i2s介面。之前沒有深入的了解過i2s的知識,只是大概的知道它是一種用於傳輸音訊資料的匯流排。本來以為沒什麼難的,實際用下來其實也沒感覺有有什麼特別的。但是還是在使用的過程中把自己坑了一把。codec晶元型號是m...