Skip to content

Commit 1def34e

Browse files
authored
Nuvoton: M487: Fix reset loop with target.wdt-reset-workaround (#526)
We may trap in DPD/SPD wake-up reset loop when multi-level bootloaders (e.g. LDROM and MCUBoot) and application all or partial integrate this workaround. To avoid this, the wake-up flag CLK_PMUSTS_TMRWK_Msk is used to guard from duplicate wake-up reset setups and the clear-up of this flag is delayed to hal_watchdog_init, which will be invoked via Mbed Watchdog API. This approach works based on the assumptions: 1. Only application will set up WDT. LDROM and MCUBoot won't. 2. WDT setup is done via Mbed Watchdog API, not direct WDT control.
1 parent 044d986 commit 1def34e

File tree

2 files changed

+30
-48
lines changed

2 files changed

+30
-48
lines changed

targets/TARGET_NUVOTON/TARGET_M480/mbed_overrides.c

Lines changed: 23 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ void mbed_sdk_init(void)
8383
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
8484
SystemCoreClockUpdate();
8585

86-
/* Lock protected registers */
87-
SYS_LockReg();
88-
8986
#if MBED_CONF_TARGET_WDT_RESET_WORKAROUND
9087
/* Work around H/W limit with WDT reset from PD
9188
*
@@ -111,9 +108,11 @@ void mbed_sdk_init(void)
111108
* and WDT wake-up from PD will. So don't rely on SYS_IS_WDT_RST() to
112109
* determine to use or not the workaround.
113110
*
114-
* NOTE: To avoid the workaround duplicate run by bootloader (e.g. MCUBoot)
115-
* and application and then crash when bootloader is enabled, the workaround
116-
* is applied only when any H/W reset flag (SYS.RSTSTS) raised.
111+
* NOTE: We may trap in DPD/SPD wake-up reset loop when multi-level
112+
* bootloaders (e.g. LDROM and MCUBoot) and application all integrate
113+
* this workaround. To avoid this, the wake-up flag CLK_PMUSTS_TMRWK_Msk
114+
* is used to guard from duplicate wake-up reset setups by delaying
115+
* its clean-up to hal_watchdog_init (watchdog_api.c).
117116
*
118117
* NOTE: The workaround will change SYS.RSTSTS and DEVICE_RESET_REASON won't
119118
* work as expected. Don't enable MBED_CONF_TARGET_WDT_RESET_WORKAROUND and
@@ -133,54 +132,30 @@ MBED_CONF_TARGET_WDT_RESET_WORKAROUND and DEVICE_RESET_REASON \
133132
at the same time."
134133
#endif
135134

136-
#define ALL_RESET_FLAGS \
137-
(SYS_RSTSTS_PORF_Msk | \
138-
SYS_RSTSTS_PINRF_Msk | \
139-
SYS_RSTSTS_WDTRF_Msk | \
140-
SYS_RSTSTS_LVRF_Msk | \
141-
SYS_RSTSTS_BODRF_Msk | \
142-
SYS_RSTSTS_SYSRF_Msk | \
143-
SYS_RSTSTS_CPURF_Msk | \
144-
SYS_RSTSTS_CPULKRF_Msk)
145-
146-
/* Apply the workaround only when any H/W reset flag is raised. For
147-
* bootloader enabled application, the workaround must apply either
148-
* by bootloader or by application, but not both.
149-
*/
150-
if (SYS->RSTSTS & ALL_RESET_FLAGS) {
151-
/* Re-unlock protected clock setting */
152-
SYS_UnlockReg();
153-
154-
/* Without this, bootloader enabled application will trap in
155-
* loop of wake-up timer wake-up reset armed here by bootloader
156-
* and application alternately, if both integrate this piece
157-
* of code.
158-
*/
159-
SYS_CLEAR_RST_SOURCE(ALL_RESET_FLAGS);
160-
161-
/* Release I/O hold status */
162-
CLK->IOPDCTL = 1;
163-
164-
if (!(CLK->PMUSTS & CLK_PMUSTS_TMRWK_Msk)) {
165-
/* Set up DPD/SPD power down mode */
166-
CLK_SetPowerDownMode(CLK_PMUCTL_PDMSEL_SPD0);
135+
/* Release I/O hold status */
136+
CLK->IOPDCTL = 1;
167137

168-
/* Enable wake-up timer */
169-
CLK_SET_WKTMR_INTERVAL(CLK_PMUCTL_WKTMRIS_256);
170-
CLK_ENABLE_WKTMR();
138+
if (!(CLK->PMUSTS & CLK_PMUSTS_TMRWK_Msk)) {
139+
/* Set up DPD/SPD power down mode */
140+
CLK_SetPowerDownMode(CLK_PMUCTL_PDMSEL_SPD0);
171141

172-
CLK_PowerDown();
142+
/* Enable wake-up timer */
143+
CLK_SET_WKTMR_INTERVAL(CLK_PMUCTL_WKTMRIS_256);
144+
CLK_ENABLE_WKTMR();
173145

174-
MBED_UNREACHABLE;
175-
}
146+
CLK_PowerDown();
176147

177-
/* Clean previous wake-up flag */
178-
CLK->PMUSTS |= (CLK_PMUSTS_CLRWK_Msk | CLK_PMUSTS_TMRWK_Msk);
179-
180-
/* Lock protected registers */
181-
SYS_LockReg();
148+
MBED_UNREACHABLE;
182149
}
150+
151+
/* Don't clean wake-up flag here (see above) */
152+
#if 0
153+
CLK->PMUSTS |= (CLK_PMUSTS_CLRWK_Msk | CLK_PMUSTS_TMRWK_Msk);
154+
#endif
183155
#endif
156+
157+
/* Lock protected registers */
158+
SYS_LockReg();
184159
}
185160

186161
// Override mbed_mac_address of mbed_interface.c to provide ethernet devices with a semi-unique MAC address

targets/TARGET_NUVOTON/TARGET_M480/watchdog_api.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ watchdog_status_t hal_watchdog_init(const watchdog_config_t *config)
8888

8989
SYS_UnlockReg();
9090

91+
/* See mbed_sdk_init (mbed_override.c) on workaround to
92+
* H/W limit with WDT reset from PD.
93+
*/
94+
#if MBED_CONF_TARGET_WDT_RESET_WORKAROUND
95+
CLK->PMUSTS |= (CLK_PMUSTS_CLRWK_Msk | CLK_PMUSTS_TMRWK_Msk);
96+
#endif
97+
9198
/* Enable IP module clock */
9299
CLK_EnableModuleClock(WDT_MODULE);
93100

0 commit comments

Comments
 (0)