精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

常被誤解的開、關總中斷話題

茶話MCU ? 來源:茶話MCU ? 2023-05-18 09:18 ? 次閱讀

我們在使用ARM Cortex-M內核芯片進行產品開發時,有時可能需要暫時開辟一個相對清靜、不被打擾的程序執行環境,以確保某些操作可靠順利完成。這時我們往往會使用所謂開、關總中斷的指令代碼來完成。我們可以對特殊功能寄存器PRIMASK寫1來關閉/屏蔽優先級不高于0【數字大于0】的所有可配置中斷的中斷響應。對其寫0,放棄關閉/屏蔽功能,即所謂的開總中斷。

關于使用PRIMASK寄存器關閉/屏蔽所有可配置中斷的做法還有其它等效操作,比如使用CPSID指令和CPSIE指令或調用相關CMSIS函數。【如下圖所示,左邊是匯編指令,右邊是對應CMSIS函數】

e20ff88a-f519-11ed-90ce-dac502259ad0.png

不過,在實際應用中很多人對這這個關、開總中斷操作有些誤解,尤其對關總中斷誤解更甚。以為關總中斷就在NVIC那里關閉了所有中斷響應允許,或者說連外設端的中斷請求的使能也關閉了,中斷請求事件標志也無效了,其實并不是這樣的。若出于誤解而使用開、關總中斷指令或函數往往就得不到自己想要的結果、或者結果讓人困惑不解。

下面基于Cortex -M4內核的STM32L4芯片做些驗證。這里我們拿STM32L476開發板驗證下相關內容【具體使用哪款STM32芯片不重要】。

e2163588-f519-11ed-90ce-dac502259ad0.png

我這里開啟片內TIM1/TIM2/TIM3/TIM4四個定時器的更新事件中斷,其中TIM1/TIM2/TIM3的時間參數完全一樣,而TIM4跟前三者相比,除了溢出時間參數【就是ARR】稍微小一點外,其它配置一樣,四者同時啟動,并確保讓TIM4一定先進入中斷服務程序[即ISR]。

它們的中斷優先級設置各不相同,TIM4的最低。現在假設TIM4中斷服務程序里要執行一段特別重要的事情,通過代碼設計保證CPU剛進入TIM4中斷服務程序時另外3個定時器一定還沒有觸發更新事件。為了便于測試,我也確保啟動程序后每個TIMER都只產生一次更新事件。他們的優先級配置如下圖所示【此處優先級高4位全部用作搶占優先級,子優先級都一樣,不做配置】:

e21d1894-f519-11ed-90ce-dac502259ad0.png

上面各中斷優先級的數字是基于優先級寄存器的高4位而言的,顯然TIM4的優先級最低【數字越大優先級越低】。我在CPU進入TIM4 ISR時立即調用所謂的關閉總中斷函數,然后一段時間后才調用所謂的打開總中斷的函數,確保TIM4 ISR執行完畢之前另外3個TIMER的更新中斷請求都產生了。

e22870f4-f519-11ed-90ce-dac502259ad0.png

我在每個中斷ISR里執行一條輸提示,基于上面的測試代碼我們看看輸出結果【我借助于RTC把執行各中斷的時間點也輸出了】:

e233bee6-f519-11ed-90ce-dac502259ad0.png

盡管在TIM4中斷里一開始就調用了disable_irq()函數,可是,它并沒有關閉TIM1/TIM2/TIM3的中斷請求和后續響應。從上圖不難看出,TIM4/TIM1/TIM2/TIM3依次得到響應執行。怎么感覺那個關閉總中斷的函數啥也沒關掉呢?這也正是被很多人誤會的地方。

其實,這里調用disable_irq()函數的目的就是關閉/屏蔽所有優先級不高于0的可配置中斷的響應,以保障當前TIM4 ISR的順暢執行。這就相當于將當前TIM4 的中斷優先級從4提升到0了。因此,讓原本優先級高于TIM4的TIM1/TIM2/TIM3中斷優先級反而低于當前TIM4ISR的執行優先級,即使在TIM4 ISR過程中發生了TIM1/TIM2/TIM3中斷請求也沒法得到響應。

而且,調用disable_irq()函數并不對被關閉/屏蔽中斷的原有參數和配置做任何改變。什么意思呢?那些暫時被屏蔽中斷的中斷響應允許位、中斷請求使能位以及觸發事件標志等都不會因暫時被屏蔽而發生改變。同樣,enable_irq()函數也不改變之前被屏蔽中斷的原有參數和配置,它只是放棄剛才的屏蔽功能【或說優先級提升功能】。所以,當執行enable_irq()函數后,那些一度被屏蔽/關閉的中斷請求都會按照之前各自優先級而被CPU響應執行。

我們可以在TIM4 ISR的適當位置后打上斷點【斷點處4個TIMER的更新事件一定都產生了】看看各個中斷的響應情況:【詳見下圖】

e23ccf9a-f519-11ed-90ce-dac502259ad0.png

圖中E、P、A是下方Eable/Pending/Active單詞的首字母。Enable表示中斷請求是否在NVIC端得到響應允許;Pending表示中斷請求等待CPU的響應執行;Active表示中斷服務程序正在被執行。

顯然,只有TIM4服務程序在被執行中,其它3個都是掛起狀態,等待被響應。也就是說disable_irq()函數并不直接影響別的中斷請求的產生和響應掛起狀態,它通過提升當前執行程序的優先級變相地實現了屏蔽/關閉其它優先級不高于0的中斷請求的響應,即這個關閉是從執行效果上來說的,相當于變相提升了中斷響應門檻;enable_irq()函數相當于將提升的門檻拿走恢復原貌。

如果其它參數都不變,我注釋掉TIM4 ISR里的關閉總中斷的代碼,看看運行結果會怎么樣呢?【見下圖中TIM4 ISR 代碼和輸出結果】

e24877dc-f519-11ed-90ce-dac502259ad0.png

雖然代碼保障了TIM4最先進入中斷服務程序,但由于其它幾個更高優先級的更新事件隨即產生而發生搶占,反而TIM4最后完成中斷執行。我們可以觀察上面輸出順序及記錄的時間點,請特別留意TIM3 ISR與 TIM4 ISR的輸出時間點是相同的,因分辨率問題時間太接近沒區分開來。不過這反而可以更清晰地看出TIM4被搶占了,TIM3一執行完馬上回到TIM4的輸出【這個結果跟TIM4的被搶占時間點密切相關】。

如果說,我在上面配置和代碼基礎上,進入TIM4 ISR后依然先關閉總中斷,在打開總中斷前對TIM1/TIM2/TIM3的幾個更新事件標志做清零,結果會怎么樣呢?【相信很多人想看看這個結果,不妨先心里猜測下。】

e2577278-f519-11ed-90ce-dac502259ad0.png

基于上面調整后的代碼,編譯運行。不論我怎么反復點擊運行,上圖右邊的輸出結果紋絲不動?這個結果是正確、合理的嗎?符合你心里預期否?

我這里清除的只是外設端的中斷請求事件標志,怎么早已生效的中斷請求就消失了呢?結合前面的分析,在TIM4 ISR里運行延時程序就是為了確保另外的TIM1/TIM2/TIM3的中斷請求得以生效,請求生效后并會在NVIC的中斷響應掛起寄存器的相應位置1,等待執行。

這是怎么回事呢?原理上說不通啊?

其實,我們看到的只是表象。真相是TIM1/TIM2/TIM3的ISR都得到執行了,為什么沒看到TIM1/TIM2/TIM3 ISR運行的結果輸出呢?這跟我們ISR代碼處理有關。

首先可以肯定,這里做中斷請求事件標志清零時,它們3個中斷請求早就生效并處于響應掛起狀態。對事件標志清零也不會影響到NVIC的中斷掛起位的。當TIM4 ISR執行完畢后,TIM1/TIM2/TIM3照樣基于優先級高低相繼運行各自ISR。但有個問題,就是各自的ISR代碼里都會檢測更新事件標志,由于該標志在TIM4 ISR早就被做了清除而成為無效標志,所以在它們3個各自ISR里因檢測到事件標志無效就都沒有繼續往下運行而提前退場,說直接點就是沒有運行到結果輸出代碼就返回了。

既然這樣,我不妨將輸出結果的代碼放在各自ISR的入口處,免掉檢查標志位這個環節,然后我們繼續看看結果。【結果輸出在各自更新中斷回調函數里完成。修改后的中斷代碼如下圖所示:】

e267510c-f519-11ed-90ce-dac502259ad0.png

基于上面的代碼調整,再看看結果輸出:

e26e2e0a-f519-11ed-90ce-dac502259ad0.png

這個輸出結果就跟我們分析和預期的一致。通過這個實驗表明,對于在NVIC端生效處于響應掛起的中斷請求,只是清除相應的事件標志是不會影響它的后續執行的。如果我在上面TIM4 ISR里面執行開啟總中斷操作前希望處于掛起狀態的TIM1/TIM2/TIM3中斷請求不要再被執行了,那要如何操作呢?

首先,清除請求事件標志是應該的,而且還要清除它們各自的NVIC端的中斷響應掛起位。我們可以通過調用__NVIC_ClearPendingIRQ(IRQn)函數對特定中斷響應掛起位清零。

e2769a40-f519-11ed-90ce-dac502259ad0.png

對TIM4ISR代碼再稍加調整【見上圖】,運行后就只能看到TIM4 ISR的輸出結果了。其它3個中斷請求半路被TIM4 ISR給清除了,即使再開總中斷也于事無補。

關于被誤解的開、關總中斷的話題,拉拉扯扯不知不覺也聊了這么多。所謂關總中斷,實質上將當前執行程序的優先級提升到0,變相提高了期望打斷當前執行程序的中斷事件的響應門檻,開總中斷就是取消對當前執行程序的優先級提升,恢復原貌。這里順便貼出幾個常用的有關中斷響應的CMSIS函數供參考備忘。

e27f7372-f519-11ed-90ce-dac502259ad0.png

今天的分享就到這里,愿本文的分享能帶給您一些收獲。祝君好運。下次再聊。

哦,最后補充下,文中的串口終端輸出結果,我是通過CPU直接向UART外設的數據寄存器輪詢式寫數據實現的。本公眾號文字力求不拖泥帶水,特意提醒這句給有心人。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • ARM
    ARM
    +關注

    關注

    134

    文章

    9045

    瀏覽量

    366808
  • 寄存器
    +關注

    關注

    31

    文章

    5317

    瀏覽量

    120002
  • 內核
    +關注

    關注

    3

    文章

    1362

    瀏覽量

    40228
  • 中斷
    +關注

    關注

    5

    文章

    895

    瀏覽量

    41391
  • Cortex-M
    +關注

    關注

    2

    文章

    227

    瀏覽量

    29726

原文標題:常被誤解的開、關總中斷話題

文章出處:【微信號:stmcu832,微信公眾號:茶話MCU】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    STM32F0內核的中斷是默認的嗎?

    STM32F0、STM32F1, 用 CubeMx生成初始化代碼,只有外設的中斷使能代碼,沒有找到中斷的使能代碼,請問內核的中斷默認是
    發表于 04-03 06:14

    常被誤解的運放壓擺動作有哪些?

    運放的壓擺動作經常被誤解。壓擺率是一個內容較多的話題,我們需要將它進行分類討論。
    發表于 02-23 07:10

    STM32關閉或開啟所有中斷代碼 精選資料分享

    STM32 關閉所有中斷如題,關閉或開啟所有中斷;代碼如下:__set_PRIMASK(1);//中斷__set_PRIMASK(0);
    發表于 08-13 06:36

    STM32全局中斷全局中斷有多種方法

    STM32全局中斷全局中斷有多種方法,分別操作PRIMASK、FAULTMASK和BASEPRI寄存器。注:完整資料請查看Cortex-M3權威指南中的NVIC與
    發表于 08-13 09:22

    有沒有中斷的函數或者指令呢

    問題: 對于基于ARM Cortex M0內核的STM32芯片各類應用開發時,有的時候需要進行中斷處理。那就究竟有沒有
    發表于 08-13 06:58

    STM32開啟和關閉中斷的方法 精選資料推薦

    __set_PRIMASK(1); //中斷__set_PRIMASK(0); //中斷
    發表于 08-16 06:23

    STM32中斷優先級和開關中斷教程

    STM32中斷優先級和開關中斷 教程
    發表于 11-23 18:03 ?0次下載

    運放的壓擺動作誤解

    作者:Bruce Trump 資深模擬工程師 運放的壓擺動作經常被誤解。壓擺率是一個內容較多的話題,我們需要將它進行分類討論。 運放輸入級電路的兩個輸入端之間的電壓通常非常小------理想
    的頭像 發表于 02-10 16:53 ?908次閱讀

    常被誤解的運放壓擺動作

    作者:Bruce Trump 資深模擬工程師 運放的壓擺動作經常被誤解。壓擺率是一個內容較多的話題,我們需要將它進行分類討論。 運放輸入級電路的兩個輸入端之間的電壓通常非常小------理想情況下
    發表于 01-29 06:00 ?9次下載
    經<b class='flag-5'>常被</b><b class='flag-5'>誤解</b>的運放壓擺動作

    MT-006:ADC噪聲系數 - 一個經常被誤解的參數

    MT-006:ADC噪聲系數 - 一個經常被誤解的參數
    發表于 03-21 04:14 ?15次下載
    MT-006:ADC噪聲系數 - 一個經<b class='flag-5'>常被</b><b class='flag-5'>誤解</b>的參數

    LTC2954:帶μP中斷的按鈕/控制器數據表

    LTC2954:帶μP中斷的按鈕/控制器數據表
    發表于 04-15 20:01 ?13次下載
    LTC2954:帶μP<b class='flag-5'>中斷</b>的按鈕<b class='flag-5'>開</b>/<b class='flag-5'>關</b>控制器數據表

    STM32 關閉所有中斷

    STM32 關閉所有中斷如題,關閉或開啟所有中斷;代碼如下:__set_PRIMASK(1);//中斷__set_PRIMASK(0);
    發表于 12-02 17:21 ?8次下載
    STM32 關閉所有<b class='flag-5'>中斷</b>

    STM32 禁用或開啟中斷

    導致升級失敗。ARM MDK中提供了如下兩個接口來禁用和開啟中斷:__disable_irq(); // 關閉中斷__enable_irq(); // 開啟
    發表于 12-09 09:36 ?13次下載
    STM32 禁用或開啟<b class='flag-5'>總</b><b class='flag-5'>中斷</b>

    PRIMASK寄存器中斷的指令代碼

    我們在使用ARM Cortex-M內核芯片進行產品開發時,有時可能需要暫時開辟一個相對清靜、不被打擾的程序執行環境,以確保某些操作可靠順利完成。這時我們往往會使用所謂中斷的指令
    的頭像 發表于 06-21 16:32 ?6255次閱讀
    PRIMASK寄存器<b class='flag-5'>開</b>、<b class='flag-5'>關</b><b class='flag-5'>總</b><b class='flag-5'>中斷</b>的指令代碼

    cc2530中斷控制位是什么?

    cc2530是一款著名的無線通信芯片,它內置了豐富的功能和資源,其中包括中斷控制位。在本文中,將介紹cc2530中斷控制位的概念、作用、使用方法以及注意事項。 首先,讓我們來了解一
    的頭像 發表于 01-08 09:37 ?979次閱讀