__disable_irq() 和 __enable_irq()定義在哪?
共 9625字,需瀏覽 20分鐘
·
2024-07-23 17:21
點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)
static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))
__disable_irq(void) {
unsigned int cpsr;
#if __ARM_ARCH >= 6
#if defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
__asm__ __volatile__("mrs %[cpsr], primask\n"
"cpsid i\n"
: [cpsr] "=r"(cpsr));
return cpsr & 0x1;
#else /* !defined(__ARM_ARCH_PROFILE) || __ARM_ARCH_PROFILE != 'M' */
__asm__ __volatile__("mrs %[cpsr], cpsr\n"
"cpsid i\n"
: [cpsr] "=r"(cpsr));
return cpsr & 0x80;
#endif
#else /* __ARM_ARCH < 6 */
unsigned int tmp;
__asm__ __volatile__(
"mrs %[cpsr], CPSR\n"
"bic %[tmp], %[cpsr], #0x80\n"
"msr CPSR_c, %[tmp]\n"
: [tmp]"=r"(tmp), [cpsr]"=r"(cpsr));
return cpsr & 0x80;
#endif
}
#if (defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M' && \
__ARM_ARCH == 6) || __ARM_ARCH_8M_BASE__
static __inline__ void __attribute__((unavailable(
"intrinsic not supported for this architecture"))) __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__("cpsie f");
#else /* __ARM_ARCH < 6 */
unsigned int tmp;
__asm__ __volatile__(
"mrs %[tmp], CPSR\n"
"bic %[tmp], %[tmp], #0x40\n"
"msr CPSR_c, %[tmp]\n"
: [tmp]"=r"(tmp));
#endif
}
#endif
-
cps全稱change processor state,即改變PRIMASK這個(gè)寄存器值 -
ie: interrupt enable. 中斷使能,即PRIMASK.PM設(shè)置為0 id: interrupt disable. 中斷關(guān)閉,即PRIMASK.PM設(shè)置為1
__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)生了。
但是,調(diào)用__enable_irq()之后就會(huì)立刻進(jìn)入到中斷服務(wù)函數(shù)中。
int main(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)
{
}
}
/**
* @brief EXTI4_15中斷服務(wù)函數(shù)
* @retval 無(wú)
*/
void EXTI4_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ù)
/**
\brief Disable Interrupt
\details Disables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
__DSB();
__ISB();
}
}
/**
\brief Enable Interrupt
\details Enables a device specific interrupt in the NVIC interrupt controller.
\param [in] IRQn Device specific interrupt number.
\note IRQn must not be negative.
*/
__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0)
{
NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
}
}
這倆函數(shù)和上述函數(shù)的區(qū)別是,上面的兩個(gè)函數(shù)是開(kāi)關(guān)全局的中斷,這倆函數(shù)是針對(duì)某特定的中斷。
往 期 推 薦
1、Vue誕生10年,創(chuàng)始人尤雨溪推動(dòng)“銹化”——通過(guò)Rust提升Web基礎(chǔ)設(shè)施性能
2、上班摸魚(yú)?不可能!卡內(nèi)基梅隆準(zhǔn)博士生開(kāi)發(fā)一款 AI 程序:監(jiān)控電腦屏幕,一分心就吼你
3、Crowdstrike更新導(dǎo)致全球Windows大面積藍(lán)屏死機(jī)
4、Rust即將進(jìn)入前十:中贏、大贏、還是特大贏?
點(diǎn)分享
點(diǎn)收藏
點(diǎn)點(diǎn)贊
點(diǎn)在看
