標題:
一個跟STM32中斷優(yōu)先級有關的話題
[打印本頁]
作者:
taoran
時間:
2016-6-17 01:38
標題:
一個跟STM32中斷優(yōu)先級有關的話題
近日有人咨詢問題如下:
“我用
STM32F7
MCU
開發(fā)產品,用到
STemwin
。在桌面有一個圖標,點擊圖標后創(chuàng)建一個窗口,窗口中
3
個按鈕,和
1
個
listbox
。點擊窗口中的
CANCEL
按鈕窗口關閉。當我多次打開關閉這個窗口時,程序就會死!經調試,程序是死在了硬件
I2C
的
while
循環(huán)中,如下代碼中:
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
中斷優(yōu)先級是
[
0,1
。
I2C
程序中超時檢測是用的
SYSTICK,
其中斷優(yōu)先級是
[
0x0f,0
(
第一個數字為搶占優(yōu)先級,第二個數字為響應優(yōu)先級
)。
調試發(fā)現,程序死掉后,
HAL_GetTick()
返回值始終不變,這樣才進入死循環(huán)!
懷疑是
systick
優(yōu)先級低,將其改為
[
0,0
最高優(yōu)先級后,依然會進入上面的死循環(huán)!”
很明顯,上面用戶代碼是基于
STM32cube
庫
實現的。根據上面用戶反饋的問題描述,他是說程序有時會死掉,而且總死在
I2C
通信代碼里。這個
I2C
通信代碼是通過
TIM3
的中斷調用的,其中
I2C
通信中的
TIMEOUT
超時檢測又是依據
SYSTICK
中斷計時實現。【注:用戶設計的合理性,這里暫且不談】
應該說用戶已經意識到問題的原因了。如果
SYSTICK
優(yōu)先級低于
TIM3
中斷優(yōu)先級,而
I2C
通信又是在
TIM3
中斷里執(zhí)行,那在
I2C
程序運行過程中
SYSTICK
中斷就沒法響應,無法進行
TICK
計數的加減。如果此時
I2C
通信出現故障,
TIMOUT
超時檢測條件就永遠不會成立。程序當然就卡死在那里面了。
后來用戶將
SYSTICK
的優(yōu)先級從之前的【
0x0f,0
】調整為【
0,0
】后現象仍未改善。他認為【
0,0
】是最高了。其實,此時
SYSTICK
的搶占優(yōu)先級與
TIM3
搶占優(yōu)先級是一樣的,只是二者響應優(yōu)先級不一樣。如果這樣的話,在
TIM3
中斷服務程序里,
SYSTICK
仍然無法響應中斷進行計數,也就無法通過
TIMEOUT
檢測退出死循環(huán)。
如果反過來,將
SYSTICK
的搶占優(yōu)先級設置得比
TIM3
的搶占優(yōu)先級高,情況就不同了。比方將
SYSTICK
的優(yōu)先級配置為【
0,0
】,
TIM3
的優(yōu)先級配置為【
1,0
】
。如果這樣,
TIM3
中斷里調用
I2C
通信程序,如果
I2C
通信出現故障,
TIMEOUT
超時檢測就不會受阻卡死。因為此時
SYSTICK
的搶占優(yōu)先級高于
TIM3
的
,
它可以打斷
TIM3
中斷程序進行
TICK
的計數計時,當
I2C
程序檢測到
TIMEOUT
成立時就可以全身而退了。后來建議用戶如此調整的確改善。
小結下,問題源于用戶對中斷優(yōu)先級的理解不到位。在
MCU
開發(fā)應用中因為中斷優(yōu)先級處理不當而導致困擾其實還挺多的,而且問題往往還比較隱蔽。
順便提醒下:對于
STM32F7/F4/F3/F1/L1/L4
系列芯片的中斷優(yōu)先級往往分為搶占優(yōu)先級和響應優(yōu)先級。只有搶占優(yōu)先級不同時才會發(fā)生中斷的打斷和嵌套。如果搶占優(yōu)先級一樣的話,在同時發(fā)生中斷事件時,響應優(yōu)先級高的中斷源優(yōu)先得到響應。如果搶占優(yōu)先級和響應優(yōu)先級也一樣,同時發(fā)生中斷時根據其中斷向量表的序號決定。
對于基于
CORTEX M0/M0+
的
STM32F0/L0
系列,它們的中斷優(yōu)先級只有搶占優(yōu)先級,不分響應優(yōu)先級。
相關話題:
STM32
系列
MCU
芯片
開關
總
中斷
的話題
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1