您現在的位置是:首頁 > 單機遊戲首頁單機遊戲
乾貨:手把手指導微控制器復位原因分析
- 2021-12-28
脈衝延遲角是什麼意思
我是輕鬆學長,一個愛折騰的程式袁,仰望星空、腳踏實地,做一個有趣有料的技術人。
本節解決問題:軟體程式碼識別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微控制器上的復位型別判斷思路及案例。其他的微控制器一樣的思路,也可以實現同樣的問題,注意檢視其官方手冊對相應暫存器的描述即可。
任何晶片的官方手冊都是一筆寶藏,待你去挖掘。