在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

Cortex-M裸機環(huán)境下臨界區(qū)保護的三種實現(xiàn)

strongerHuang ? 來源:痞子衡嵌入式 ? 作者:痞子衡 ? 2021-09-08 09:23 ? 次閱讀

今天給大家分享的是Cortex-M裸機環(huán)境下臨界區(qū)保護的三種實現(xiàn)。

嵌入式玩過 RTOS 的朋友想必都對 OS_ENTER_CRITICAL()、OS_EXIT_CRITICAL() 這個功能代碼對特別眼熟,在 RTOS 里常常會有多任務(進程)處理,有些情況下一些特殊操作(比如 XIP 下 Flash 擦寫、低功耗模式切換)不能被隨意打斷,或者一些共享數(shù)據(jù)區(qū)不能被無序訪問(A 任務正在讀,B 任務卻要寫),這時候就要用到臨界區(qū)保護策略了。

所謂臨界區(qū)保護策略,簡單說就是系統(tǒng)中硬件臨界資源或者軟件臨界資源,多個任務必須互斥地對它們進行訪問。RTOS 環(huán)境下有現(xiàn)成的臨界區(qū)保護接口函數(shù),而裸機系統(tǒng)里其實也有這種需求。在裸機系統(tǒng)里,臨界區(qū)保護主要就是跟系統(tǒng)全局中斷控制有關(guān)。痞子衡之前寫過一篇 《嵌入式MCU中通用的三重中斷控制設計》,文中介紹的第三重也是最頂層的中斷控制是系統(tǒng)全局中斷控制,今天痞子衡就從這個系統(tǒng)全局中斷控制使用入手給大家介紹三種臨界區(qū)保護做法:

一、臨界區(qū)保護測試場景

關(guān)于臨界區(qū)保護的測試場景無非兩種。第一種場景是受保護的多個任務間并無關(guān)聯(lián),也不會互相嵌套,如下面的代碼所示,task1 和 task2 是按序被保護的,因此 enter_critical() 和 exit_critical() 這兩個臨界區(qū)保護函數(shù)總是嚴格地成對執(zhí)行:

void critical_section_test(void)

{

// 進入臨界區(qū)

enter_critical();

// 做受保護的任務1

do_task1();

// 退出臨界區(qū)

exit_critical();

// 進入臨界區(qū)

enter_critical();

// 做受保護的任務2,與任務1無關(guān)聯(lián)

do_task2();

// 退出臨界區(qū)

exit_critical();

}

第二種場景就是多個任務間可能有關(guān)聯(lián),會存在嵌套情況,如下面的代碼所示,task2 是 task1 的一個子任務,這種情況下,你會發(fā)現(xiàn)實際上是先執(zhí)行兩次 enter_critical(),然后再執(zhí)行兩次 exit_critical()。需要注意的是 task1 里面的子任務 task3 雖然沒有像子任務 task2 那樣被主動加一層保護,但由于主任務 task1 整體是受保護的,因此子任務 task3 也應該是受保護的。

void do_task1(void)

{

// 進入臨界區(qū)

enter_critical();

// 做受保護的任務2,是任務1中的子任務

do_task2();

// 退出臨界區(qū)

exit_critical();

// 做任務3

do_task3();

}

void critical_section_test(void)

{

// 進入臨界區(qū)

enter_critical();

// 做受保護的任務1

do_task1();

// 退出臨界區(qū)

exit_critical();

}

二、臨界區(qū)保護三種實現(xiàn)

上面的臨界區(qū)保護測試場景很清楚了,現(xiàn)在到 enter_critical()、exit_critical() 這對臨界區(qū)保護函數(shù)的實現(xiàn)環(huán)節(jié)了:

2.1 入門做法

首先是非常入門的做法,直接就是對系統(tǒng)全局中斷控制函數(shù) __disable_irq()、__enable_irq() 的封裝?;氐缴弦还?jié)的測試場景里,這種實現(xiàn)可以很好地應對非嵌套型任務的保護,但是對于互相嵌套的任務保護就失效了。上一節(jié)測試代碼里,task3 應該也要受到保護的,但實際上并沒有被保護,因為緊接著 task2 后面的 exit_critical() 直接就打開了系統(tǒng)全局中斷。

void enter_critical(void)

{

// 關(guān)閉系統(tǒng)全局中斷

__disable_irq();

}

void exit_critical(void)

{

// 打開系統(tǒng)全局中斷

__enable_irq();

}

2.2 改進做法

針對入門做法,可不可以改進呢?當然可以,我們只需要加一個全局變量 s_lockObject 來實時記錄當前已進入的臨界區(qū)保護的次數(shù),即如下代碼所示。每調(diào)用一次 enter_critical() 都會直接關(guān)閉系統(tǒng)全局中斷(保證臨界區(qū)一定是受保護的),并記錄次數(shù),而調(diào)用 exit_critical() 時僅當當前次數(shù)是 1 時(即當前不是臨界區(qū)保護嵌套情況),才會打開系統(tǒng)全局中斷,否則只是抵消一次進入臨界區(qū)次數(shù)而已。改進后的實現(xiàn)顯然可以保護上一節(jié)測試代碼里的 task3 了。

static uint32_t s_lockObject;

void init_critical(void)

{

__disable_irq();

// 清零計數(shù)器

s_lockObject = 0;

__enable_irq();

}

void enter_critical(void)

{

// 關(guān)閉系統(tǒng)全局中斷

__disable_irq();

// 計數(shù)器加 1

++s_lockObject;

}

void exit_critical(void)

{

if (s_lockObject 《= 1)

{

// 僅當計數(shù)器不大于 1 時,才打開系統(tǒng)全局中斷,并清零計數(shù)器

s_lockObject = 0;

__enable_irq();

}

else

{

// 當計數(shù)器大于 1 時,直接計數(shù)器減 1 即可

--s_lockObject;

}

}

2.3 終極做法

上面的改進做法雖然解決了臨界區(qū)任務嵌套保護的問題,但是增加了一個全局變量和一個初始化函數(shù),實現(xiàn)不夠優(yōu)雅,并且嵌入式系統(tǒng)里全局變量極容易被篡改,存在一定風險,有沒有更好的實現(xiàn)呢?當然有,這要借助 Cortex-M 處理器內(nèi)核的特殊屏蔽寄存器 PRIMASK,下面是 PRIMASK 寄存器位定義(取自 ARMv7-M 手冊),其僅有最低位 PM 是有效的,當 PRIMASK[PM] 為 1 時,系統(tǒng)全局中斷是關(guān)閉的(將執(zhí)行優(yōu)先級提高到 0x0/0x80);當 PRIMASK[PM] 為 0 時,系統(tǒng)全局中斷是打開的(對執(zhí)行優(yōu)先級無影響)。

345fd67a-1018-11ec-8fb8-12bb97331649.png

看到這,你應該明白了 __disable_irq()、__enable_irq() 功能其實就是操作 PRIMASK 寄存器實現(xiàn)的。既然 PRIMASK 寄存器控制也保存了系統(tǒng)全局中斷的開關(guān)狀態(tài),我們可以通過獲取 PRIMASK 值來替代上面改進做法里的全局變量 s_lockObject 的功能,代碼實現(xiàn)如下:

uint32_t enter_critical(void)

{

// 保存當前 PRIMASK 值

uint32_t regPrimask = __get_PRIMASK();

// 關(guān)閉系統(tǒng)全局中斷(其實就是將 PRIMASK 設為 1)

__disable_irq();

return regPrimask;

}

void exit_critical(uint32_t primask)

{

// 恢復 PRIMASK

__set_PRIMASK(primask);

}

因為 enter_critical()、exit_critical() 函數(shù)原型有所變化,因此使用上也要相應改變下:

void critical_section_test(void)

{

// 進入臨界區(qū)

uint32_t primask = enter_critical();

// 做受保護的任務

do_task();

// 退出臨界區(qū)

exit_critical(primask);

// 。..

}

附錄、PRIMASK寄存器設置函數(shù)在各 IDE 下實現(xiàn)

//////////////////////////////////////////////////////// IAR 環(huán)境下實現(xiàn)(見 cmsis_iccarm.h 文件)#define __set_PRIMASK(VALUE) (__arm_wsr(“PRIMASK”, (VALUE)))#define __get_PRIMASK() (__arm_rsr(“PRIMASK”))//////////////////////////////////////////////////////// Keil 環(huán)境下實現(xiàn)(見 cmsis_armclang.h 文件)

__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask)

{

__ASM volatile (“MSR primask, %0” : : “r” (priMask) : “memory”);

}

__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void)

{

uint32_t result;

__ASM volatile (“MRS %0, primask” : “=r” (result) );

return(result);

}

至此,Cortex-M裸機環(huán)境下臨界區(qū)保護的三種實現(xiàn)已經(jīng)講述完畢,你學廢了嗎?

責任編輯:haq

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

    關(guān)注

    6040

    文章

    44602

    瀏覽量

    637040
  • 嵌入式
    +關(guān)注

    關(guān)注

    5088

    文章

    19160

    瀏覽量

    306549
  • RTOS
    +關(guān)注

    關(guān)注

    22

    文章

    818

    瀏覽量

    119772

原文標題:單片機非RTOS時,臨界區(qū)保護的實現(xiàn)辦法

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

收藏 人收藏

    評論

    相關(guān)推薦

    示波器的三種觸發(fā)模式

    示波器的觸發(fā)方式不僅影響波形捕捉的時機,還決定了顯示的波形是否穩(wěn)定。 常見的觸發(fā)模式有三種: 單次觸發(fā) (Single)、 正常觸發(fā) (Normal)和 自動觸發(fā) (Auto)。下面將對這三種觸發(fā)
    的頭像 發(fā)表于 01-07 11:04 ?173次閱讀
    示波器的<b class='flag-5'>三種</b>觸發(fā)模式

    如何使用Ozone分析Cortex-M異常

    Ozone可以幫助用戶快速分析和查找導致CPU故障的軟件bug。本文解釋如何使用Ozone的調(diào)試功能,深入了解Cortex-M架構(gòu)上的這些錯誤。
    的頭像 發(fā)表于 11-29 11:14 ?855次閱讀
    如何使用Ozone分析<b class='flag-5'>Cortex-M</b>異常

    三種封裝形式的400G光模塊概述

    本文主要就三種封裝形式(QSFP-DD、OSFP、QSFP112)的400G光模塊做了簡單的梳理,從為什么會有400G光模塊問世?400G光模塊在三種封裝形式的各個具體型號(以短距離為主,最遠2km),
    的頭像 發(fā)表于 11-11 11:35 ?483次閱讀
    <b class='flag-5'>三種</b>封裝形式<b class='flag-5'>下</b>的400G光模塊概述

    mosfet的三種工作狀態(tài)及工作條件是什么

    )的不同,可以工作在三種主要狀態(tài):截止狀態(tài)、線性區(qū)和飽和區(qū)。 1. 截止狀態(tài) 工作狀態(tài)描述 : 當VGS小于MOSFET的開啟電壓(VGS(TH))時,MOSF
    的頭像 發(fā)表于 10-06 16:51 ?2484次閱讀

    電流保護裝置的接線方式主要有哪三種

    三種主要的電流保護裝置接線方式的介紹: 1. 星形接線(Star Connection) 星形接線,也稱為Y型接線,是一常見的電流保護裝置接線方式。在這種接線方式中,電流
    的頭像 發(fā)表于 09-13 15:48 ?865次閱讀

    如何利用三種 SOT-563 封裝實現(xiàn)共同布局

    電子發(fā)燒友網(wǎng)站提供《如何利用三種 SOT-563 封裝實現(xiàn)共同布局.pdf》資料免費下載
    發(fā)表于 09-10 14:25 ?0次下載
    如何利用<b class='flag-5'>三種</b> SOT-563 封裝<b class='flag-5'>實現(xiàn)</b>共同布局

    丙類諧振功率放大器有哪三種工作狀態(tài)

    丙類諧振功率放大器是一廣泛應用于通信、廣播、雷達等領域的高頻功率放大器。它利用非線性元件的非線性特性,通過調(diào)整工作狀態(tài),實現(xiàn)高效率、高功率輸出。丙類諧振功率放大器有三種工作狀態(tài):截止區(qū)
    的頭像 發(fā)表于 08-01 11:05 ?1812次閱讀

    淺析FreeRTOS任務調(diào)度器的三種調(diào)度算法和應用

    FreeRTOS在MCU領域應用非常廣泛,今天就給大家講解一FreeRTOS調(diào)度器中的三種調(diào)度算法,以及在瑞薩RZ/T2L MPU中的應用。
    的頭像 發(fā)表于 05-10 14:02 ?7703次閱讀
    淺析FreeRTOS任務調(diào)度器的<b class='flag-5'>三種</b>調(diào)度算法和應用

    Cortex-M0+內(nèi)核介紹

    和8位的價位實現(xiàn)32位性能。處理器的低門數(shù)使其能夠部署在需要簡單功能的應用中。 作為ARM Cortex-M處理器系列的最新成員,32位Cortex-M0+處理器采用了低成本90納米低功耗(LP)工藝,耗電量僅9μA/MHz,約
    的頭像 發(fā)表于 03-27 09:13 ?1113次閱讀
    <b class='flag-5'>Cortex-M</b>0+內(nèi)核介紹

    三種實現(xiàn)光模塊更高傳輸速率的技術(shù)

    本文介紹三種提高光模塊傳輸速率的技術(shù):波分復用技術(shù)、多路并行傳輸技術(shù)和高階調(diào)制技術(shù)。波分復用技術(shù)利用光的波長特性將不同波長的信號同時傳輸在同一條光纖上,實現(xiàn)光纖的并行傳輸。多路并行傳輸技術(shù)利用多個通道同時傳輸數(shù)據(jù),從而提高傳輸帶寬和速度。
    的頭像 發(fā)表于 03-11 15:31 ?802次閱讀

    簡述斬波電路的三種控制方式

    斬波電路是一常見的電力電子器件,廣泛應用于直流電壓調(diào)節(jié)、電壓變換、電流變換等領域。它可以實現(xiàn)對電流和電壓的控制,以滿足不同的電氣設備的需求。斬波電路的控制方式主要有三種:脈寬調(diào)制控制、頻率調(diào)制控制
    的頭像 發(fā)表于 03-11 15:22 ?4486次閱讀

    Cortex-M85內(nèi)核單片機如何快速上手

    2022年4月,Arm推出了全新的MCU級內(nèi)核Cortex-M85。截止目前(2024年2月),Cortex-M85是最新、最強的Cortex-M內(nèi)核。
    發(fā)表于 02-29 09:35 ?777次閱讀
    <b class='flag-5'>Cortex-M</b>85內(nèi)核單片機如何快速上手

    M70 PLC增加注解的三種方法簡析

    M70 PLC增加注解的三種方法
    的頭像 發(fā)表于 02-26 09:59 ?1129次閱讀
    <b class='flag-5'>三</b>菱<b class='flag-5'>M</b>70 PLC增加注解的<b class='flag-5'>三種</b>方法簡析

    運放的三種應用

    運放在電路中主要存在三種應用,放大器,濾波器,振蕩器。再這三種應用電路中,運放的兩大特點虛短虛斷仍然成立嗎? 在阻尼振蕩器中,工作過程是否按照我描述的這樣,在反相輸入端加一個近似鋸齒波的電流源,正半
    發(fā)表于 01-26 16:18

    嵌入式Linux開發(fā)的三種方式

    嵌入式Linux開發(fā)主要有三種方式:裸機開發(fā)、SDK開發(fā)和驅(qū)動開發(fā)。
    的頭像 發(fā)表于 01-22 14:22 ?1017次閱讀
    主站蜘蛛池模板: 在线天堂bt种子| 天天欲色| 亚洲网站免费观看| 亚洲一区二区精品推荐| 女攻各种play男受h| 国产精品第页| 亚洲欧美在线播放| 四虎国产精品高清在线观看| 人人草97| 国内自拍露脸普通话对白在线| 性欧美丰满xxxx性久久久| 国产精品自在线天天看片| 涩涩色中文综合亚洲| 亚州一级毛片| 亚洲综合久久综合激情久久| 色老头久久网| 精品国产成人系列| 777777777妇女亚洲| 日日躁夜夜躁狠狠天天| 163黄页网又粗又长又舒服| 日本一区视频在线播放| 亚洲91| 欧美freesex10一|3| 四虎永久免费网站入口2020| 青草91| 成人做视频免费| 色综合色综合色综合色综合| 国产18到20岁美女毛片| 丝袜美女被c| 天堂资源在线bt种子| 九色欧美| 手机在线看片福利盒子| 俺也啪| 网友偷自拍原创区| 性欧美视频在线观看| 日本久本草精品| 免费能直接在线观看黄的视频| 国模福利| 免费一级黄色录像| 视频一区 在线| 日本网站黄色|