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

一个跟STM32中断优先级有关的话题

[复制链接]
STMCU小助手 发布时间:2021-1-22 09:53
一个跟STM32中断优先级有关的话题
1.1.jpg
近日有人咨询问题如下:
“我用STM32F7 MCU开发产品,用到STemwin。在桌面有一个图标,点击图标后创建一个窗口,窗口中3个按钮,和1个listbox。点击窗口中的CANCEL按钮窗口关闭。当我多次打开关闭这个窗口时,程序就会死!经调试,程序是死在了硬件I2C的while循环中,如下代码中:
  1. static  e3 C4 S" w1 p; k
  2. HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t
    3 c% ~' b3 d5 v) u. G
  3. Flag, FlagStatus Status, uint32_t Timeout)
    " j) a1 p" V" D1 y
  4. {
    $ l/ o  ]1 N4 R7 E5 q" [
  5.   uint32_t tickstart = HAL_GetTick();0 d2 v0 ^. p7 S9 v- \8 x4 h
  6.     /* Wait until flag is set */
    , y5 l+ g. k4 i* q) Q
  7.   if(Status == RESET)
    9 |4 t5 c# y0 q- v0 Z
  8.   {     i' h! T) Z% z1 r: _
  9.     while(__HAL_I2C_GET_FLAG(hi2c, Flag) ==2 ^7 x5 Y6 ^7 W! e
  10. RESET)
    % ?! M: z9 m) c6 t# U+ F
  11.     {% i+ u  ?9 F: e) y" f" Q0 Y
  12.       /* Check for the Timeout */
    4 l, z6 P, r6 N! F& ^9 Q6 O$ h- q
  13.       if(Timeout != HAL_MAX_DELAY)
    6 D5 x( Q- F9 w/ T
  14.       {6 q& R: T* }6 T$ Q) Z
  15.         if((Timeout == 0)||((HAL_GetTick() -) x; Z! C! O! z
  16. tickstart ) > Timeout))
    * J+ k: X0 X$ j9 y
  17.         {
    7 o$ s! M! H6 [: _' |6 D
  18.           hi2c->State= HAL_I2C_STATE_READY;5 s. q4 s. a6 p# d6 I
  19.           /* Process Unlocked */5 p/ c) ^* j' u/ ~
  20.           __HAL_UNLOCK(hi2c);/ b7 ]3 z% |, G) X( x% ]
  21.           return HAL_TIMEOUT;
    " [3 M6 R; z+ G' v
  22.         }: F/ I: T! g9 K1 R3 A8 P! I5 x
  23.       }
    1 y  |# W$ @( U1 [. e. y0 f
  24.     }
    ; g/ i( j, U7 |' @
  25.   }...........省略
复制代码
, b4 E% r$ ~5 ]6 E
或者
  1. static* w/ h3 l1 q' Q  @' i9 c
  2. HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t& f/ D* a, C* i; D2 C$ e' i) |  u2 s
  3. Timeout)1 ~; t" R. e- `' Z& I( N; T
  4. {  j; ?0 g& H* C' k. b6 ]" b
  5.   uint32_t tickstart = 0x00;/ T+ I! B, K# \* Z" M. S, K: a
  6.   tickstart = HAL_GetTick();
    * [$ `2 R% t1 b% L  @) d

  7. 0 {( P2 K6 N' d- C
  8.   if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) ==
    / e# g: d. O: L1 ]7 _
  9. SET)
    3 ]( a2 i% S8 p2 d1 G/ `
  10.   {" K+ ~2 H5 `) y* r. K$ I! h: F
  11.     /* Wait until STOP Flag is reset */: I- v* [& d3 v' @
  12.     /* AutoEnd should be initiate after AF */3 g3 T0 R4 z+ ]& ~3 `
  13.     while(__HAL_I2C_GET_FLAG(hi2c,- K( A. q( e0 p. n2 a1 E7 _+ {/ a
  14. I2C_FLAG_STOPF) == RESET)
    ) Y+ K4 Z  f4 a3 `3 |
  15.     {
    7 F- O) k  W; o1 U5 M" l8 q7 j# f
  16.       /* Check for the Timeout */
    $ r1 H- p& a3 i- O9 Q" \7 U0 f
  17.       if(Timeout != HAL_MAX_DELAY)' c/ J$ f' e8 B+ D4 }/ }
  18.       {
    ; D$ l/ V3 U2 x% U$ O4 s1 U, ?
  19.         if((Timeout == 0)||((HAL_GetTick() -% D, ?7 r2 Z$ `6 [9 [" F8 [7 q$ J* n
  20. tickstart ) > Timeout))
    ( M3 [7 Q! B4 O# [& i. ~, h
  21.         {
    # _! _' ^0 n; Y5 x! o
  22.           hi2c->State= HAL_I2C_STATE_READY;
    9 g) X; `- Z& A/ d/ ]5 M
  23.           /* Process Unlocked */
    3 A1 }" l0 a2 q. C4 X- c4 T( e
  24.           __HAL_UNLOCK(hi2c);
    / a; E: L  q3 F: c8 h
  25.           return HAL_TIMEOUT;
    5 m5 k& F5 ^3 Y8 ?
  26.         }7 ]2 K$ j! [1 v! `5 |' C; m9 w
  27.       }8 r' Z8 ?  H2 C  t5 H
  28.     }...........省略
复制代码
3 n8 I/ l2 r- h8 m
该I2C程序是操作电阻触摸屏芯片的,由TIMER3定时器定时调用它。timer3中断优先级是[0,1]。I2C程序中超时检测是用的SYSTICK,其中断优先级是[0x0f,0](第一个数字为抢占优先级,第二个数字为响应优先级)。
调试发现,程序死掉后,HAL_GetTick() 返回值始终不变,这样才进入死循环!
怀疑是systick优先级低,将其改为[0,0]最高优先级后,依然会进入上面的死循环!”
很明显,上面用户代码是基于STM32cube库实现的。根据上面用户反馈的问题描述,他是说程序有时会死掉,而且总死在I2C通信代码里。这个I2C通信代码是通过TIM3的中断调用的,其中I2C通信中的TIMEOUT超时检测又是依据SYSTICK中断计时实现。【注:用户设计的合理性,这里暂且不谈】
应该说用户已经意识到问题的原因了。如果SYSTICK优先级低于TIM3中断优先级,而I2C通信又是在TIM3中断里执行,那在I2C程序运行过程中SYSTICK中断就没法响应,无法进行TICK计数的加减。如果此时I2C通信出现故障,TIMOUT超时检测条件就永远不会成立。程序当然就卡死在那里面了。
后来用户将SYSTICK的优先级从之前的【0x0f,0】调整为【0,0】后现象仍未改善。他认为【0,0】是最高了。其实,此时SYSTICK的抢占优先级与TIM3抢占优先级是一样的,只是二者响应优先级不一样。如果这样的话,在TIM3 中断服务程序里,SYSTICK仍然无法响应中断进行计数,也就无法通过TIMEOUT检测退出死循环。
如果反过来,将SYSTICK的抢占优先级设置得比TIM3的抢占优先级高,情况就不同了。比方将SYSTICK的优先级配置为【0,0】,TIM3的优先级配置为【1,0】。如果这样,TIM3中断里调用I2C通信程序,如果I2C通信出现故障,TIMEOUT超时检测就不会受阻卡死。因为此时SYSTICK的抢占优先级高于TIM3的,它可以打断TIM3中断程序进行TICK的计数计时,当I2C程序检测到TIMEOUT成立时就可以全身而退了。后来建议用户如此调整的确改善。
小结下,问题源于用户对中断优先级的理解不到位。在MCU开发应用中因为中断优先级处理不当而导致困扰其实还挺多的,而且问题往往还比较隐蔽。
顺便提醒下:对于STM32F7/F4/F3/F1/L1/L4系列芯片的中断优先级往往分为抢占优先级和响应优先级。只有抢占优先级不同时才会发生中断的打断和嵌套。如果抢占优先级一样的话,在同时发生中断事件时,响应优先级高的中断源优先得到响应。如果抢占优先级和响应优先级也一样,同时发生中断时根据其中断向量表的序号决定。
对于基于CORTEX M0/M0+的STM32F0/L0系列,它们的中断优先级只有抢占优先级,不分响应优先级。
文章出处: 茶话MCU
" b" z2 F$ t5 m7 Z+ ^
赞 收藏 评论0 发布时间:2021-1-22 09:53

举报

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