你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32开关总中断

[复制链接]
STMCU小助手 发布时间:2022-1-28 19:04
在 STM32/Cortex-M3 中是通过改变 CPU 的当前优先级来允许或禁止中断。
3 c: m, V6 I+ c# d- t   
$ o) B+ k9 ~* p1 [$ MPRIMASK 位:只允许 NMI 和 hard  fault 异常,其他中断/  异常都被屏蔽(当前 CPU 优先级=0)。9 Q: T- p% f, v
  
' A9 z1 g' n# }! B: y& t$ wFAULTMASK 位:只允许 NMI,其他所有中断/异常都被屏蔽(当前 CPU 优先级=-1)。   
* |# L8 M) S" e7 a8 R% h7 X
( s" e6 \! |6 k) _4 z# F- u在 STM32 固件库中(stm32f10x_nvic.c 和 stm32f10x_nvic.h) 定义了四个函数操作 PRIMASK 位和
, L2 c: M7 E7 V  a; d  |' O( y* T7 J# b5 Z
FAULTMASK 位,改变 CPU 的当前优先级,从而达到控制所有中断的目的。   
' q) [' H4 Y5 F
' u5 D. Y5 R% X: ~2 G# P8 j下面两个函数等效于关闭总中断:  
: Z! e. I% S% m9 G5 lvoid NVIC_SETPRIMASK(void);   
% k" A% i8 ~" z: Svoid NVIC_SETFAULTMASK(void);
8 [  [; s3 w0 U2 l  @# e   & k- U& P+ K  A, F& i# \4 [/ `. s5 ^

# R+ P& P3 Z4 R下面两个函数等效于开放总中断:  & m: l0 G0 q# ]* Q- s/ ]
void NVIC_RESETPRIMASK(void);   
& n6 |$ u( g& h/ `- \7 F: Avoid NVIC_RESETFAULTMASK(void);
$ c3 Q! J: r% b3 ?) N0 ?   
' T. x3 L6 v: S- l- {) G) q0 }" ^3 a; F" h, {
上面两组函数要成对使用,不能交叉使用。  7 c) `0 E4 P. O
" r+ i" x* W; w: x" n% Z" u
例如:  
1 q% g0 B7 I+ i+ ]$ g# o: Q
+ r7 t" e* e, A4 V$ d第一种方法:  
; P9 r' G! C7 D4 kNVIC_SETPRIMASK();         //关闭总中断  ) e+ ?, ]6 W5 Z' x8 q1 U0 E% o
NVIC_RESETPRIMASK();       //开放总中断   
* M8 `; j/ E( Y1 g4 m* J
- S3 Q* N, Q$ S) d) q; w/ |# y; o第二种方法:  3 ]# l8 g2 u- E  r5 k% G/ W4 V
NVIC_SETFAULTMASK();      //关闭总中断  & G& _; P8 M, R
NVIC_RESETFAULTMASK();    //开放总中断   
5 h0 }3 U. U$ v0 r/ d
  y7 f( D3 S" q& p. q# j- x/ j. X) j; E常常使用  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 -----------------*/
4 k" ~- j/ x- R* q6 T5 s( H/* ARM armcc specific functions */* ~7 x; @; a- x: W, K3 A+ g/ m

9 u' x) B* B1 d$ n3 }#define __enable_fault_irq                __enable_fiq5 d+ z0 s2 ?& D
#define __disable_fault_irq               __disable_fiq
* v9 ^8 M5 w% r9 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() ;
8 Q3 I. L0 l& A& \; }3 O7 h9 D1 {__enable_irq() ;
/*IAR ICC Compiler*/
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
8 i+ g* |7 b0 W/ e" j7 H/* 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
{
; r% ~1 ]1 ~/ e5 F& l  CPSID f
- y: |. m% H1 }8 x/ R( H' ^  BX r14 /*LR*/3 r* W) \+ V$ F$ d

5 v) D% x. ]5 F( c8 d}
, F4 X0 Z; H* h) ]! {8 E( p; i/*************开启中断************************/
, X) y  K# v% B/ _$ q# y__asm void INT_EN(void). Y& S. L; y3 H0 h/ j
{
. {- H) l9 H4 r. X# Z8 l* y  CPSIE f
5 {1 Z* B* S( w, E  BX r14/*LR*/, N  w4 k' a. v. \3 @
}
cpsid i 关中断,但是不关硬fault 和NMI
" l: X) p; \4 X3 ~/ Y! Scpsid f 连硬fault也关了,只剩下NMI/*MCU上电初始化读取参数期间尝试关闭ALL中断,所以用的F,读取参数完成后再开启中断,进入主程序不用再用F中断*/
MDK的话可以直接书写(好像不对这是对应IAR):
7 M) @' v% \: \- j* Q__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);
) t7 {6 B1 t# V' w, vvoid __set_PRIMASK(uint32_t priMask);
STM32在使用时有时需要禁用全局中断,比如MCU在升级过程中需禁用外部中断,防止升级过程中外部中断触发导致升级失败。
* I- H2 I8 t: s7 M( tARM MDK中提供了如下两个接口来禁用和开启总中断:9 r: O' A% X8 w0 I2 P3 R3 t
__disable_irq();   // 关闭总中断
6 J7 q* ^4 ^/ p( }. `4 ?2 k' k4 v__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  ############################################ */
9 N5 ?4 t, ~) y2 }3 Q) U! J
( M  W" ~2 X/ V2 o$ P* n/**
0 e# r& S0 U; w$ W1 l' N * @brief  Initiate a system reset request.
) e4 T$ {  `+ u% C) | *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 ########################################### */
+ Z' J. Z- I2 o& ?  v0 sstatic __INLINE void __disable_irq()              { __ASM volatile ("cpsid i"); }
+ e/ G8 |7 K/ i- c9 v; _* \
$ W8 s8 W% C4 Z, bstatic __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
赞 收藏 评论0 发布时间:2022-1-28 19:04

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版