Skip to content

Commit 0b7b3a1

Browse files
authored
Nuvoton: M487: Fix RTC spare registers cleared with WDT reset from PD (#519)
WDT reset from PD needs workaround in which DPD wake-up reset is set up to run immediately, but it will clear RTC spare registers per test. The solution is to use SPD wake-up reset instead. NOTE1: This workaround is applied only when H/W reset flag is raised. This is to avoid abnormal boot sequence for bootloader-enabled application. NOTE2: This workaround will change SYS.RSTSTS and influence RESET_REASON. To avoid confusion, RESET_REASON is disabled by default.
1 parent af876a0 commit 0b7b3a1

File tree

2 files changed

+91
-10
lines changed

2 files changed

+91
-10
lines changed

targets/TARGET_NUVOTON/TARGET_M480/mbed_overrides.c

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,24 +86,101 @@ void mbed_sdk_init(void)
8686
/* Lock protected registers */
8787
SYS_LockReg();
8888

89-
/* Get around h/w limit with WDT reset from PD */
90-
if (SYS_IS_WDT_RST()) {
89+
#if MBED_CONF_TARGET_WDT_RESET_WORKAROUND
90+
/* Work around H/W limit with WDT reset from PD
91+
*
92+
* To reproduce WDT reset from PD, run like:
93+
* Watchdog &watchdog = Watchdog::get_instance();
94+
* watchdog.start(2500);
95+
* while (1) {
96+
* SYS_UnlockReg();
97+
* CLK_PowerDown();
98+
* }
99+
*
100+
* To reproduce WDT wake-up from PD and then WDT reset, run:
101+
* Watchdog &watchdog = Watchdog::get_instance();
102+
* watchdog.start(2500);
103+
* SYS_UnlockReg();
104+
* CLK_PowerDown();
105+
* while (1);
106+
*
107+
* NOTE: The H/W limit is met on WDT reset from PD, not WDT wake-up
108+
* from PD and then WDT reset.
109+
*
110+
* NOTE: Per test, WDT reset from PD won't raise SYS_RSTSTS.WDTRF flag,
111+
* and WDT wake-up from PD will. So don't rely on SYS_IS_WDT_RST() to
112+
* determine to use or not the workaround.
113+
*
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.
117+
*
118+
* NOTE: The workaround will change SYS.RSTSTS and DEVICE_RESET_REASON won't
119+
* work as expected. Don't enable MBED_CONF_TARGET_WDT_RESET_WORKAROUND and
120+
* DEVICE_RESET_REASON at the same time.
121+
*
122+
* NOTE: Per test, DPD wake-up reset will clean RTC spare registers,
123+
* so use SPD wake-up reset instead to get around the limit.
124+
*
125+
* NOTE: Per test, SPD wake-up reset doesn't release I/O hold status
126+
* (CLK->IOPDCTL) automatically. Must do it manually.
127+
*/
128+
129+
#if DEVICE_RESET_REASON
130+
#warning "MBED_CONF_TARGET_WDT_RESET_WORKAROUND will change SYS.RSTSTS \
131+
and DEVICE_RESET_REASON won't work as expected. Don't enable \
132+
MBED_CONF_TARGET_WDT_RESET_WORKAROUND and DEVICE_RESET_REASON \
133+
at the same time."
134+
#endif
135+
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) {
91151
/* Re-unlock protected clock setting */
92152
SYS_UnlockReg();
93153

94-
/* Set up DPD power down mode */
95-
CLK->PMUSTS |= CLK_PMUSTS_CLRWK_Msk;
96-
CLK->PMUSTS |= CLK_PMUSTS_TMRWK_Msk;
97-
CLK_SetPowerDownMode(CLK_PMUCTL_PDMSEL_DPD);
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);
98167

99-
CLK_SET_WKTMR_INTERVAL(CLK_PMUCTL_WKTMRIS_256);
100-
CLK_ENABLE_WKTMR();
168+
/* Enable wake-up timer */
169+
CLK_SET_WKTMR_INTERVAL(CLK_PMUCTL_WKTMRIS_256);
170+
CLK_ENABLE_WKTMR();
101171

102-
CLK_PowerDown();
172+
CLK_PowerDown();
173+
174+
MBED_UNREACHABLE;
175+
}
176+
177+
/* Clean previous wake-up flag */
178+
CLK->PMUSTS |= (CLK_PMUSTS_CLRWK_Msk | CLK_PMUSTS_TMRWK_Msk);
103179

104180
/* Lock protected registers */
105181
SYS_LockReg();
106182
}
183+
#endif
107184
}
108185

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

targets/targets.json5

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8294,6 +8294,11 @@ mode is recommended for target MCUs with small amounts of flash and RAM.",
82948294
"usb-device-hsusbd": {
82958295
"help": "Select high-speed USB device or not",
82968296
"value": 0
8297+
},
8298+
"wdt-reset-workaround": {
8299+
"help": "Workaround to H/W limit with WDT reset from power-down",
8300+
"options": [false, true],
8301+
"value": true
82978302
}
82988303
},
82998304
"inherits": [
@@ -8328,7 +8333,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.",
83288333
"EMAC",
83298334
"MPU",
83308335
"WATCHDOG",
8331-
"RESET_REASON",
83328336
"USBDEVICE"
83338337
],
83348338
"release_versions": [

0 commit comments

Comments
 (0)