diff options
author | Patryk Duda <pdk@semihalf.com> | 2021-05-21 13:23:19 +0200 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-05-26 20:04:01 +0000 |
commit | 3ca879a81c455531b438fc5186ac54694f733ab5 (patch) | |
tree | e5c9a9f972861257eea658b78568f250d23a1d7d /chip/stm32 | |
parent | 59c47366fe3832bbbbc098948f4073fdd8fe438a (diff) | |
download | chrome-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/stm32')
-rw-r--r-- | chip/stm32/system.c | 21 | ||||
-rw-r--r-- | chip/stm32/watchdog.c | 24 |
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(); |