STMCU小助手
发布时间:2022-1-28 19:04
|
在 STM32/Cortex-M3 中是通过改变 CPU 的当前优先级来允许或禁止中断。 PRIMASK 位:只允许 NMI 和 hard fault 异常,其他中断/ 异常都被屏蔽(当前 CPU 优先级=0)。9 Q: T- p% f, v FAULTMASK 位:只允许 NMI,其他所有中断/异常都被屏蔽(当前 CPU 优先级=-1)。 在 STM32 固件库中(stm32f10x_nvic.c 和 stm32f10x_nvic.h) 定义了四个函数操作 PRIMASK 位和 a; d |' O( y* T7 J# b5 Z FAULTMASK 位,改变 CPU 的当前优先级,从而达到控制所有中断的目的。 下面两个函数等效于关闭总中断: void NVIC_SETPRIMASK(void); void NVIC_SETFAULTMASK(void); & k- U& P+ K A, F& i# \4 [/ `. s5 ^ 下面两个函数等效于开放总中断: & m: l0 G0 q# ]* Q- s/ ] void NVIC_RESETPRIMASK(void); void NVIC_RESETFAULTMASK(void); 0 }" ^3 a; F" h, { 上面两组函数要成对使用,不能交叉使用。 7 c) `0 E4 P. O " r+ i" x* W; w: x" n% Z" u 例如: 第一种方法: NVIC_SETPRIMASK(); //关闭总中断 ) e+ ?, ]6 W5 Z' x8 q1 U0 E% o NVIC_RESETPRIMASK(); //开放总中断 第二种方法: 3 ]# l8 g2 u- E r5 k% G/ W4 V NVIC_SETFAULTMASK(); //关闭总中断 & G& _; P8 M, R NVIC_RESETFAULTMASK(); //开放总中断 常常使用 3 z) O. d" q% r " [' q$ l/ J% k# X, |. L% d" F NVIC_SETPRIMASK(); // Disable Interrupts - F3 d7 W2 v1 U2 g; J NVIC_RESETPRIMASK(); // Enable Interrupts 1 在CORE_CM3.H中根据不同编译器有不同的语句 #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ /* ARM armcc specific functions */* ~7 x; @; a- x: W, K3 A+ g/ m #define __enable_fault_irq __enable_fiq5 d+ z0 s2 ?& D #define __disable_fault_irq __disable_fiq 9 U: t& a- s( \9 W3 }4 f& o7 c #define __NOP __nop9 z& o5 [4 |8 p/ C" p8 w6 v) i #define __WFI __wfi /*IAR ICC Compiler*/ __disable_irq() ; __enable_irq() ; /*IAR ICC Compiler*/ #elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ /* GNU gcc specific functions */# O+ t. r5 p$ i, A9 B * t/ z% p& h# {8 l static __INLINE void __enable_irq() { __ASM volatile ("cpsie i"); } 二 其它 __asm void INT_DIS(void)" W6 {- z4 S Y1 g$ G, Y2 B( A { CPSID f BX r14 /*LR*/3 r* W) \+ V$ F$ d } /*************开启中断************************/ __asm void INT_EN(void). Y& S. L; y3 H0 h/ j { CPSIE f BX r14/*LR*/, N w4 k' a. v. \3 @ } cpsid i 关中断,但是不关硬fault 和NMI cpsid f 连硬fault也关了,只剩下NMI/*MCU上电初始化读取参数期间尝试关闭ALL中断,所以用的F,读取参数完成后再开启中断,进入主程序不用再用F中断*/ MDK的话可以直接书写(好像不对这是对应IAR): __disable_irq(); 相当于 CPSID I& H9 H& O$ s; Y+ L+ v, r __enable_irq(); 相当于 CPSIE I. h: l" [; d. T, v __disable_fiq(); 相当于 CPSID F3 H* @1 {- g0 O0 Y! _, {# E __enable_fiq(); 相当于 CPSIE F 其实最正规的做法是用CMSIS库里面的(跨平台)- L3 ^6 p& y( t0 }6 f. A void __set_FAULTMASK(uint32_t faultMask); void __set_PRIMASK(uint32_t priMask); STM32在使用时有时需要禁用全局中断,比如MCU在升级过程中需禁用外部中断,防止升级过程中外部中断触发导致升级失败。 ARM MDK中提供了如下两个接口来禁用和开启总中断:9 r: O' A% X8 w0 I2 P3 R3 t __disable_irq(); // 关闭总中断 __enable_irq(); // 开启总中断 测试发现这样一个问题,在关闭总中断后,如果有中断触发,虽然此时不会引发中断,但在调用__enable_irq()开启总中断后,MCU会立即处理之前触发的中断。这说明__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,中断发生后,相应的寄存器会将中断标志置位,在__enable_irq()开启中断后,由于相应的中断标志没有清空,因而还会触发中断。所以要想禁止所有中断,必须对逐个模块的中断进行Disable操作,由于每个模块中断源有很多,对逐个中断Disable的话比较复杂,较为简单的方法是通过XXX_ClearITPendingBit()清除中断标志或者直接通过XXX_DeInit()来清除寄存器的状态。这样在__enable_irq()开启总中断后,MCU就不会响应之前触发的中断了。 软件重启MCU与半主机调试0 \/ l# W9 s3 f- ] /* ################################## Reset function ############################################ */ /** * @brief Initiate a system reset request. *1 B6 \/ u9 L2 M9 }7 a# k * Initiate a system reset request to reset the MCU- _; m+ r y7 W0 W, G */2 B9 F+ M8 G, z |' a4 i5 D 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"); }& u r! r: A* x" | static __INLINE void __disable_fault_irq() { __ASM volatile ("cpsid f"); } 在NVIC中 2 |0 k+ Y% U' r1 l) [2 p |
实战经验 | 基于STM32G0B1的全桥移相+同步整流PWM解决方案
DMA 原理从 0 到 1:为什么它能解放 CPU?一文讲透 DMA 的工作流程
【福利三:逢7发帖赢大礼】8、基于STM32G070板子的Ymodem串口协议IAP Bootloader开发
【福利三:逢7发帖赢大礼】7、基于STM32G070板子TF卡的FATFS移植
【福利三:逢7发帖赢大礼】6、基于STM32G070板子spiflash的FATFS移植
【福利三:逢7发帖赢大礼】5、基于STM32G070板子IRDA红外遥控接收解码
【福利三:逢7发帖赢大礼】4、基于STM32G070板子SPI flash 移植SFUD库
【福利三:逢7发帖赢大礼】基于STM32G070板子的uart shell移植设计
【福利三:逢7发帖赢大礼】3、基于STM32G070板子的YModem串口协议通信
【福利三:逢7发帖赢大礼】2、基于STM32G070板子的OLED移植U8G2库
微信公众号
手机版