0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

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

3天內(nèi)不再提示

什么是臨界段 RTOS臨界段的作用是什么

GReq_mcu168 ? 作者:工程師李察 ? 2018-10-06 14:38 ? 次閱讀

什么是臨界段

代碼的臨界段也稱為臨界區(qū),指處理時不可分割的代碼區(qū)域,一旦這部分代碼開始執(zhí)行,則不允許任何中斷打斷。為確保臨界段代碼的執(zhí)行不被中斷,在進入臨界段之前須關(guān)中斷,而臨界段代碼執(zhí)行完畢后,要立即打開中斷。

臨界段的作用

其實在RTOS中,使用最多的臨界段是OS本身的調(diào)用,但是我們用戶也是需要對臨界資源進行保護的(臨界資源是一次僅允許一個線程使用的共享資源),特別是一些全局變量,當(dāng)線程正在使用的時候不希望有人來打斷我的操作,就行很多時候我們寫代碼時,需要集中精力,不希望別人打斷我們的思路一樣。這樣子使得系統(tǒng)的運行更加穩(wěn)定健壯。

什么時候會打斷代碼的執(zhí)行?

顧名思義,代碼正在正常運行的時候,基本不會被打斷,能被打斷的都是系統(tǒng)發(fā)生了異常(中斷也是異常),在OS中,除了外部中斷能將正在運行的代碼打斷,還有線程的調(diào)度——PendSV,系統(tǒng)產(chǎn)生PendSV中斷,在PendSV Handler里面實現(xiàn)線程的切換。我們要將這項東西屏蔽掉,保證當(dāng)前只有一個線程在使用臨界資源。

如何關(guān)閉中斷?

其實,在我們常用的MCU中,一般為Cortex-M內(nèi)核的,M內(nèi)核是有一些指令能快速關(guān)閉中斷,一起來看看Cortex-M權(quán)威指南吧(以Cortex-M3為例)。

什么是臨界段 RTOS臨界段的作用是什么

簡單來說,快速屏蔽中斷就是處理這些內(nèi)核寄存器,在Cortex-M中有相應(yīng)的操作指令,一般我們無需關(guān)注,因為OS已經(jīng)給我們寫好了這些底層的東西。不過如果你是想自己寫一個OS的話,可以了解一下,要訪問PRIMASK, FAULTMASK以及BASEPRI,同樣要使用MRS/MSR指令,如:

1MRSR0,BASEPRI;讀取BASEPRI到R0中2MRSR0,FAULTMASK;似上3MRSR0,PRIMASK;似上4MSRBASEPRI,R0;寫入R0到BASEPRI中5MSRFAULTMASK,R0;似上6MSRPRIMASK,R0;似上

只有在特權(quán)級下,才允許訪問這3個寄存器。

其實,為了快速地開關(guān)中斷,CM3還專門設(shè)置了一條CPS指令,有4種用法:

1CPSIDI;PRIMASK=1,;關(guān)中斷2CPSIEI;PRIMASK=0,;開中斷3CPSIDF;FAULTMASK=1,;關(guān)異常4CPSIEF;FAULTMASK=0;開異常

上面的代碼中的PRIMASK和FAULTMAST是Cortex-M內(nèi)核 里面三個中斷屏蔽寄存器中的兩個,還有一個是BASEPRI,這些寄存器都用于屏蔽中斷。具體的作用見表格(表格出自《【野火】RT-Thread內(nèi)核實現(xiàn)與應(yīng)用開發(fā)實戰(zhàn)指南》)

什么是臨界段 RTOS臨界段的作用是什么

不同OS的處理臨界段的區(qū)別

FreeRTOS

FreeRTOS對中斷的開和關(guān)是通過操作BASEPRI寄存器來實現(xiàn)的,即大于等于BASEPRI的值的中斷會被屏蔽,小于BASEPRI的值的中斷則不會被屏蔽。這樣子的好處就是用戶可以設(shè)置BASEPRI的值來選擇性的給一些非常緊急的中斷留一條后路。比如飛控的防撞處理。代碼在portmacro.h 中實現(xiàn):

屏蔽中斷:

1staticportFORCE_INLINEvoidvPortRaiseBASEPRI(void) 2{ 3uint32_tulNewBASEPRI=configMAX_SYSCALL_INTERRUPT_PRIORITY; 4 5__asm 6{ 7msrbasepri,ulNewBASEPRI 8dsb 9isb10}11}

打開中斷:

1staticportFORCE_INLINEvoidvPortSetBASEPRI(uint32_tulBASEPRI)2{3__asm4{5msrbasepri,ulBASEPRI6}7}

RT-Thread:

與FreeRTOS不同的是,RT-Thread對臨界段的保護處理的很干脆,不管三七二十一直接把中斷全部關(guān)了(直接操作PRIMASK內(nèi)核寄存器), 只有NMI FAULT和硬FAULT能被相應(yīng)。 這種方法簡單粗暴,是很不錯的選擇。一般我們臨界段的處理時間是比較短的,關(guān)了再開其實并沒有太大的影響。

現(xiàn)在要看看RT-Thread的關(guān)中斷的代碼實現(xiàn):

1rt_hw_interrupt_disablePROC2EXPORTrt_hw_interrupt_disable3MRSr0,PRIMASK4CPSIDI5BXLR6ENDP

開中斷:

1rt_hw_interrupt_enablePROC2EXPORTrt_hw_interrupt_enable3MSRPRIMASK,r04BXLR5ENDP

這短短的幾句代碼其實還是很有意思的,我就引用火哥的話來解釋一下這些處理操作(我個人是不會匯編的,但是跟著書來解讀這些代碼還是很輕而易舉的)

可能有人懂匯編的話,就會看出來,關(guān)中斷,不就是直接使用CPSID I指令就行了嘛~開中斷,不就是使用CPSIE I指令就行了嘛,為啥跟我等凡人想的不一樣?

RT-Thread的處理好像是多此一舉了,實則不然,“所有東西的存在必然有其存在的意義”這句話應(yīng)該沒人反駁吧~~因為RT-Thread要防止用戶錯誤地退出了中斷臨界段,因為這樣子可能會產(chǎn)生巨大的危害,所以RT-Thread將當(dāng)前的PRIMASK的狀態(tài)保存起來,這樣子就必須要關(guān)多少次中斷就得開多少次中斷。

怎么說呢,用例子來證明吧:

1/*臨界段1開始*/ 2rt_hw_interrupt_disable();/*關(guān)中斷,PRIMASK=1*/ 3{ 4/*臨界段2*/ 5rt_hw_interrupt_disable();/*關(guān)中斷,PRIMASK=1*/ 6{ 7} 8rt_hw_interrupt_enable();/*開中斷,PRIMASK=0*/(注意) 9}10/*臨界段1結(jié)束*/11rt_hw_interrupt_enable();/*開中斷,PRIMASK=0*/

如果直接操作PRIMASK,而不保存PRIMASK的狀態(tài),這樣子當(dāng)臨界段2結(jié)束后調(diào)用一次打開中斷,那么連臨界段1的后半部分就無效了。而RT-Thread的實現(xiàn)就能很好避免這種問題,也用代碼來說明吧:

1/*臨界段1開始*/ 2level1=rt_hw_interrupt_disable();/*關(guān)中斷,level1=0,PRIMASK=1*/ 3{ 4/*臨界段2*/ 5level2=rt_hw_interrupt_disable();/*關(guān)中斷,level2=1,PRIMASK=1*/ 6{ 7} 8rt_hw_interrupt_enable(level2);/*開中斷,level2=1,PRIMASK=1*/ 9}10/*臨界段1結(jié)束*/11rt_hw_interrupt_enable(level1);/*開中斷,level1=0,PRIMASK=0*/

這樣子就完全避免了對吧!

有人又會問了,F(xiàn)reeRTOS的臨界段能允許嵌套嗎,答案是肯定的,F(xiàn)reeRTOS中早已給我們想好調(diào)用的函數(shù)了,并且全部使用宏定義實現(xiàn)了:

1#defineportDISABLE_INTERRUPTS()vPortRaiseBASEPRI()2#defineportENABLE_INTERRUPTS()vPortSetBASEPRI(0)3#defineportENTER_CRITICAL()vPortEnterCritical()4#defineportEXIT_CRITICAL()vPortExitCritical()5#defineportSET_INTERRUPT_MASK_FROM_ISR()ulPortRaiseBASEPRI()6#defineportCLEAR_INTERRUPT_MASK_FROM_ISR(x)vPortSetBASEPRI(x)

其實原理都是差不多的,通過保存和恢復(fù)寄存器basepri的數(shù)值就可以實現(xiàn)嵌套使用。

1UBaseType_tuxSavedInterruptStatus; 2 3uxSavedInterruptStatus=portSET_INTERRUPT_MASK_FROM_ISR(); 4{ 5uxSavedInterruptStatus=portSET_INTERRUPT_MASK_FROM_ISR(); 6{ 7//臨界區(qū)代碼 8} 9portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);10}11portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);

進入中斷源碼的實現(xiàn):

1staticportFORCE_INLINEuint32_tulPortRaiseBASEPRI(void) 2{ 3uint32_tulReturn,ulNewBASEPRI=configMAX_SYSCALL_INTERRUPT_PRIORITY; 4 5__asm 6{ 7mrsulReturn,basepri 8msrbasepri,ulNewBASEPRI 9dsb10isb11}12returnulReturn;13}

退出中斷源碼實現(xiàn):(跟前面的函數(shù)一樣)

1staticportFORCE_INLINEvoidvPortSetBASEPRI(uint32_tulBASEPRI)2{3__asm4{5msrbasepri,ulBASEPRI6}7}

總結(jié)

對于時間關(guān)鍵的任務(wù)而言,恰如其分地使用PRIMASK和BASEPRI來暫時關(guān)閉一些中斷是非常重要的。

FreeRTOS源碼中就有多處臨界段的處理,除了FreeRTOS操作系統(tǒng)源碼所帶的臨界段以外,用戶寫應(yīng)用的時候也有臨界段的問題,比如以下兩種:

讀取或者修改變量(特別是用于任務(wù)間通信的全局變量)的代碼,一般來說這是最常見的臨界代碼。

調(diào)用公共函數(shù)的代碼,特別是不可重入的函數(shù),如果多個任務(wù)都訪問這個函數(shù),結(jié)果是可想而知的。

總之,對于臨界段要做到執(zhí)行時間越短越好,否則會影響系統(tǒng)的實時性。

那假如我有一個線程,處理的時間較長,但是我又不想被其他線程打斷,關(guān)中斷可能影響系統(tǒng)的正常運行,怎么辦呢?其實很簡單,在OS中一般可以直接掛起調(diào)度器,系統(tǒng)正常運行,但是不會切換線程,當(dāng)我處理完再把調(diào)度器解除即可。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 中斷
    +關(guān)注

    關(guān)注

    5

    文章

    900

    瀏覽量

    41997
  • RTOS
    +關(guān)注

    關(guān)注

    23

    文章

    829

    瀏覽量

    120149
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4858

    瀏覽量

    69550

原文標題:RTOS臨界段知識詳解

文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    【安富萊】【RTX操作系統(tǒng)教程】第11章 臨界,任務(wù)鎖和中斷鎖

    多個任務(wù)都訪問這個函數(shù),結(jié)果是可想而知的。 總之,對于臨界要做到執(zhí)行時間越短越好,要不會影響系統(tǒng)的實時性。11.2中斷鎖 中斷鎖就是RTOS提供的開關(guān)中斷函數(shù),因為Cortex-M3/M4的RTX源碼
    發(fā)表于 01-25 16:52

    轉(zhuǎn):第15章 FreeRTOS臨界和開關(guān)中斷

    第15章FreeRTOS臨界和開關(guān)中斷 本章教程為大家講解兩個重要的概念,F(xiàn)reeRTOS的臨界和開關(guān)中斷。 本章教程配套的例子含Cortex-M3內(nèi)核的STM32F103和Cor
    發(fā)表于 08-31 10:15

    第11章 臨界,任務(wù)鎖和中斷鎖

    轉(zhuǎn)rtx操作系統(tǒng) 本章教程為大家講解幾個重要的概念,臨界,任務(wù)鎖和中斷鎖。本章教程配套的例子含Cortex-M3內(nèi)核的STM32F103和Cortex-M4內(nèi)核的STM32F407。11.1 臨界
    發(fā)表于 10-04 19:58

    RTOS臨界知識詳解

    執(zhí)行完畢后,要立即打開中斷。 臨界作用 其實在RTOS中,使用最多的臨界是OS本身的調(diào)用,
    發(fā)表于 10-09 11:02

    【設(shè)計技巧】從單片機到操作系統(tǒng)(8)-RTOS臨界知識詳解

    斷,而臨界代碼執(zhí)行完畢后,要立即打開中斷。臨界作用 其實在RTOS中,使用最多的
    發(fā)表于 08-01 08:30

    FreeRTOS關(guān)于臨界的疑問如何解答

    FreeRTOS中關(guān)于臨界的函數(shù)有4個,taskENTER_CRITICAL():進入臨界,用于任務(wù)中taskEXIT_CRITICAL():退出
    發(fā)表于 06-19 04:36

    請問STM32的FreeRTOS怎么使用臨界?

    STM32的FreeRTOS怎么使用臨界
    發(fā)表于 08-28 08:06

    怎樣去使用FreeRTOS的中斷配置和臨界

    STM32之FreeRTOS:(一) 中斷配置和臨界的使用文章目錄STM32之FreeRTOS:(一) 中斷配置和臨界的使用前言 一、stm32的NVIC 分組配置二、FreeRT
    發(fā)表于 01-14 09:28

    求大佬分享FreeRTOS臨界代碼

    求大佬分享FreeRTOS臨界代碼
    發(fā)表于 02-07 06:28

    freertos中的臨界是如何實現(xiàn)的?

    怎么實現(xiàn)對應(yīng)臨界的保護
    發(fā)表于 10-20 07:25

    FreeRTOS學(xué)習(xí)筆記--臨界代碼處關(guān)閉中斷

    FreeRTOS學(xué)習(xí)筆記--臨界代碼處關(guān)閉中斷一、臨界代碼二、Cortex-M4中斷管理三、中斷屏蔽實驗四、結(jié)語一、臨界
    發(fā)表于 12-04 14:51 ?10次下載
    FreeRTOS學(xué)習(xí)筆記--<b class='flag-5'>臨界</b><b class='flag-5'>段</b>代碼處關(guān)閉中斷

    FreeRTOS臨界

    臨界斷代碼也叫做臨界區(qū),是指那些必須完整運行,不能被打斷的代碼,F(xiàn)reeRTOS與臨界斷代碼保護有關(guān)的函數(shù)有4個:taskENTER_CRITICAL() ——任務(wù)級進入
    發(fā)表于 12-04 16:06 ?0次下載
    FreeRTOS<b class='flag-5'>臨界</b><b class='flag-5'>段</b>

    STM32之FreeRTOS:(一) 中斷配置和臨界的使用

    STM32之FreeRTOS:(一) 中斷配置和臨界的使用文章目錄STM32之FreeRTOS:(一) 中斷配置和臨界的使用前言 一、stm32的NVIC 分組配置二、FreeRT
    發(fā)表于 01-14 15:43 ?3次下載
    STM32之FreeRTOS:(一) 中斷配置和<b class='flag-5'>臨界</b><b class='flag-5'>段</b>的使用

    什么是RTOS臨界

    代碼的臨界也稱為臨界區(qū),指處理時不可分割的代碼區(qū)域,一旦這部分代碼開始執(zhí)行,則不允許任何中斷打斷。為確保臨界代碼的執(zhí)行不被中斷,在進入
    的頭像 發(fā)表于 02-14 09:48 ?1201次閱讀
    什么是<b class='flag-5'>RTOS</b><b class='flag-5'>臨界</b><b class='flag-5'>段</b>

    RTOS臨界知識詳解

    代碼的臨界也稱為臨界區(qū),指處理時不可分割的代碼區(qū)域,一旦這部分代碼開始執(zhí)行,則不允許任何中斷打斷。
    的頭像 發(fā)表于 06-13 14:07 ?1303次閱讀
    <b class='flag-5'>RTOS</b><b class='flag-5'>臨界</b><b class='flag-5'>段</b>知識詳解