标题:
一个跟STM32中断优先级有关的话题
[打印本页]
作者:
taoran
时间:
2016-6-17 01:38
标题:
一个跟STM32中断优先级有关的话题
近日有人咨询问题如下:
“我用
STM32F7
MCU
开发产品,用到
STemwin
。在桌面有一个图标,点击图标后创建一个窗口,窗口中
3
个按钮,和
1
个
listbox
。点击窗口中的
CANCEL
按钮窗口关闭。当我多次打开关闭这个窗口时,程序就会死!经调试,程序是死在了硬件
I2C
的
while
循环中,如下代码中:
static
HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t
Flag, FlagStatus Status, uint32_t Timeout)
{
uint32_t tickstart = HAL_GetTick();
/* Wait until flag is set */
if(Status == RESET)
{
while(__HAL_I2C_GET_FLAG(hi2c, Flag) ==
RESET)
{
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0)||((HAL_GetTick() -
tickstart ) > Timeout))
{
hi2c->State= HAL_I2C_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_TIMEOUT;
}
}
}
}...........
省略
或者
static
HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t
Timeout)
{
uint32_t tickstart = 0x00;
tickstart = HAL_GetTick();
if(__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) ==
SET)
{
/* Wait until STOP Flag is reset */
/* AutoEnd should be initiate after AF */
while(__HAL_I2C_GET_FLAG(hi2c,
I2C_FLAG_STOPF) == RESET)
{
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if((Timeout == 0)||((HAL_GetTick() -
tickstart ) > Timeout))
{
hi2c->State= HAL_I2C_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_TIMEOUT;
}
}
}...........
省略
该
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
系列,它们的中断优先级只有抢占优先级,不分响应优先级。
相关话题:
STM32
系列
MCU
芯片
开关
总
中断
的话题
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1