進入臨界就是關閉 單片機總中斷,退出臨界就是恢複單片機中斷,記住最好是恢複,不是打開,因為進入臨界之前單片機總中斷未必是開著的。 那為什麼要進入臨界?有什麼作用? 我們假設一種場景:
我們來看這樣一段代碼。 假設我們程序執行到第12行,也就是a = 0的位置,*p的值肯定是等於2的對吧? 突然有個定時器中斷來了,然後在定時器中斷處理函數裏麵,我們執行了p++。 執行完以後回到主程序繼續執行,也就是會去執行13行代碼,這個時候*p的值你猜猜是多少? 沒錯,肯定不是2,而是3。 明明條件判斷是2,最後值卻變成了3,這種bug估計能調到你哭。 這個時候進入臨界就穩得一逼了,可以改成如下代碼。
STM32不像51單片機這樣直接EA=0就能關閉總中斷,而是通過__get_PRIMASK和__set_PRIMASK來做,當然也可以用__disable_irq和__enable_irq。 具體的可以在工程裏搜索,看注釋。 每個單片機關閉總中斷的方式都不一樣,所以進入臨界和退出臨界代碼也有所區別。 你隻需要記住本質就是關總中斷,執行完程序後,恢複總中斷就行了。 不用過於擔心單片機總中斷怎麼開關的問題,網上隨便都能搜到。 那繼續聊下我們上麵那個程序,很多人可能會說,我寫程序的時候規避這種問題,不在定時器裏對p指針進行操作不就行了? 如果你是做一些比較大的項目,幾乎不可能避免,比如說我們的隊列算法。 我們會在串口中斷裏接收到數據以後,把數據丟進隊列,然後在主函數進行解析。
用了隊列以後,數據傳輸穩定性可以大大提升,哪怕是數據傳輸很快,數據量很大也不會出現丟包的情況。 我們不妨來看下隊列算法的入列函數。
這種,如果不用指針,幾乎不可能實現,哪怕實現了靈活性和移植性也不高。 試想一下,如果這種在主函數和中斷裏都會頻繁去操作指針,不做臨界的話程序很容易因為指針指向異常導致死機或者數據錯亂導致的程序邏輯問題。 當然,進入臨界除了保護全局變量、數組、結構體等數據不錯亂以外,還能是硬件的數據,比如IO、SCI、SPI、flash。 |