zoukankan      html  css  js  c++  java
  • 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中

  • 相关阅读:
    Java Web
    Tomcat学习笔记
    Java Web学习笔记(2)
    Java Web学习笔记(1)
    2017-2018-1 Java演绎法 小组会议及交互汇总
    【Alpha版本】冲刺阶段
    【Alpha版本】冲刺阶段
    【Alpha版本】冲刺阶段
    【Alpha版本】冲刺阶段
    【Alpha版本】冲刺阶段
  • 原文地址:https://www.cnblogs.com/jieruishu/p/6396225.html
Copyright © 2011-2022 走看看