summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorPatryk Duda <pdk@semihalf.com>2021-05-21 13:23:19 +0200
committerCommit Bot <commit-bot@chromium.org>2021-05-26 20:04:01 +0000
commit3ca879a81c455531b438fc5186ac54694f733ab5 (patch)
treee5c9a9f972861257eea658b78568f250d23a1d7d /chip
parent59c47366fe3832bbbbc098948f4073fdd8fe438a (diff)
downloadchrome-ec-3ca879a81c455531b438fc5186ac54694f733ab5.tar.gz
stm32/system: Wait for RVU bit clear before updating IWDG_RLR
EC is not waiting for IWDG_RLR value to be updated in watchdog_init() function. It's intended behaviour because updating value can take much time (even 48ms) which is not desired during initialization. It's also allowed by documentation too: RM0433 Rev 7 Section 45.4.4 Page 1920 https://www.st.com/resource/en/reference_manual/dm00314099.pdf If several reload, prescaler, or window values are used by the application, it is mandatory to wait until RVU bit is reset before changing the reload value, to wait until PVU bit is reset before changing the prescaler value, and to wait until WVU bit is reset before changing the window value. However, after updating the prescaler and/or the reload/window value it is not necessary to wait until RVU or PVU or WVU is reset before continuing code execution except in case of low-power mode entry. Documentation clearly states that before next Reload Register update we are obligated to wait until RVU bit in IWDG_SR register is cleared. Setting IWDG_RLR register when RVU bit is set causes new value to be ignored. This is exactly the behaviour observed while running flash_write_protect hardware unit test. Time of Step 2 execution is short enough to perform hard reboot (all reboots between test steps are hard) when RVU bit is set. As a result setting IWDG_RLR to 1 is ignored and watchdog is reloaded with old value. This is why it takes very long to perform hard reset and watchdog trace is printed. Platforms affected by this change: STM32H7: nocturne_fp (dartmonkey) nucleo-h743zi STM32F4: hatch_fp (bloonchipper) nucleo-f411re nucleo-f412zg polyberry sweetberry stm32f446e-eval BUG=b:170432597 BRANCH=none TEST=Run flash_write_protect hardware unit test on icetower board using `./test/run_device_tests.py --board dartmonkey \ --tests flash_write_protect` Make sure that test passes and no watchdog traces appear. TEST=Run flash_write_protect hardware unit test on dragonclaw 0.2 board using `./test/run_device_tests.py --board bloonchipper \ --tests flash_write_protect` Make sure that test passes and no watchdog traces appear. Signed-off-by: Patryk Duda <pdk@semihalf.com> Change-Id: I2585dcbf3cb1a14107c7ae674c51999f082e3df7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2917115 Reviewed-by: Craig Hesling <hesling@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/stm32/system.c21
-rw-r--r--chip/stm32/watchdog.c24
2 files changed, 44 insertions, 1 deletions
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index 42525deb48..8367ae2a12 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -435,6 +435,23 @@ void system_reset(int flags)
*/
/*
+ * RM0433 Rev 7
+ * Section 45.4.4 Page 1920
+ * https://www.st.com/resource/en/reference_manual/dm00314099.pdf
+ * If several reload, prescaler, or window values are used by
+ * the application, it is mandatory to wait until RVU bit is
+ * reset before changing the reload value, to wait until PVU bit
+ * is reset before changing the prescaler value, and to wait
+ * until WVU bit is reset before changing the window value.
+ *
+ * Here we should wait to finish previous IWDG_RLR register
+ * update (see watchdog_init()) before starting next update,
+ * otherwise new IWDG_RLR value will be lost.
+ */
+ while (STM32_IWDG_SR & STM32_IWDG_SR_RVU)
+ ;
+
+ /*
* Enable IWDG, which shouldn't be necessary since the IWDG
* only needs to be started once, but STM32F412 hangs unless
* this is added.
@@ -446,9 +463,11 @@ void system_reset(int flags)
/* Ask the watchdog to trigger a hard reboot */
STM32_IWDG_KR = STM32_IWDG_KR_UNLOCK;
STM32_IWDG_RLR = 0x1;
- /* Wait for value to be reloaded. */
+ /* Wait for value to be updated. */
while (STM32_IWDG_SR & STM32_IWDG_SR_RVU)
;
+
+ /* Reload IWDG counter, it also locks registers */
STM32_IWDG_KR = STM32_IWDG_KR_RELOAD;
#endif
/* wait for the chip to reboot */
diff --git a/chip/stm32/watchdog.c b/chip/stm32/watchdog.c
index 067ea32aa6..c3266904e2 100644
--- a/chip/stm32/watchdog.c
+++ b/chip/stm32/watchdog.c
@@ -57,6 +57,30 @@ int watchdog_init(void)
/* Start the watchdog (and re-lock registers) */
STM32_IWDG_KR = STM32_IWDG_KR_START;
+ /*
+ * We should really wait for IWDG_PR and IWDG_RLR value to be updated
+ * but updating those registers can take about 48ms (found
+ * empirically, it's 6 LSI cycles at 32kHz). Such a big delay is not
+ * desired during system init.
+ *
+ * However documentation allows us to continue code execution, but
+ * we should wait for RVU bit to be clear before updating IWDG_RLR
+ * once again (hard reboot for STM32H7 and STM32F4).
+ *
+ * RM0433 Rev 7
+ * Section 45.4.4 Page 1920
+ * https://www.st.com/resource/en/reference_manual/dm00314099.pdf
+ * If several reload, prescaler, or window values are used by the
+ * application, it is mandatory to wait until RVU bit is reset before
+ * changing the reload value, to wait until PVU bit is reset before
+ * changing the prescaler value, and to wait until WVU bit is reset
+ * before changing the window value. However, after updating the
+ * prescaler and/or the reload/window value it is not necessary to wait
+ * until RVU or PVU or WVU is reset before continuing code execution
+ * except in case of low-power mode entry.
+ */
+
+
#ifdef CONFIG_WATCHDOG_HELP
/* Use a harder timer to warn about an impending watchdog reset */
hwtimer_setup_watchdog();