|
| 1 | +//! @file |
| 2 | +//! |
| 3 | +//! Copyright (c) Memfault, Inc. |
| 4 | +//! See License.txt for details |
| 5 | +//! |
| 6 | +//! A port for recovering reset reason information by reading the "Reset and |
| 7 | +//! Clock Control" (RCC)'s "Control & Status Register" (CSR). |
| 8 | +//! |
| 9 | +//! More details can be found in the "RCC clock control & status register |
| 10 | +//! (RCC_CSR)" section of the STM32F7 family reference manual. |
| 11 | + |
| 12 | +#include "memfault/components.h" |
| 13 | +#include "stm32f769xx.h" |
| 14 | +#include "stm32f7xx_hal.h" |
| 15 | + |
| 16 | +#if MEMFAULT_ENABLE_REBOOT_DIAG_DUMP |
| 17 | +#define MEMFAULT_PRINT_RESET_INFO(...) MEMFAULT_LOG_INFO(__VA_ARGS__) |
| 18 | +#else |
| 19 | +#define MEMFAULT_PRINT_RESET_INFO(...) |
| 20 | +#endif |
| 21 | + |
| 22 | +//! Mappings come from "5.3.21 RCC clock control & status register (RCC_CSR)" of |
| 23 | +//! the ST "RM0410" Reference Manual for (STM32F76xxx and STM32F77xxx). |
| 24 | +typedef enum ResetSource { |
| 25 | + kResetSource_PwrPor = (RCC_CSR_PORRSTF_Msk), |
| 26 | + kResetSource_Pin = (RCC_CSR_PINRSTF_Msk), |
| 27 | + kResetSource_PwrBor = (RCC_CSR_BORRSTF_Msk), |
| 28 | + kResetSource_Software = (RCC_CSR_SFTRSTF_Msk), |
| 29 | + kResetSource_Wwdg = (RCC_CSR_WWDGRSTF_Msk), |
| 30 | + kResetSource_Iwdg = (RCC_CSR_IWDGRSTF_Msk), |
| 31 | + kResetSource_LowPwr = (RCC_CSR_LPWRRSTF_Msk), |
| 32 | +} eResetSource; |
| 33 | + |
| 34 | +void memfault_reboot_reason_get(sResetBootupInfo *info) { |
| 35 | + const uint32_t reset_cause = RCC->CSR; |
| 36 | + |
| 37 | + eMemfaultRebootReason reset_reason = kMfltRebootReason_Unknown; |
| 38 | + |
| 39 | + MEMFAULT_PRINT_RESET_INFO("Reset Reason, RCC_CSR=0x%" PRIx32, reset_cause); |
| 40 | + MEMFAULT_PRINT_RESET_INFO("Reset Causes: "); |
| 41 | + |
| 42 | + const uint32_t reset_mask_all = |
| 43 | + (RCC_CSR_BORRSTF_Msk | RCC_CSR_PINRSTF_Msk | RCC_CSR_PORRSTF_Msk | RCC_CSR_SFTRSTF_Msk | |
| 44 | + RCC_CSR_IWDGRSTF_Msk | RCC_CSR_WWDGRSTF_Msk | RCC_CSR_LPWRRSTF_Msk); |
| 45 | + |
| 46 | + switch (reset_cause & reset_mask_all) { |
| 47 | + case kResetSource_PwrPor: |
| 48 | + MEMFAULT_PRINT_RESET_INFO(" Power on Reset"); |
| 49 | + reset_reason = kMfltRebootReason_PowerOnReset; |
| 50 | + break; |
| 51 | + case kResetSource_Pin: |
| 52 | + MEMFAULT_PRINT_RESET_INFO(" Pin Reset"); |
| 53 | + reset_reason = kMfltRebootReason_PinReset; |
| 54 | + break; |
| 55 | + case kResetSource_PwrBor: |
| 56 | + MEMFAULT_PRINT_RESET_INFO(" Brown out"); |
| 57 | + reset_reason = kMfltRebootReason_BrownOutReset; |
| 58 | + break; |
| 59 | + case kResetSource_Software: |
| 60 | + MEMFAULT_PRINT_RESET_INFO(" Software"); |
| 61 | + reset_reason = kMfltRebootReason_SoftwareReset; |
| 62 | + break; |
| 63 | + case kResetSource_Wwdg: |
| 64 | + MEMFAULT_PRINT_RESET_INFO(" Window Watchdog"); |
| 65 | + reset_reason = kMfltRebootReason_HardwareWatchdog; |
| 66 | + break; |
| 67 | + case kResetSource_Iwdg: |
| 68 | + MEMFAULT_PRINT_RESET_INFO(" Independent Watchdog"); |
| 69 | + reset_reason = kMfltRebootReason_HardwareWatchdog; |
| 70 | + break; |
| 71 | + case kResetSource_LowPwr: |
| 72 | + MEMFAULT_PRINT_RESET_INFO(" Low power management"); |
| 73 | + reset_reason = kMfltRebootReason_LowPower; |
| 74 | + break; |
| 75 | + default: |
| 76 | + MEMFAULT_PRINT_RESET_INFO(" Unknown"); |
| 77 | + break; |
| 78 | + } |
| 79 | + |
| 80 | +#if MEMFAULT_REBOOT_REASON_CLEAR |
| 81 | + // we have read the reset information so clear the bits (since they are sticky across reboots) |
| 82 | + __HAL_RCC_CLEAR_RESET_FLAGS(); |
| 83 | +#endif |
| 84 | + |
| 85 | + *info = (sResetBootupInfo){ |
| 86 | + .reset_reason_reg = reset_cause, |
| 87 | + .reset_reason = reset_reason, |
| 88 | + }; |
| 89 | +} |
0 commit comments