色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

RTOS臨界段知識詳解

冬至子 ? 來源:物聯網IoT開發 ? 作者:杰杰mcu ? 2023-06-13 14:07 ? 次閱讀

什么是臨界段

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

臨界段的作用

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

什么時候會打斷代碼的執行?

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

如何關閉中斷?

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

圖片

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

1MRS R0, BASEPRI ;讀取 BASEPRI 到 R02MRS R0, FAULTMASK ;似上
3MRS R0, PRIMASK ;似上
4MSR BASEPRI, R0 ;寫入 R0 到 BASEPRI 中
5MSR FAULTMASK, R0 ;似上
6MSR PRIMASK, R0 ;似上

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

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

圖片

1CPSID I ;PRIMASK=1, ;關中斷
2CPSIE I ;PRIMASK=0, ;開中斷
3CPSID F ;FAULTMASK=1, ;關異常
4CPSIE F ;FAULTMASK=0 ;開異常

上面的代碼中的PRIMASK和 FAULTMAST 是 Cortex-M 內核 里面三個中斷屏蔽寄存器中的兩個,還有一個是 BASEPRI,這些寄存器都用于屏蔽中斷。

1.jpg

不同OS的處理臨界段的區別

FreeRTOS

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

屏蔽中斷:

1static portFORCE_INLINE void vPortRaiseBASEPRI( void )
 2{
 3uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
 4
 5    __asm
 6    {
 7        msr basepri, ulNewBASEPRI
 8        dsb
 9        isb
10    }
11}

打開中斷:

1static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
2{
3    __asm
4    {
5        msr basepri, ulBASEPRI
6    }
7}

RT-Thread

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

現在要看看RT-Thread的關中斷的代碼實現:

1rt_hw_interrupt_disable    PROC
2    EXPORT  rt_hw_interrupt_disable
3    MRS     r0, PRIMASK
4    CPSID   I
5    BX      LR
6    ENDP

開中斷:

1rt_hw_interrupt_enable    PROC
2    EXPORT  rt_hw_interrupt_enable
3    MSR     PRIMASK, r0
4    BX      LR
5    ENDP

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

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

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

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

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

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

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

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

有人又會問了,FreeRTOS的臨界段能允許嵌套嗎,答案是肯定的,FreeRTOS中早已給我們想好調用的函數了,并且全部使用宏定義實現了:

1#define portDISABLE_INTERRUPTS()                vPortRaiseBASEPRI()
2#define portENABLE_INTERRUPTS()                 vPortSetBASEPRI( 0 )
3#define portENTER_CRITICAL()                    vPortEnterCritical()
4#define portEXIT_CRITICAL()                     vPortExitCritical()
5#define portSET_INTERRUPT_MASK_FROM_ISR()       ulPortRaiseBASEPRI()
6#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)    vPortSetBASEPRI(x)

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

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

進入中斷源碼的實現:

1static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
 2{
 3uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
 4
 5    __asm
 6    {
 7        mrs ulReturn, basepri
 8        msr basepri, ulNewBASEPRI
 9        dsb
10        isb
11    }
12    return ulReturn;
13}

退出中斷源碼實現:(跟前面的函數一樣)

1static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )

2{

3 __asm

4 {

5 msr basepri, ulBASEPRI

6 }

7}

總結

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

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

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

調用公共函數的代碼,特別是不可重入的函數,如果多個任務都訪問這個函數,結果是可想而知的。

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

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

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

    關注

    31

    文章

    5363

    瀏覽量

    120949
  • RTOS
    +關注

    關注

    22

    文章

    819

    瀏覽量

    119824
  • MRS
    MRS
    +關注

    關注

    0

    文章

    7

    瀏覽量

    7643
  • Cortex-M
    +關注

    關注

    2

    文章

    229

    瀏覽量

    29805
  • MCU控制
    +關注

    關注

    0

    文章

    48

    瀏覽量

    6772
收藏 人收藏

    評論

    相關推薦

    【安富萊】【RTX操作系統教程】第11章 臨界,任務鎖和中斷鎖

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

    轉:第15章 FreeRTOS臨界和開關中斷

    。 注:FreeRTOS臨界相關知識補充 FreeRTOS的源碼中有多處臨界的地方,臨界
    發表于 08-31 10:15

    第11章 臨界,任務鎖和中斷鎖

    轉rtx操作系統 本章教程為大家講解幾個重要的概念,臨界,任務鎖和中斷鎖。本章教程配套的例子含Cortex-M3內核的STM32F103和Cortex-M4內核的STM32F407。11.1 臨界
    發表于 10-04 19:58

    RTOS臨界知識詳解

    執行完畢后,要立即打開中斷。 臨界的作用 其實在RTOS中,使用最多的臨界是OS本身的調用,但是我們用戶也是需要對
    發表于 10-09 11:02

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

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

    FreeRTOS關于臨界的疑問如何解答

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

    請問STM32的FreeRTOS怎么使用臨界

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

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

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

    freertos中的臨界是如何實現的?

    怎么實現對應臨界的保護
    發表于 10-20 07:25

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

    代碼的臨界也稱為臨界區,指處理時不可分割的代碼區域,一旦這部分代碼開始執行,則不允許任何中斷打斷。為確保臨界代碼的執行不被中斷,在進入
    的頭像 發表于 10-06 14:38 ?1.2w次閱讀
    什么是<b class='flag-5'>臨界</b><b class='flag-5'>段</b> <b class='flag-5'>RTOS</b><b class='flag-5'>臨界</b><b class='flag-5'>段</b>的作用是什么

    FreeRTOS學習筆記--臨界代碼處關閉中斷

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

    FreeRTOS臨界

    臨界斷代碼也叫做臨界區,是指那些必須完整運行,不能被打斷的代碼,FreeRTOS與臨界斷代碼保護有關的函數有4個:taskENTER_CRITICAL() ——任務級進入
    發表于 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
    發表于 01-14 15:43 ?3次下載
    STM32之FreeRTOS:(一) 中斷配置和<b class='flag-5'>臨界</b><b class='flag-5'>段</b>的使用

    什么是RTOS臨界

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

    STM32 RTOS知識

    電子發燒友網站提供《STM32 RTOS知識點.pdf》資料免費下載
    發表于 08-01 14:28 ?3次下載
    STM32 <b class='flag-5'>RTOS</b><b class='flag-5'>知識</b>點
    主站蜘蛛池模板: 国产高清在线a视频大全 | 96精品视频| 国产在线精彩视频 | 18国产精品白浆在线观看免费 | 日韩精品一区二区三区AV在线观看 | 熟妇少妇任你躁在线无码 | 亚洲国产在线精品国偷产拍 | 成人午夜精品久久久久久久秋霞 | 动漫美女喷水 | 久久精品国产亚洲精品2020 | 妖精视频一区二区免费 | 国产AV无码一二三区视频 | 操他射他影院 | 啦啦啦 中文 日本 韩国 免费 | 亚州笫一色惰网站 | 奇米狠狠一区二区三区 | 欧美嫩freexxxhddvd | 欧美 国产 日产 韩国 在线 | 国产在线精品视频资源 | 97在线免费观看 | 欧美日韩高清一区二区三区 | 扒开屁股眼往里面夹东西 | 扒开她的黑森林让我添动态图 | 国产精品日韩欧美一区二区三区 | 成人午夜精品无码区久久漫画日本 | 久久精品国产午夜伦班片 | 久久久免费观成人影院 | 国产在线观看成人 | 在线 | 果冻国产传媒61国产免费 | 特黄特色大片免费播放器试看 | 美女扒开腿让男人桶个爽 | 中文字幕精品AV内射夜夜夜 | 国产精品禁18久久久夂久 | 久久xxxx | 俺来也俺去也视频久久 | 97在线免费观看 | 无限资源在线完整高清观看1 | 尤物久久99国产综合精品 | poronovideos动物狗猪 | 亚洲AV国产精品无码精 | 大屁股国产白浆一二区 |