diff --git a/stm-firmware/include/reflow-controller/safety/watchdog.h b/stm-firmware/include/reflow-controller/safety/watchdog.h index 021b838..6d283cd 100644 --- a/stm-firmware/include/reflow-controller/safety/watchdog.h +++ b/stm-firmware/include/reflow-controller/safety/watchdog.h @@ -40,11 +40,4 @@ int watchdog_setup(uint8_t prescaler); */ int watchdog_ack(uint32_t magic); -/** - * @brief Check if reset was generated by the watchdog. - * @note This also clears the relevant flag, so the function will return false when called a second time - * @return true, if reset was generated by the watchdog - */ -bool watchdog_check_reset_source(void); - #endif /* __WATCHDOG_H__ */ diff --git a/stm-firmware/include/stm-periph/rcc-manager.h b/stm-firmware/include/stm-periph/rcc-manager.h index 71ddbd6..e67c7de 100644 --- a/stm-firmware/include/stm-periph/rcc-manager.h +++ b/stm-firmware/include/stm-periph/rcc-manager.h @@ -23,6 +23,7 @@ #include #include +#include /** * @brief The RCC Enable Manager uses static memory with a fixed maximum @@ -35,6 +36,19 @@ #error "RCC Enable Manager not yet implemented with dynamic memory" #endif +/** + * @brief The source/cause of a system reset. The values can be or'ed together as multiple flags may be possible at the same time. + */ +enum rcc_reset_source { + RCC_RESET_SOURCE_LOW_POWER = (1<<0), /**< @brief System reset caused by low power reset */ + RCC_RESET_SOURCE_SOFTWARE = (1<<1), /**< @brief System reset caused by software */ + RCC_RESET_SOURCE_WWD = (1<<2), /**< @brief System reset caused by window watchdog */ + RCC_RESET_SOURCE_IWDG = (1<<3), /**< @brief System reset caused by independent watchdog */ + RCC_RESET_SOURCE_POWER_ON = (1<<4), /**< @brief System reset caused by power on reset (POR) */ + RCC_RESET_SOURCE_PIN = (1<<5), /**< @brief System reset caused by NRST pin */ + RCC_RESET_BOR_POR = (1<<6), /**< @brief System reset caused by eitehr brown out or POR */ +}; + /** * @brief Enable Clock for peripheral by setting the corresponding bit (@p bit_no) to one * @@ -64,4 +78,11 @@ int rcc_manager_enable_clock(volatile uint32_t *rcc_enable_register, uint8_t bit */ int rcc_manager_disable_clock(volatile uint32_t *rcc_enable_register, uint8_t bit_no); +/** + * @brief Get the causes of the last system reset. + * @param clear_flags Clear the reset cause + * @return Reset cause + */ +enum rcc_reset_source rcc_manager_get_reset_cause(bool clear_flags); + #endif /* __RCC_MANAGER_H__ */ diff --git a/stm-firmware/safety/safety-controller.c b/stm-firmware/safety/safety-controller.c index 0d7f60b..49a4ec2 100644 --- a/stm-firmware/safety/safety-controller.c +++ b/stm-firmware/safety/safety-controller.c @@ -39,6 +39,7 @@ #include #include #include +#include #define check_flag_persistent(flag) ((flag)->persistency && (flag)->persistency->persistency) #define get_flag_weight(flag) ((flag)->weight ? (flag->weight->weight) : SAFETY_FLAG_CONFIG_WEIGHT_NONE) @@ -513,7 +514,7 @@ void safety_controller_init() safety_adc_init(); watchdog_setup(WATCHDOG_PRESCALER); - if (watchdog_check_reset_source()) + if (rcc_manager_get_reset_cause(false) & RCC_RESET_SOURCE_IWDG) safety_controller_report_error(ERR_FLAG_WTCHDG_FIRED); #ifdef DEBUGBUILD diff --git a/stm-firmware/safety/watchdog.c b/stm-firmware/safety/watchdog.c index f9e4ed8..15d3554 100644 --- a/stm-firmware/safety/watchdog.c +++ b/stm-firmware/safety/watchdog.c @@ -105,16 +105,4 @@ int watchdog_ack(uint32_t magic) return ret; } -bool watchdog_check_reset_source(void) -{ - bool ret; - - ret = !!(RCC->CSR & RCC_CSR_WDGRSTF); - - if (ret) - RCC->CSR |= RCC_CSR_RMVF; - - return ret; -} - /** @} */ diff --git a/stm-firmware/stm-periph/rcc-manager.c b/stm-firmware/stm-periph/rcc-manager.c index 68f8c8b..f98f5cb 100644 --- a/stm-firmware/stm-periph/rcc-manager.c +++ b/stm-firmware/stm-periph/rcc-manager.c @@ -21,6 +21,7 @@ #include #include #include +#include struct rcc_enable_count { volatile uint32_t *rcc_reg_addr; @@ -153,3 +154,30 @@ int rcc_manager_disable_clock(volatile uint32_t *rcc_enable_register, uint8_t bi return ret_val; } + +enum rcc_reset_source rcc_manager_get_reset_cause(bool clear_flags) +{ + enum rcc_reset_source ret = 0; + uint32_t rcc_csr; + + rcc_csr = RCC->CSR; + if (rcc_csr & RCC_CSR_LPWRRSTF) + ret |= RCC_RESET_SOURCE_LOW_POWER; + if (rcc_csr & RCC_CSR_WWDGRSTF) + ret |= RCC_RESET_SOURCE_WWD; + if (rcc_csr & RCC_CSR_WDGRSTF) + ret |= RCC_RESET_SOURCE_IWDG; + if (rcc_csr & RCC_CSR_SFTRSTF) + ret |= RCC_RESET_SOURCE_SOFTWARE; + if (rcc_csr & RCC_CSR_PORRSTF) + ret |= RCC_RESET_SOURCE_POWER_ON; + if (rcc_csr & RCC_CSR_PADRSTF) + ret |= RCC_RESET_SOURCE_PIN; + if (rcc_csr & RCC_CSR_BORRSTF) + ret |= RCC_RESET_BOR_POR; + + if (clear_flags) + RCC->CSR |= RCC_CSR_RMVF; + + return ret; +}