吴忠躺衫网络科技有限公司

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

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

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

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

TopSemic嵌入式 ? 來(lái)源:TopSemic嵌入式 ? 2024-08-29 10:06 ? 次閱讀

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

wKgZombP18aAKIgJAACAC6ifUtA639.png

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

wKgaombP19iAKZCIAAAnqTdnJps986.png

可是如果直接去調(diào)用這倆函數(shù)的話,編譯又不會(huì)報(bào)錯(cuò),那么這倆函數(shù)的定義到底在哪呢?

__disable_irq() 和 __enable_irq() 是所謂的intrinsic函數(shù),編譯器自動(dòng)識(shí)別并替換為相關(guān)的指令,它們其實(shí)是編譯器的一部分,實(shí)際的定義位于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 這兩個(gè)指令。

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

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

id: interrupt disable. 中斷關(guān)閉,即PRIMASK.PM設(shè)置為1

3dd39db1f6db39a0cd121d329fe74de5.png

3dd39db1f6db39a0cd121d329fe74de5.png

__enable_irq()函數(shù)調(diào)用cpsie i指令。

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

需要注意的是:如果之前開(kāi)啟了相關(guān)外設(shè)的中斷功能,在調(diào)用__disable_irq()函數(shù)關(guān)中斷后,這時(shí)如果有中斷觸發(fā),那么不會(huì)去進(jìn)行中斷響應(yīng)。但是在調(diào)用__enable_irq()開(kāi)啟中斷后,MCU會(huì)立即處理之前觸發(fā)的中斷。這說(shuō)明__disable_irq()只是禁止CPU去響應(yīng)中斷,沒(méi)有真正的去屏蔽中斷的觸發(fā),當(dāng)中斷發(fā)生后,相應(yīng)的寄存器會(huì)將中斷標(biāo)志置位,在__enable_irq()開(kāi)啟中斷后,由于相應(yīng)的中斷標(biāo)志沒(méi)有清空,因而還會(huì)觸發(fā)中斷。

以下述代碼為例,程序中使用了一個(gè)GPIO中斷,當(dāng)按鍵按下時(shí)翻轉(zhuǎn)一次LED。實(shí)際測(cè)試如果在調(diào)用__disable_irq()后、__enable_irq()之前的這3s時(shí)間內(nèi)按下按鍵,并不會(huì)進(jìn)入中斷翻轉(zhuǎn)LED,雖然這時(shí)中斷標(biāo)志位已經(jīng)產(chǎn)生了。

e0ec29af41084f964c2f2593534e1382.png

但是調(diào)用__enable_irq()之后就會(huì)立刻進(jìn)入到中斷服務(wù)函數(shù)中。

intmain(void)
{
/*配置系統(tǒng)時(shí)鐘*/
system_clock_config();

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

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

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

__disable_irq();

std_delayms(3000);

__enable_irq();

while(1)
{

}
}

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

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

/**
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<

這倆函數(shù)和上述函數(shù)的區(qū)別是,上面的兩個(gè)函數(shù)是開(kāi)關(guān)全局的中斷,這倆函數(shù)是針對(duì)某特定的中斷。

但是有一點(diǎn)相同的是,如果在調(diào)用__NVIC_DisableIRQ之后發(fā)生了中斷事件,當(dāng)調(diào)用__NVIC_EnableIRQ(IRQn_Type IRQn)之后還是會(huì)進(jìn)入到中斷處理。

綜上disable函數(shù)只是不響應(yīng)中斷,并不會(huì)影響中斷的產(chǎn)生,在disable狀態(tài)下如果發(fā)生中斷則會(huì)掛起,等到enable后滿足條件還是會(huì)被執(zhí)行。如果不希望此現(xiàn)象發(fā)生,那么需要再enable前清除掉相關(guān)外設(shè)模塊中斷掛起請(qǐng)求標(biāo)志。

如果想真正禁止中斷的產(chǎn)生的話,還得從源頭上配置相關(guān)外設(shè)的寄存器關(guān)掉中斷才行。

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

    關(guān)注

    146

    文章

    17317

    瀏覽量

    352638
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5363

    瀏覽量

    121158
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4346

    瀏覽量

    62969
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1642

    瀏覽量

    49284

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

文章出處:【微信號(hào):TopSemic,微信公眾號(hào):TopSemic嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    cmsis_armcc.h沒(méi)有實(shí)現(xiàn)__disable_irq函數(shù)接口,還有別的函數(shù)嗎?

    cmsis_armcc.h沒(méi)有實(shí)現(xiàn)__disable_irq函數(shù)接口,還有別的函數(shù)嗎?除了__NVIC_DisableIRQ
    發(fā)表于 04-02 08:25

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

    如題,STM32F030C8T6 做 IAP 現(xiàn)能正確的從 bootloader 中跳轉(zhuǎn)到 APP,在APP中也能正常的進(jìn)入中斷,為什么在APP中使用 __disable_irq();無(wú)法關(guān)閉 所有中斷。 經(jīng)測(cè)試 在bootloader中__disable_irq();是
    發(fā)表于 04-22 08:21

    stm32f0讀寫內(nèi)部flash和刷新液晶屏?xí)r,禁止所有中斷,__disable_irq();不起作用,還會(huì)進(jìn)入中斷響應(yīng)函數(shù)為什么?

    讀寫內(nèi)部flash和刷新液晶屏?xí)r,禁止所有中斷,__disable_irq();不起作用,還會(huì)進(jìn)入中斷響應(yīng)函數(shù)
    發(fā)表于 05-09 06:41

    TC387中有__disable_interrupts()關(guān)閉所有中斷和打開(kāi)所有中斷的函數(shù)或宏嗎?

    TC387 芯片中有__disable_irq()和__enable_irq()關(guān)閉所有中斷和打開(kāi)所有中斷的函數(shù)或宏嗎,請(qǐng)告知
    發(fā)表于 08-01 08:22

    Nios PIO中斷---“implicit declaration of function 'alt_irq_register”警告

    使能中斷增強(qiáng)版的中斷API提供如下函數(shù):alt_ic_irq_disable(),alt_ic_irq_enable(),alt_ic_irq
    發(fā)表于 03-08 20:42

    stm32 Cortex M3內(nèi)核 ,CPU調(diào)用__disable_irq函數(shù)關(guān)閉中斷后,為何還能接收到中斷????????

    Cortex M3內(nèi)核 ,CPU調(diào)用__disable_irq函數(shù)關(guān)閉中斷后,進(jìn)入睡眠模式,并且調(diào)用__WFI()函數(shù),等待中斷,結(jié)果當(dāng)有外部中斷進(jìn)入時(shí),CPU喚醒。跪求大神指教這是什么原理,關(guān)閉中斷后,等待中斷,然后中斷來(lái)了,
    發(fā)表于 05-25 11:41

    請(qǐng)問(wèn)除了__disable_irq();__enable_irq()之外還有其他暫時(shí)屏蔽中斷嗎?

    我在設(shè)計(jì)中要利用__disable_irq();__enable_irq()來(lái)實(shí)現(xiàn)原子操作,防止中斷與正常運(yùn)行程序同時(shí)訪問(wèn)數(shù)據(jù)造成不一致,但是這個(gè)是暫時(shí)屏蔽全局中斷的。我系統(tǒng)中有個(gè)最高優(yōu)先級(jí)的是不能
    發(fā)表于 08-27 10:15

    設(shè)備樹(shù)中GIC中斷控制器節(jié)點(diǎn)

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

    請(qǐng)問(wèn)ch32v103如何使用全局中斷?

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

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

    __enable_irq();//打開(kāi)所有中斷但實(shí)際應(yīng)用中發(fā)現(xiàn),當(dāng)使用__disable_irq(); 關(guān)閉所有中斷后,再用__enable_irq();打開(kāi)所有中斷,就會(huì)出現(xiàn)HAL_Delay(xx)不能再使用,所以直接用上述
    發(fā)表于 12-03 09:09

    逐步認(rèn)識(shí)中斷請(qǐng)求IRQ

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

    Linux中斷(interrupt)子系統(tǒng)之一:驅(qū)動(dòng)程序接口層和中斷通用邏輯層

    這兩個(gè)API應(yīng)該配對(duì)使用,disable_irq可以被多次嵌套調(diào)用,要想重新打開(kāi)irqenable_irq必須也要被調(diào)用同樣的次數(shù),為此,irq_desc結(jié)構(gòu)中的depth字段專門用
    發(fā)表于 05-15 11:28 ?524次閱讀
    Linux中斷(interrupt)子系統(tǒng)之一:驅(qū)動(dòng)程序接口層和中斷通用邏輯層

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

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

    2.單片機(jī)flash操作注意事項(xiàng)

    (); //關(guān)閉中斷//////////////////////if(a) __disable_irq(); else __enable_irq();2.創(chuàng)建備份區(qū)降低擦寫時(shí)掉電數(shù)據(jù)丟失的風(fēng)險(xiǎn)...
    發(fā)表于 12-01 20:51 ?9次下載
    2.單片機(jī)flash操作注意事項(xiàng)

    控制IRQ和FIQ中斷的編譯器內(nèi)部函數(shù) - 基于Keil MDK

    編譯器內(nèi)部函數(shù)__disable_irq、__enable_irq、__disable_fiq和__enable_fiq用于控制
    發(fā)表于 01-26 17:16 ?1次下載
    控制<b class='flag-5'>IRQ</b>和FIQ中斷的編譯器內(nèi)部<b class='flag-5'>函數(shù)</b> - 基于Keil MDK
    百家乐官网加牌规则| 澳门百家乐鸿运| 大发真钱娱乐城| 保时捷百家乐娱乐城| 赌博百家乐官网的路单| 君怡百家乐的玩法技巧和规则 | 新锦江百家乐官网赌场娱乐网规则| 昆明百家乐装修装潢有限公司| 百家乐官网美女视频聊天| 方形百家乐筹码| 罗马百家乐官网的玩法技巧和规则| 188金宝博| 百家乐画哪个路单| 百家乐官网娱乐网会员注册| 网络赌博| 云鼎百家乐作弊| 游戏机百家乐官网的玩法技巧和规则| 澳门赌场黄金城| 精通百家乐的玩法技巧和规则| 百佬汇百家乐官网的玩法技巧和规则| 齐河县| 申烨太阳城三期| 新濠百家乐现金网| 查看百家乐官网赌博| 大发888手机版下载安装到手| 百家乐最新首存优惠| 百家乐官网澳门百家乐官网澳门赌场 | 百家乐官网手机游戏下载| 环球棋牌评测网| 百家乐门户网站| 鑫鑫百家乐官网的玩法技巧和规则| 百家乐官网单跳双跳| 大发888下载34| 百家乐网站赌博| 旧金山百家乐官网的玩法技巧和规则| 在线百家乐官网赌场| 大发888娱乐场下载yguard| 御金百家乐娱乐城| 海港城百家乐官网的玩法技巧和规则 | 樱桃木百家乐官网桌| 交口县|