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

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

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

3天內不再提示

__disable_irq()和__enable_irq()函數的具體定義

TopSemic嵌入式 ? 來源:TopSemic嵌入式 ? 2024-08-29 10:06 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前段時間一工程師向我咨詢了一個問題,問我為什么他的MCU KEIL工程代碼里沒有找到__disable_irq() 和 __enable_irq()的具體定義,是不是有問題。

wKgZombP18aAKIgJAACAC6ifUtA639.png

直接在工程里搜索,確實只能在cmsis_armcc.h文件里看到下面的兩處注釋說明,并沒有這倆函數的具體定義。

wKgaombP19iAKZCIAAAnqTdnJps986.png

可是如果直接去調用這倆函數的話,編譯又不會報錯,那么這倆函數的定義到底在哪呢?

__disable_irq() 和 __enable_irq() 是所謂的intrinsic函數,編譯器自動識別并替換為相關的指令,它們其實是編譯器的一部分,實際的定義位于arm_compat.h 文件中(位于KEIL的安裝目錄里),

static__inline__unsignedint__attribute__((__always_inline__,__nodebug__))
__disable_irq(void){
unsignedintcpsr;
#if__ARM_ARCH>=6
#ifdefined(__ARM_ARCH_PROFILE)&&__ARM_ARCH_PROFILE=='M'
__asm____volatile__("mrs%[cpsr],primask
"
"cpsidi
"
:[cpsr]"=r"(cpsr));
returncpsr&0x1;
#else/*!defined(__ARM_ARCH_PROFILE)||__ARM_ARCH_PROFILE!='M'*/
__asm____volatile__("mrs%[cpsr],cpsr
"
"cpsidi
"
:[cpsr]"=r"(cpsr));
returncpsr&0x80;
#endif
#else/*__ARM_ARCH
#if(defined(__ARM_ARCH_PROFILE)&&__ARM_ARCH_PROFILE=='M'&&
__ARM_ARCH==6)||__ARM_ARCH_8M_BASE__
static__inline__void__attribute__((unavailable(
"intrinsicnotsupportedforthisarchitecture")))__enable_fiq(void);
#else//(!defined(__ARM_ARCH_PROFILE)||__ARM_ARCH_PROFILE!='M'||
//__ARM_ARCH!=6)&&!__ARM_ARCH_8M_BASE__
static__inline__void__attribute__((__always_inline__,__nodebug__))
__enable_fiq(void){
#if__ARM_ARCH>=6
__asm____volatile__("cpsief");
#else/*__ARM_ARCH

核心是 cpsie i 和 cpsid i 這兩個指令。

cps全稱change processor state,即改變PRIMASK這個寄存器

ie: interrupt enable. 中斷使能,即PRIMASK.PM設置為0

id: interrupt disable. 中斷關閉,即PRIMASK.PM設置為1

3dd39db1f6db39a0cd121d329fe74de5.png

3dd39db1f6db39a0cd121d329fe74de5.png

__enable_irq()函數調用cpsie i指令。

__disable_irq()函數除調用cpsid i 指令,同時返回了PRIMASK的值,即如果返回值為 0,則表示中斷在調用該函數之前是使能的;如果返回值為1,則表示中斷在調用函數之前是禁用的。

需要注意的是:如果之前開啟了相關外設的中斷功能,在調用__disable_irq()函數關中斷后,這時如果有中斷觸發,那么不會去進行中斷響應。但是在調用__enable_irq()開啟中斷后,MCU會立即處理之前觸發的中斷。這說明__disable_irq()只是禁止CPU去響應中斷,沒有真正的去屏蔽中斷的觸發,當中斷發生后,相應的寄存器會將中斷標志置位,在__enable_irq()開啟中斷后,由于相應的中斷標志沒有清空,因而還會觸發中斷。

以下述代碼為例,程序中使用了一個GPIO中斷,當按鍵按下時翻轉一次LED。實際測試如果在調用__disable_irq()后、__enable_irq()之前的這3s時間內按下按鍵,并不會進入中斷翻轉LED,雖然這時中斷標志位已經產生了。

e0ec29af41084f964c2f2593534e1382.png

但是調用__enable_irq()之后就會立刻進入到中斷服務函數中。

intmain(void)
{
/*配置系統時鐘*/
system_clock_config();

/*Systick初始化*/
std_delay_init();

/*LED初始化*/
led_init();

/*EXTI初始化*/
exti_init();

__disable_irq();

std_delayms(3000);

__enable_irq();

while(1)
{

}
}

/**
*@briefEXTI4_15中斷服務函數
*@retval無
*/
voidEXTI4_15_IRQHandler(void)
{
/*讀取EXTI通道中斷掛起狀態*/
if(std_exti_get_pending_status(EXTI_LINE_GPIO_PIN13))
{
/*清除EXTI通道中斷掛起狀態*/
std_exti_clear_pending(EXTI_LINE_GPIO_PIN13);
LED1_TOGGLE();
}
}

說到這里你可能還注意到還有__NVIC_DisableIRQ(IRQn_Type IRQn)、__NVIC_EnableIRQ(IRQn_Type IRQn) 這倆函數

/**
riefDisableInterrupt
detailsDisablesadevicespecificinterruptintheNVICinterruptcontroller.
param[in]IRQnDevicespecificinterruptnumber.

oteIRQnmustnotbenegative.
*/
__STATIC_INLINEvoid__NVIC_DisableIRQ(IRQn_TypeIRQn)
{
if((int32_t)(IRQn)>=0)
{
NVIC->ICER[0U]=(uint32_t)(1UL<
/**
riefEnableInterrupt
detailsEnablesadevicespecificinterruptintheNVICinterruptcontroller.
param[in]IRQnDevicespecificinterruptnumber.

oteIRQnmustnotbenegative.
*/
__STATIC_INLINEvoid__NVIC_EnableIRQ(IRQn_TypeIRQn)
{
if((int32_t)(IRQn)>=0)
{
NVIC->ISER[0U]=(uint32_t)(1UL<

這倆函數和上述函數的區別是,上面的兩個函數是開關全局的中斷,這倆函數是針對某特定的中斷。

但是有一點相同的是,如果在調用__NVIC_DisableIRQ之后發生了中斷事件,當調用__NVIC_EnableIRQ(IRQn_Type IRQn)之后還是會進入到中斷處理。

綜上disable函數只是不響應中斷,并不會影響中斷的產生,在disable狀態下如果發生中斷則會掛起,等到enable后滿足條件還是會被執行。如果不希望此現象發生,那么需要再enable前清除掉相關外設模塊中斷掛起請求標志。

如果想真正禁止中斷的產生的話,還得從源頭上配置相關外設的寄存器關掉中斷才行。

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

    關注

    146

    文章

    17918

    瀏覽量

    362811
  • 寄存器
    +關注

    關注

    31

    文章

    5430

    瀏覽量

    123965
  • 函數
    +關注

    關注

    3

    文章

    4377

    瀏覽量

    64556
  • 編譯器
    +關注

    關注

    1

    文章

    1659

    瀏覽量

    50059

原文標題:__disable_irq() 和 __enable_irq()定義在哪?

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

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

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    cmsis_armcc.h沒有實現__disable_irq函數接口,還有別的函數嗎?

    cmsis_armcc.h沒有實現__disable_irq函數接口,還有別的函數嗎?除了__NVIC_DisableIRQ
    發表于 04-02 08:25

    STM32F0 IAP進入APP后 __disable_irq() 失效了的原因?

    如題,STM32F030C8T6 做 IAP 現能正確的從 bootloader 中跳轉到 APP,在APP中也能正常的進入中斷,為什么在APP中使用 __disable_irq();無法關閉 所有中斷。 經測試 在bootloader中__disable_irq();是
    發表于 04-22 08:21

    stm32f0讀寫內部flash和刷新液晶屏時,禁止所有中斷,__disable_irq();不起作用,還會進入中斷響應函數為什么?

    讀寫內部flash和刷新液晶屏時,禁止所有中斷,__disable_irq();不起作用,還會進入中斷響應函數
    發表于 05-09 06:41

    TC387中有__disable_interrupts()關閉所有中斷和打開所有中斷的函數或宏嗎?

    TC387 芯片中有__disable_irq()和__enable_irq()關閉所有中斷和打開所有中斷的函數或宏嗎,請告知
    發表于 08-01 08:22

    stm32 Cortex M3內核 ,CPU調用__disable_irq函數關閉中斷后,為何還能接收到中斷????????

    Cortex M3內核 ,CPU調用__disable_irq函數關閉中斷后,進入睡眠模式,并且調用__WFI()函數,等待中斷,結果當有外部中斷進入時,CPU喚醒。跪求大神指教這是什么原理,關閉中斷后,等待中斷,然后中斷來了,
    發表于 05-25 11:41

    請問除了__disable_irq();__enable_irq()之外還有其他暫時屏蔽中斷嗎?

    我在設計中要利用__disable_irq();__enable_irq()來實現原子操作,防止中斷與正常運行程序同時訪問數據造成不一致,但是這個是暫時屏蔽全局中斷的。我系統中有個最高優先級的是不能
    發表于 08-27 10:15

    設備樹中GIC中斷控制器節點

    irq_handler_tirqreturn_t(2)flags2、free_irq()函數3、enable_irq()函數4、
    發表于 01-10 07:37

    請問ch32v103如何使用全局中斷?

    在使用arm芯片時有叫做__disable_irq();和__enable_irq();的全局中斷方法,請問riscv里面要如何使用這種全局中斷?
    發表于 06-02 07:14

    STM32使用__disable_irq()后就無法使用HAL_Delay(xx),這是為什么?

    __enable_irq();//打開所有中斷但實際應用中發現,當使用__disable_irq(); 關閉所有中斷后,再用__enable_irq();打開所有中斷,就會出現HAL_Delay(xx)不能再使用,所以直接用上述
    發表于 12-03 09:09

    逐步認識中斷請求IRQ

    一、了解IRQ家族??IRQ全稱為Interrupt Request,即是“中斷請求”的意思(以下使用IRQ稱呼)。IRQ的作
    發表于 04-17 22:51 ?2321次閱讀

    Linux中斷(interrupt)子系統之一:驅動程序接口層和中斷通用邏輯層

    這兩個API應該配對使用,disable_irq可以被多次嵌套調用,要想重新打開irq,enable_irq必須也要被調用同樣的次數,為此,irq_desc結構中的depth字段專門用
    發表于 05-15 11:28 ?608次閱讀
    Linux中斷(interrupt)子系統之一:驅動程序接口層和中斷通用邏輯層

    6.分析request_irq和free_irq函數如何注冊注銷中斷(詳解)

    上一節講了如何實現運行中斷,這些都是系統給做好的,當我們想自己寫個中斷處理程序,去執行自己的代碼,就需要寫irq_desc->action->handler,然后通過
    發表于 11-30 18:36 ?13次下載
    6.分析request_<b class='flag-5'>irq</b>和free_<b class='flag-5'>irq</b><b class='flag-5'>函數</b>如何注冊注銷中斷(詳解)

    2.單片機flash操作注意事項

    (); //關閉中斷//////////////////////if(a) __disable_irq(); else __enable_irq();2.創建備份區降低擦寫時掉電數據丟失的風險...
    發表于 12-01 20:51 ?9次下載
    2.單片機flash操作注意事項

    控制IRQ和FIQ中斷的編譯器內部函數 - 基于Keil MDK

    編譯器內部函數__disable_irq、__enable_irq、__disable_fiq和__enable_fiq用于控制
    發表于 01-26 17:16 ?1次下載
    控制<b class='flag-5'>IRQ</b>和FIQ中斷的編譯器內部<b class='flag-5'>函數</b> - 基于Keil MDK

    IRQ domain支持幾種映射方式

    IRQ domain IRQ domain用于將硬件的中斷號,轉換成Linux系統中的中斷號(virtual irq, virq),來張圖: 每個中斷控制器都對應一個IRQ Domai
    的頭像 發表于 09-28 15:21 ?1066次閱讀
    <b class='flag-5'>IRQ</b> domain支持幾種映射方式
    主站蜘蛛池模板: 六月丁香婷婷激情国产 | 国产女主播在线播放一区二区 | 免费视频在线播放 | 色黄视频| 久久国产精品网 | 午夜免费观看 | 在线免费影视 | 黄在线视频 | 久久精品夜夜夜夜夜久久 | 亚洲国产高清精品线久久 | 午夜理伦片免费 | 国产三级视频 | 亚洲精品成人在线 | 亚洲国产成+人+综合 | 在线免费视频一区二区 | 久久天天躁夜夜躁狠狠85麻豆 | 人人干人人上 | 人人干人人搞 | 久久国产午夜精品理论篇小说 | zzji国产精品视频 | 亚洲地址一地址二地址三 | 亚洲大黑香蕉在线观看75 | 国语自产拍在线观看7m | 色免费在线观看 | 好爽毛片一区二区三区四区 | 午夜视频在线观看免费高清 | 日本午夜大片 | 成人黄色免费 | 丁香婷婷久久 | a亚洲| 91婷婷色涩涩 | 男人资源站 | 狠狠色综合色综合网络 | 午夜视频在线观看一区二区 | 高清国产下药迷倒美女 | 日本三级网址 | 久久午夜神器 | 在线a亚洲老鸭窝天堂新地址 | 大尺度视频在线 | 国产一级特黄高清免费大片 | 欧美一级日韩一级亚洲一级 |