您現在的位置是:首頁 > 單機遊戲首頁單機遊戲

乾貨:手把手指導微控制器復位原因分析

簡介先看一下stm32中文參考手冊對RCC_CSR暫存器的描述:stm32對CSR暫存器各個位的宏封裝:* 公眾號:輕鬆學長 *  * Flags in the CSR register *#define RCC_FLAG_LSIRDY

脈衝延遲角是什麼意思

我是輕鬆學長,一個愛折騰的程式袁,仰望星空、腳踏實地,做一個有趣有料的技術人。

本節解決問題:軟體程式碼識別STM32復位原因,輔助程式碼除錯。

當STM32發生復位時,可能原因有上電覆位、掉電覆位、看門狗復位、軟體復位等多種,那怎麼判斷STM32復位的原因呢?且看輕鬆學長慢慢道來。

1、STM32 復位型別

STM32有三種復位:

系統復位

電源復位

後備域復位

1。1 系統復位

指除時鐘控制暫存器CSR中的復位標誌和備份區域中的暫存器外,將其他的所有暫存器復位為它們的復位數值。

系統復位可透過檢視RCC_CSR控制狀態暫存器中的復位狀態標誌位識別復位事件來源

,這就是今天的重點。

關於備份區域的理解可看下圖:

乾貨:手把手指導微控制器復位原因分析

有以下事件發生時,會產生一個系統復位:

軟體復位(SW復位)

低功耗管理復位

NRST引腳上的低電平(外部復位)

視窗看門狗計數終止(WWDG復位)

獨立看門狗計數終止(IWDG復位)

看門狗復位和外部復位好理解,那軟體復位和低功耗管理復位怎麼理解呢,何時會發生復位?

軟體復位

即透過將Cortex™-M3中斷應用和復位控制暫存器中的SYSRESETREQ位置’1’,實現軟體復位。STM32官方已經將軟體復位過程給封裝好了,即 NVIC_SystemReset() 函式,NVIC_SystemReset()函式的內容如下:

/* 公眾號:輕鬆學長 */  /**  \brief   System Reset  \details Initiates a system reset request to reset the MCU。 */__STATIC_INLINE void NVIC_SystemReset(void){  __DSB();                                                          /* Ensure all outstanding memory accesses included                                                                       buffered write are completed before reset */  SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |                           (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |                            SCB_AIRCR_SYSRESETREQ_Msk    );         /* Keep priority group unchanged */  __DSB();                                                          /* Ensure completion of memory access */  for(;;)                                                           /* wait until reset */  {    __NOP();  }}

使用軟體復位NVIC_SystemReset()函式時,需在該函式之前加上__set_FAULTMASK(1)語句,表示關閉所有中斷的意思;

因為在《Cortex-M3權威指南》中有這麼一句話提醒我們:從 SYSRESETREQ 被置為有效,到復位發生器執行復位令,往往會有一個延時。在此延時期間,處理器仍然可以響應中斷請求。但我們的本意往往是要讓此次執行到此為止,不要再做任何其它事情了。所以,最好在發出復位請求前,先把 FAULTMASK 置位,即關閉所有中斷。

低功耗管理復位

:在以下兩種情況下可產生低功耗管理復位:

1。在進入待機模式時產生低功耗管理復位:透過將使用者選擇位元組中的nRST_STDBY位置’1’將使能該復位。這時,即使執行了進入待機模式的過程,系統將被複位而不是進入待機模式。

2。在進入停止模式時產生低功耗管理復位:透過將使用者選擇位元組中的nRST_STOP位置’1’將使能該復位。這時,即使執行了進入停機模式的過程,系統將被複位而不是進入停機模式。

1。2 電源復位

電源復位將復位除了備份區域外的所有暫存器,當發生以下事件之一時,會產生電源復位:

上電/掉電覆位(POR/PDR復位)

從待機模式中返回

電源復位的復位源將最終作用於RESET引腳,並在復位過程中保持低電平。

晶片內部的復位訊號會在NRST引腳上輸出,脈衝發生器保證每一個(外部或內部)復位源都能有至少20μs的脈衝延時;當NRST引腳被拉低產生外部復位時,它將產生復位脈衝。

STM32晶片內部的復位電路如下圖所示:

乾貨:手把手指導微控制器復位原因分析

1。3 備份域復位

當以下事件發生之一時,會產生備份區域復位,備份區域復位隻影響備份區域。

軟體復位,備份區域復位可由設定備份域控制暫存器 (RCC_BDCR)中的BDRST位產生。

在VDD和VBAT兩者掉電的前提下,VDD或VBAT上電將引發備份區域復位。

2、軟體判斷復位原因

方法:透過檢視控制/狀態暫存器(RCC_CSR)中的復位狀態標誌位識別復位事件來源。

先看一下stm32中文參考手冊對RCC_CSR暫存器的描述:

乾貨:手把手指導微控制器復位原因分析

乾貨:手把手指導微控制器復位原因分析

stm32對CSR暫存器各個位的宏封裝:

/* 公眾號:輕鬆學長 */  /* Flags in the CSR register */#define RCC_FLAG_LSIRDY                  ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_LSIRDY)))   /*!< Internal Low Speed oscillator Ready */#define RCC_FLAG_LSECSS                  ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_LSECSSD)))  /*!< CSS on LSE failure Detection */#define RCC_FLAG_OBLRST                  ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_OBLRSTF)))  /*!< Options bytes loading reset flag */#define RCC_FLAG_PINRST                  ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_PINRSTF)))  /*!< PIN reset flag */#define RCC_FLAG_PORRST                  ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_PORRSTF)))  /*!< POR/PDR reset flag */#define RCC_FLAG_SFTRST                  ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_SFTRSTF)))  /*!< Software Reset flag */#define RCC_FLAG_IWDGRST                 ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_IWDGRSTF))) /*!< Independent Watchdog reset flag */#define RCC_FLAG_WWDGRST                 ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_WWDGRSTF))) /*!< Window watchdog reset flag */#define RCC_FLAG_LPWRRST                 ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_LPWRRSTF))) /*!< Low-Power reset flag */#define RCC_FLAG_LSERDY                  ((uint8_t)((CSR_REG_INDEX << 5U) | POSITION_VAL(RCC_CSR_LSERDY))) /*!< External Low Speed oscillator Ready */

stm32獲取復位標誌的宏:__HAL_RCC_GET_FLAG(FLAG)

/* 公眾號:輕鬆學長 */  /** @brief  Check RCC flag is set or not。  * @param  __FLAG__ specifies the flag to check。  *          This parameter can be one of the following values:  *            @arg @ref RCC_FLAG_HSIRDY HSI oscillator clock ready。  *            @arg @ref RCC_FLAG_MSIRDY MSI oscillator clock ready。  *            @arg @ref RCC_FLAG_HSERDY HSE oscillator clock ready。  *            @arg @ref RCC_FLAG_PLLRDY Main PLL clock ready。  *            @arg @ref RCC_FLAG_LSERDY LSE oscillator clock ready。  *            @arg @ref RCC_FLAG_LSECSS CSS on LSE failure Detection (*)  *            @arg @ref RCC_FLAG_LSIRDY LSI oscillator clock ready。  *            @arg @ref RCC_FLAG_OBLRST Option Byte Load reset  *            @arg @ref RCC_FLAG_PINRST  Pin reset。  *            @arg @ref RCC_FLAG_PORRST  POR/PDR reset。  *            @arg @ref RCC_FLAG_SFTRST  Software reset。  *            @arg @ref RCC_FLAG_IWDGRST Independent Watchdog reset。  *            @arg @ref RCC_FLAG_WWDGRST Window Watchdog reset。  *            @arg @ref RCC_FLAG_LPWRRST Low Power reset。  * @note (*) This bit is available in high and medium+ density devices only。  * @retval The new state of __FLAG__ (TRUE or FALSE)。  */#define __HAL_RCC_GET_FLAG(__FLAG__) (((((__FLAG__) >> 5U) == CR_REG_INDEX)? RCC->CR :RCC->CSR) & (1U << ((__FLAG__) & RCC_FLAG_MASK)))

stm32清除復位標誌的宏:__HAL_RCC_CLEAR_RESET_FLAGS()

/* 公眾號:輕鬆學長 */  /** @brief Set RMVF bit to clear the reset flags。  *         The reset flags are RCC_FLAG_PINRST, RCC_FLAG_PORRST, RCC_FLAG_SFTRST,  *         RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST, RCC_FLAG_LPWRRST  */#define __HAL_RCC_CLEAR_RESET_FLAGS() (RCC->CSR |= RCC_CSR_RMVF)

2。1 程式碼思路

看了對上面對控制/狀態暫存器(RCC_CSR)的描述,程式碼的思路就已經很明顯了,透過RCC_CSR暫存器中的復位狀態標誌位獲取復位事件來源,應用層做復位標誌位,最後清除復位標誌。

定義復位型別列舉

/* 公眾號:輕鬆學長 */  /* Reset Flag Status */typedef enum{ RCC_RESET_FLAG_NONE       = 0x00,       /*!< None Reset Flag    */ RCC_RESET_FLAG_IWDGRST    = 0x01,       /*!< Independent Watchdog Reset Flag */ RCC_RESET_FLAG_SFTRST     = 0x02,       /*!< Software Reset Flag    */ RCC_RESET_FLAG_PORRST     = 0x03,       /*!< POR/PDR Reset Flag    */ RCC_RESET_FLAG_PINRST     = 0x04,       /*!< PIN Reset Flag     */ RCC_RESET_FLAG_LPWRRST    = 0x05,       /*!< Low-Power Reset Flag   */ RCC_RESET_FLAG_OBLRST     = 0x06,       /*!< Options Bytes Loading Reset Flag */ RCC_RESET_FLAG_WWDGRST    = 0x07       /*!< Window Watchdog Reset Flag  */}RCC_RESET_FLAG_TypeDef;

獲取STM32復位型別

/* 公眾號:輕鬆學長 */  RCC_RESET_FLAG_TypeDef RCC_ResetFlag_GetStatus(void){ RCC_RESET_FLAG_TypeDef ResetStatusFlag = RCC_RESET_FLAG_NONE;  if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET)  {   ResetStatusFlag = RCC_RESET_FLAG_IWDGRST; } else if (__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST) != RESET)  {  ResetStatusFlag = RCC_RESET_FLAG_SFTRST; } else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET)  {  ResetStatusFlag = RCC_RESET_FLAG_PORRST; } else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET)  {  ResetStatusFlag = RCC_RESET_FLAG_PINRST; } else if (__HAL_RCC_GET_FLAG(RCC_FLAG_LPWRRST) != RESET)  {  ResetStatusFlag = RCC_RESET_FLAG_LPWRRST; } else if (__HAL_RCC_GET_FLAG(RCC_FLAG_OBLRST) != RESET)  {  ResetStatusFlag = RCC_RESET_FLAG_OBLRST; } else if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET) {  ResetStatusFlag = RCC_RESET_FLAG_WWDGRST; } __HAL_RCC_CLEAR_RESET_FLAGS();  return ResetStatusFlag;}

到這裡就結束啦,這只是應用在STM32微控制器上的復位型別判斷思路及案例。其他的微控制器一樣的思路,也可以實現同樣的問題,注意檢視其官方手冊對相應暫存器的描述即可。

任何晶片的官方手冊都是一筆寶藏,待你去挖掘。

Top