STM32开关总中断

引用 http://www.amobbs.com/forum.php?mod=viewthread&tid=5397451

在 STM32/Cortex-M3 中是通过改变 CPU 的当前优先级来允许或禁止中断。
   
PRIMASK 位:只允许 NMI 和 hard  fault 异常,其他中断/  异常都被屏蔽(当前 CPU 优先级=0)。
  
FAULTMASK 位:只允许 NMI,其他所有中断/异常都被屏蔽(当前 CPU 优先级=-1)。   

在 STM32 固件库中(stm32f10x_nvic.c 和 stm32f10x_nvic.h) 定义了四个函数操作 PRIMASK 位和

FAULTMASK 位,改变 CPU 的当前优先级,从而达到控制所有中断的目的。   

下面两个函数等效于关闭总中断:  
void NVIC_SETPRIMASK(void);   
void NVIC_SETFAULTMASK(void);
   

下面两个函数等效于开放总中断:  
void NVIC_RESETPRIMASK(void);   
void NVIC_RESETFAULTMASK(void);
   

上面两组函数要成对使用,不能交叉使用。  

例如:  

第一种方法:  
NVIC_SETPRIMASK();         //关闭总中断  
NVIC_RESETPRIMASK();       //开放总中断   

第二种方法:  
NVIC_SETFAULTMASK();      //关闭总中断  
NVIC_RESETFAULTMASK();    //开放总中断   

常常使用  

NVIC_SETPRIMASK();                       // Disable Interrupts  
NVIC_RESETPRIMASK();                     // Enable Interrupts

1 在CORE_CM3.H中根据不同编译器有不同的语句

#if defined ( __CC_ARM   ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */

#define __enable_fault_irq                __enable_fiq
#define __disable_fault_irq               __disable_fiq

#define __NOP                             __nop
#define __WFI                             __wfi

/*IAR ICC Compiler*/

__disable_irq() ;
__enable_irq() ;

/*IAR ICC Compiler*/

#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */

static __INLINE void __enable_irq()               { __ASM volatile ("cpsie i"); }

二 其它

__asm void INT_DIS(void)
{
  CPSID f
  BX r14 /*LR*/

}
/*************开启中断************************/
__asm void INT_EN(void)
{
  CPSIE f
  BX r14/*LR*/
}

cpsid i 关中断,但是不关硬fault 和NMI
cpsid f 连硬fault也关了,只剩下NMI/*MCU上电初始化读取参数期间尝试关闭ALL中断,所以用的F,读取参数完成后再开启中断,进入主程序不用再用F中断*/

MDK的话可以直接书写(好像不对这是对应IAR):
__disable_irq();  相当于 CPSID I
__enable_irq();   相当于 CPSIE I
__disable_fiq();  相当于 CPSID F
__enable_fiq();   相当于 CPSIE F

其实最正规的做法是用CMSIS库里面的(跨平台)
void __set_FAULTMASK(uint32_t faultMask);
void __set_PRIMASK(uint32_t priMask);

STM32在使用时有时需要禁用全局中断,比如MCU在升级过程中需禁用外部中断,防止升级过程中外部中断触发导致升级失败。
ARM MDK中提供了如下两个接口来禁用和开启总中断:
__disable_irq();   // 关闭总中断
__enable_irq();    // 开启总中断

测试发现这样一个问题,在关闭总中断后,如果有中断触发,虽然此时不会引发中断,但在调用__enable_irq()开启总中断后,MCU会立即处理之前触发的中断。这说明__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,中断发生后,相应的寄存器会将中断标志置位,在__enable_irq()开启中断后,由于相应的中断标志没有清空,因而还会触发中断。所以要想禁止所有中断,必须对逐个模块的中断进行Disable操作,由于每个模块中断源有很多,对逐个中断Disable的话比较复杂,较为简单的方法是通过XXX_ClearITPendingBit()清除中断标志或者直接通过XXX_DeInit()来清除寄存器的状态。这样在__enable_irq()开启总中断后,MCU就不会响应之前触发的中断了。

软件重启MCU与半主机调试
/* ##################################    Reset function  ############################################ */

/**
 * @brief  Initiate a system reset request.
 *
 * Initiate a system reset request to reset the MCU
 */
static __INLINE void NVIC_SystemReset(void)

/* ##################################### Debug In/Output function ########################################### */
static __INLINE void __disable_irq()              { __ASM volatile ("cpsid i"); }

static __INLINE void __enable_fault_irq()         { __ASM volatile ("cpsie f"); }
static __INLINE void __disable_fault_irq()        { __ASM volatile ("cpsid f"); }

在NVIC中

posted on 2017-02-14 09:33  杰瑞鼠  阅读(4933)  评论(0编辑  收藏  举报