国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

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

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

3天內不再提示

Cortex-M裸機環境下臨界區保護的三種實現

strongerHuang ? 來源:痞子衡嵌入式 ? 作者:痞子衡 ? 2021-09-08 09:23 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

今天給大家分享的是Cortex-M裸機環境下臨界區保護的三種實現。

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

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

一、臨界區保護測試場景

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

void critical_section_test(void)

{

// 進入臨界區

enter_critical();

// 做受保護的任務1

do_task1();

// 退出臨界區

exit_critical();

// 進入臨界區

enter_critical();

// 做受保護的任務2,與任務1無關聯

do_task2();

// 退出臨界區

exit_critical();

}

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

void do_task1(void)

{

// 進入臨界區

enter_critical();

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

do_task2();

// 退出臨界區

exit_critical();

// 做任務3

do_task3();

}

void critical_section_test(void)

{

// 進入臨界區

enter_critical();

// 做受保護的任務1

do_task1();

// 退出臨界區

exit_critical();

}

二、臨界區保護三種實現

上面的臨界區保護測試場景很清楚了,現在到 enter_critical()、exit_critical() 這對臨界區保護函數的實現環節了:

2.1 入門做法

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

void enter_critical(void)

{

// 關閉系統全局中斷

__disable_irq();

}

void exit_critical(void)

{

// 打開系統全局中斷

__enable_irq();

}

2.2 改進做法

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

static uint32_t s_lockObject;

void init_critical(void)

{

__disable_irq();

// 清零計數器

s_lockObject = 0;

__enable_irq();

}

void enter_critical(void)

{

// 關閉系統全局中斷

__disable_irq();

// 計數器加 1

++s_lockObject;

}

void exit_critical(void)

{

if (s_lockObject 《= 1)

{

// 僅當計數器不大于 1 時,才打開系統全局中斷,并清零計數器

s_lockObject = 0;

__enable_irq();

}

else

{

// 當計數器大于 1 時,直接計數器減 1 即可

--s_lockObject;

}

}

2.3 終極做法

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

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

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

uint32_t enter_critical(void)

{

// 保存當前 PRIMASK 值

uint32_t regPrimask = __get_PRIMASK();

// 關閉系統全局中斷(其實就是將 PRIMASK 設為 1)

__disable_irq();

return regPrimask;

}

void exit_critical(uint32_t primask)

{

// 恢復 PRIMASK

__set_PRIMASK(primask);

}

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

void critical_section_test(void)

{

// 進入臨界區

uint32_t primask = enter_critical();

// 做受保護的任務

do_task();

// 退出臨界區

exit_critical(primask);

// 。..

}

附錄、PRIMASK寄存器設置函數在各 IDE 下實現

//////////////////////////////////////////////////////// IAR 環境下實現(見 cmsis_iccarm.h 文件)#define __set_PRIMASK(VALUE) (__arm_wsr(“PRIMASK”, (VALUE)))#define __get_PRIMASK() (__arm_rsr(“PRIMASK”))//////////////////////////////////////////////////////// Keil 環境下實現(見 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裸機環境下臨界區保護的三種實現已經講述完畢,你學廢了嗎?

責任編輯:haq

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

    關注

    6076

    文章

    45494

    瀏覽量

    670258
  • 嵌入式
    +關注

    關注

    5198

    文章

    20442

    瀏覽量

    333971
  • RTOS
    +關注

    關注

    25

    文章

    866

    瀏覽量

    122972

原文標題:單片機非RTOS時,臨界區保護的實現辦法

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    Cortex-M0和Cortex-M0+的區別

    ),但是只使用了Thumb ISA的一個子集(56條指令),多數指令是16位,只有少數一些事32位。 一般來說,盡管指令具有不同大小,Cortex-M處理器可被歸為精簡指令集架構。 支持可選的單周期
    發表于 01-22 06:23

    最小化ARM Cortex-M CPU功耗的方法與技巧分享

    中斷處理程序中,中斷服務程序之間的“入棧和出棧(push-and-pop)”操作就要消耗多達42個時鐘周期。而Cortex-M NVIC采用更有效的方法實現相同任務,被稱為“末尾連鎖
    發表于 01-21 06:19

    Cortex-M0 處理器介紹

    功耗的32位處理器。 Cortex-M0是Cortex-M家族中的M0系列。最大特點是低功耗的設計。Cortex-M0為32位、3級流水線RISC處理器,其核心仍為馮.諾依曼結構,是指
    發表于 01-16 08:04

    請問CW32芯片的三種工作模式是什么?

    CW32芯片的三種工作模式是什么?
    發表于 12-26 06:48

    Cortex-M產品的特色

    低功耗設計:Cortex-M系列處理器核心被設計為低功耗架構,適用于移動電源和電池供電的嵌入式系統。 高性能處理:Cortex-M處理器具有高性能的特點,能夠處理復雜的實時任務,并擁有較高
    發表于 11-26 07:22

    Cortex-M內核中的精確延時的方法

    使用 CYCCNT寄存器來測量執行某個任務所花的周期數,這也可以用作時間基準相關的目的(操作系統中統計 CPU使用率可以用到它)。” Cortex-M中的DWT它有一個32位的寄存器叫CYCCNT
    發表于 11-21 07:51

    Cortex-M級別的轉換

    一、 簡述 Cortex-M 里面有特權級別的概念,不同級別可以設定不同的權限,如何轉換特權級別基本是本章的內容。 二、操作模式 ARM M 核操作模式有兩個: 線程(Thread)模式:在復位時或
    發表于 11-19 07:32

    請問NuMicro? Cortex-M? 系列芯片是否支持 I2C 監視器功能?

    NuMicro? Cortex-M? 系列芯片是否支持 I2C 監視器功能?
    發表于 08-21 06:04

    MEMS中的三種測溫方式

    在集成MEMS芯片的環境溫度測量領域,熱阻、熱電堆和PN結原理是三種主流技術。熱阻是利用熱敏電阻,如金屬鉑或注入硅的溫度電阻系數恒定,即電阻隨溫度線性變化的特性測溫,電阻變化直接對應絕對溫度,需恒流源供電。
    的頭像 發表于 07-16 13:58 ?1657次閱讀
    MEMS中的<b class='flag-5'>三種</b>測溫方式

    開關電源三種控制模式:PWM/PFM/PSM

    摘要 本文詳細介紹了開關電源的三種主要調制方式:PWM(脈沖寬度調制)、PFM(脈沖頻率調制)和PSM(脈沖跨周期調制)。PWM通過調整脈沖寬度保持恒定頻率,適用于重負載,但輕負載效率低。PFM則在
    發表于 06-09 16:11

    介紹三種常見的MySQL高可用方案

    在生產環境中,為了確保數據庫系統的連續可用性、降低故障恢復時間以及實現業務的無縫切換,高可用(High Availability, HA)方案至關重要。本文將詳細介紹三種常見的 MySQL 高可用
    的頭像 發表于 05-28 17:16 ?1235次閱讀

    redis三種集群方案詳解

    在Redis中提供的集群方案總共有三種(一般一個redis節點不超過10G內存)。
    的頭像 發表于 03-31 10:46 ?1528次閱讀
    redis<b class='flag-5'>三種</b>集群方案詳解

    DeepSeek企業級部署RakSmart裸機環境準備指南

    RakSmart裸機環境中部署DeepSeek的企業級環境準備指南,內容涵蓋關鍵步驟和注意事項,主機推薦小編為您整理發布DeepSeek企業級RakSmart裸機云部署指南。
    的頭像 發表于 03-24 10:07 ?938次閱讀

    介紹三種數據保護策略的特點與適用場景

    在企業IT環境中,數據保護是不可忽視的重要環節,而復制(Replication)、快照(Snapshot)和備份(Backup)是三種常見的策略。它們在數據恢復、業務連續性以及災難恢復中扮演著不同的角色,但很多企業在選擇數據
    的頭像 發表于 03-21 11:46 ?1517次閱讀

    瑞薩RA8快速上手指南:Cortex-M85內核瑞薩RA8開發環境搭建 并點亮一個LED

    因為Cortex-M內核,瑞薩RA8系列單片機支持多種市面上常見的開發環境,像Keil MDK、IAR EWARM等,而本文講述的是瑞薩自家官方的IDE(e2 studio)。
    的頭像 發表于 03-17 14:35 ?1926次閱讀
    瑞薩RA8快速上手指南:<b class='flag-5'>Cortex-M</b>85內核瑞薩RA8開發<b class='flag-5'>環境</b>搭建 并點亮一個LED