STM32F103ZE单片机在WWDG窗口看门狗的EWI中断中喂狗导致系统复位的原因及解决办法(中断函数重入问题)
版權聲明:本文為博主原創文章,歡迎轉載?? ?https://blog.csdn.net/ZLK1214/article/details/78308058
程序開啟了WWDG的Early wakeup(EWI)中斷,在中斷中喂狗,但系統不停地復位。
HCLK=72MHz, PCLK1=4.5MHz, PCLK2=72MHz
程序如下:
#include <stdio.h>
#include <stm32f10x.h>
?
int fputc(int ch, FILE *fp)
{
?? ?if (fp == stdout)
?? ?{
?? ??? ?if (ch == '\n')
?? ??? ?{
?? ??? ??? ?while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
?? ??? ??? ?USART_SendData(USART1, '\r');
?? ??? ?}
?? ??? ?while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
?? ??? ?USART_SendData(USART1, ch);
?? ?}
?? ?return ch;
}
?
int main(void)
{
?? ?GPIO_InitTypeDef gpio;
?? ?USART_InitTypeDef usart;
?? ?
?? ?RCC_PCLK1Config(RCC_HCLK_Div16);
?? ?RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);?// 打開WWDG的時鐘后, 計數器就開始空轉
?? ?RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
?? ?
?? ?gpio.GPIO_Mode = GPIO_Mode_AF_PP;
?? ?gpio.GPIO_Pin = GPIO_Pin_9;
?? ?gpio.GPIO_Speed = GPIO_Speed_50MHz;
?? ?GPIO_Init(GPIOA, &gpio);
?? ?
?? ?USART_StructInit(&usart);
?? ?usart.USART_BaudRate = 115200;
?? ?usart.USART_Mode = USART_Mode_Tx;
?? ?USART_Init(USART1, &usart);
?? ?USART_Cmd(USART1, ENABLE);
?? ?
?? ?if (RCC_GetFlagStatus(RCC_FLAG_PINRST) == SET)
?? ??? ?printf("PIN reset!\n");
?? ?if (RCC_GetFlagStatus(RCC_FLAG_PORRST) == SET)
?? ??? ?printf("POR reset!\n");
?? ?if (RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET)
?? ??? ?printf("WWDG reset!\n");
?? ?RCC_ClearFlag();
?? ?
?? ?WWDG_Enable(94);?// 啟動看門狗并在沒有窗口值的情況下喂狗
?? ?WWDG_SetPrescaler(WWDG_Prescaler_8);
?? ?WWDG_SetWindowValue(74);?// 設置窗口值
?? ?WWDG_EnableIT();
?? ?NVIC_EnableIRQ(WWDG_IRQn);
?? ?
?? ?while (1);
}
?
void WWDG_IRQHandler(void)
{
?? ?WWDG_ClearFlag();
?? ?WWDG_SetCounter(94);
}
不過只要去掉RCC_PCLK1Config(RCC_HCLK_Div16)這句話,讓PCLK1回到默認的36MHz,系統就不再復位了。
于是配置DBGMCU_Config(DBGMCU_WWDG_STOP, ENABLE),設置調試時WWDG暫停。然后打開ST-Link調試,發現系統復位前WWDG_IRQHandler中斷函數連續執行了兩次,第一次執行時T=0x40,正常喂狗,緊接著又再次重入了中斷,T=0x5e,這個時候喂狗就引發了系統復位,因為此時計數值T>窗口值W。
問題的原因找到了,這是因為程序的執行速度(HCLK)太快,而中斷標志位EWIF的清除需要一定的時間(PCLK1),前者的速度是后者的16倍,雖然在中斷函數里面調用了清除中斷標志位的函數,但是到了中斷執行完畢后EWIF都還未來得及清除,所以中斷又再次重入了,第二次喂狗就引發了系統復位。
解決辦法就是,清除標志位后等待一下標志位真正清除,然后再喂狗,退出中斷。保證中斷只執行一次。
void WWDG_IRQHandler(void)
{
? WWDG_ClearFlag();
? while (WWDG_GetFlagStatus() == SET); // 等待中斷標志位真正清除, 防止中斷重入
? WWDG_SetCounter(94);
}
當HCLK=2*PCLK2時不需要等待,因為標志位的清除速度能夠跟得上中斷的執行速度。
程序一開始的時候就在RCC中打開了WWDG外設的時鐘,這時WDGA=0,窗口看門狗未啟用但處于空轉狀態,EWIF的置位規律如下:
T=127
T=126
T=125
...
T=66
T=65
T=64 *** EWIF置位, 手動清除標志位
T=63
...
T=2
T=1
T=0 *** EWIF置位, 手動清除標志位
T=127
T=126
...
T=66
T=65
T=64 *** EWIF置位, 手動清除標志位
T=63
...
在一個計數周期內EWIF會自動置位兩次。但在窗口看門狗啟動之前(WDGA=0),即使打開了EWI中斷,也不會進入中斷函數WWDG_IRQHandler執行。只有WDGA=1且EWIF=1時才會觸發中斷。
---------------------?
作者:巨大八爪魚?
來源:CSDN?
原文:https://blog.csdn.net/ZLK1214/article/details/78308058?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的STM32F103ZE单片机在WWDG窗口看门狗的EWI中断中喂狗导致系统复位的原因及解决办法(中断函数重入问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32之独立看门狗与窗口看门狗总结
- 下一篇: Linux Kernel 0.01 的编