一、__disable_irq()与 __enable_irq()
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
static __INLINE void __enable_irq() { __ASM volatile ("cpsie i"); }
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
static __INLINE void __disable_irq() { __ASM volatile ("cpsid i"); }
__ASM代表后面为汇编语句,CPS为ARM封装的汇编操作语句规则如下链接:
__disable_irq()其实际效果为禁止CPU对中断产生响应,这里简单说明一下中断产生到进入中断的过程:
1.中断源使能的情况下,中断触发电平为高且保持了一段时间。(中断触发电平举例:大部分中断的IF)
2.置位相对应Pending位。
3.进入中断并自动清除对应Pending位。
4.若不手动清楚IF,会回到1处继续执行。
__disable_irq()即“cpsie i”指令,是屏蔽了CPU对Pending位的响应,因此当执行了__disable_irq()后,即使有Pending置位也不会进入中断,但是__disable_irq()不会禁止产生中断请求,即使用__disable_irq()后若在期间发生了中断,IF将会自动置位并再置位对应Pending,在运行__enable_irq()后将会直接按中断优先级运行中断服务子函数。
其与关闭IE的区别在于,关闭IE后,IF置位后不会产生Pending位,但若已经存在Pending位,关闭IE不能阻止本次进入中断。
因此当需要在主循环完整的关闭中断且在执行对应关闭语句后一次都不进入中断需要遵循如下顺序:
1.__disable_irq()
2.关闭中断可能存在的中断触发源等(若无跳过)
3.关闭中断IE
4.清IF
5.清对应的Pending位
6.__enable_irq()
打开中断建议操作顺序如下:
1.清IF标志
2.清对应Pending
3.打开芯片对应中断
举例一种错误关闭顺序造成的影响:
1.__disable_irq()
2.清IF
3.清Pending
4.关IE
5.__enable_irq()
造成结果如下,若操作步骤2后,IF置位,此时即使执行步骤3,Pending也会置位,从而在执行步骤5后进入一次本中断,这种情况在AD这些外设中较容易出现。
二、中断发生过程
中断发生细节参考以下文章: