From 585ca0c8291ab8658055b2eaba0c7ec2784c5d88 Mon Sep 17 00:00:00 2001 From: andreika-git Date: Sat, 25 Nov 2023 01:15:50 +0200 Subject: [PATCH] Initial support for watchdog --- firmware/controllers/engine_controller.cpp | 1 + firmware/controllers/flash_main.cpp | 7 ++++ firmware/hw_layer/ports/at32/at32_common.cpp | 3 ++ firmware/hw_layer/ports/cypress/mpu_util.cpp | 3 ++ firmware/hw_layer/ports/kinetis/mpu_util.cpp | 3 ++ firmware/hw_layer/ports/mpu_util.h | 5 +++ .../hw_layer/ports/stm32/stm32_common.cpp | 33 +++++++++++++++++++ 7 files changed, 55 insertions(+) diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp index d1508c336b..4cd01d96c3 100644 --- a/firmware/controllers/engine_controller.cpp +++ b/firmware/controllers/engine_controller.cpp @@ -224,6 +224,7 @@ static void doPeriodicSlowCallback() { } #endif // EFI_TCU + tryResetWatchdog(); } void initPeriodicEvents() { diff --git a/firmware/controllers/flash_main.cpp b/firmware/controllers/flash_main.cpp index 9aeb66ba94..381f762330 100644 --- a/firmware/controllers/flash_main.cpp +++ b/firmware/controllers/flash_main.cpp @@ -147,6 +147,10 @@ void writeToFlashNow() { persistentState.version = FLASH_DATA_VERSION; persistentState.crc = flashStateCrc(persistentState); + // there's no wdgStop() for STM32, so we cannot disable it. + // we just set a long timeout of 5 secs to wait until flash is done. + startWatchdog(5000); + #if EFI_STORAGE_MFS == TRUE mfs_error_t err; /* In case of MFS: @@ -173,6 +177,9 @@ void writeToFlashNow() { isSuccess = (result1 == FLASH_RETURN_SUCCESS) && (result2 == FLASH_RETURN_SUCCESS); #endif + // restart the watchdog with the default timeout + startWatchdog(); + if (isSuccess) { efiPrintf("FLASH_SUCCESS"); } else { diff --git a/firmware/hw_layer/ports/at32/at32_common.cpp b/firmware/hw_layer/ports/at32/at32_common.cpp index 576374bd48..2c2d802e60 100644 --- a/firmware/hw_layer/ports/at32/at32_common.cpp +++ b/firmware/hw_layer/ports/at32/at32_common.cpp @@ -131,6 +131,9 @@ BOR_Result_t BOR_Set(BOR_Level_t BORValue) { return BOR_Result_Ok; } +void resetWatchdog() { +} + void baseMCUInit(void) { // looks like this holds a random value on start? Let's set a nice clean zero DWT->CYCCNT = 0; diff --git a/firmware/hw_layer/ports/cypress/mpu_util.cpp b/firmware/hw_layer/ports/cypress/mpu_util.cpp index deabdc280a..9d8018e079 100644 --- a/firmware/hw_layer/ports/cypress/mpu_util.cpp +++ b/firmware/hw_layer/ports/cypress/mpu_util.cpp @@ -21,6 +21,9 @@ extern "C" { void HardFaultVector(void); } +void resetWatchdog() { +} + void baseMCUInit(void) { } diff --git a/firmware/hw_layer/ports/kinetis/mpu_util.cpp b/firmware/hw_layer/ports/kinetis/mpu_util.cpp index 939f843654..e098477002 100644 --- a/firmware/hw_layer/ports/kinetis/mpu_util.cpp +++ b/firmware/hw_layer/ports/kinetis/mpu_util.cpp @@ -13,6 +13,9 @@ #include "mpu_util.h" #include "flash_int.h" +void resetWatchdog() { +} + void baseMCUInit(void) { } diff --git a/firmware/hw_layer/ports/mpu_util.h b/firmware/hw_layer/ports/mpu_util.h index e0474f22c9..c724771295 100644 --- a/firmware/hw_layer/ports/mpu_util.h +++ b/firmware/hw_layer/ports/mpu_util.h @@ -15,6 +15,11 @@ void jump_to_openblt(); void causeHardFault(); bool allowFlashWhileRunning(); +// 300 ms is our default timeout (we use 'int' for compatibility with addConsoleActionI()) +void startWatchdog(int timeoutMs = 300); +void setWatchdogResetPeriod(int resetMs); +void tryResetWatchdog(); + bool ramReadProbe(volatile const char *read_address); #if defined(STM32F4) bool isStm32F42x(); diff --git a/firmware/hw_layer/ports/stm32/stm32_common.cpp b/firmware/hw_layer/ports/stm32/stm32_common.cpp index b1338af677..6b48a005ac 100644 --- a/firmware/hw_layer/ports/stm32/stm32_common.cpp +++ b/firmware/hw_layer/ports/stm32/stm32_common.cpp @@ -103,11 +103,44 @@ BOR_Result_t BOR_Set(BOR_Level_t BORValue) { return BOR_Result_Ok; } +void startWatchdog(int timeoutMs) { +#if HAL_USE_WDG + // RL is a 12-bit value so we use a "2 ms" prescaler to support long timeouts (> 4.095 sec) + static WDGConfig wdgcfg; + wdgcfg.pr = STM32_IWDG_PR_64; // t = (1/32768) * 64 = ~2 ms + wdgcfg.rlr = STM32_IWDG_RL((uint32_t)((32.768f / 64.0f) * timeoutMs)); + wdgStart(&WDGD1, &wdgcfg); +#endif // HAL_USE_WDG +} + +static efitimems_t watchdogResetPeriodMs = 0; + +void setWatchdogResetPeriod(int resetMs) { + watchdogResetPeriodMs = (efitimems_t)resetMs; +} + +void tryResetWatchdog() { +#if HAL_USE_WDG + static efitimems_t lastTimeWasResetMs = 0; + // check if it's time to reset the watchdog + efitimems_t curTimeResetMs = getTimeNowMs(); + if (curTimeResetMs >= lastTimeWasResetMs + watchdogResetPeriodMs) { + // we assume tryResetWatchdog() is called from a timer callback + wdgResetI(&WDGD1); + lastTimeWasResetMs = curTimeResetMs; + } +#endif // HAL_USE_WDG +} + void baseMCUInit(void) { // looks like this holds a random value on start? Let's set a nice clean zero DWT->CYCCNT = 0; BOR_Set(BOR_Level_1); // one step above default value + + // 200 ms is our default period for runMainLoop + setWatchdogResetPeriod(200); + startWatchdog(); } extern uint32_t __main_stack_base__;