diff --git a/targets/TARGET_NUVOTON/TARGET_M480/device/startup_M480.c b/targets/TARGET_NUVOTON/TARGET_M480/device/startup_M480.c index a851c655ed3..6110f145770 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/device/startup_M480.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/device/startup_M480.c @@ -360,18 +360,12 @@ __asm void Reset_Handler_Cascade(void *sp, void *pc) #elif defined (__GNUC__) || defined (__ICCARM__) -void Reset_Handler(void) +__attribute__((naked)) void Reset_Handler(void) { - /* NOTE: In debugger disassembly view, check initial stack cannot be accessed until initial stack pointer has changed to 0x20000200 */ - __asm volatile ( - "mov sp, %0 \n" - "mov r0, sp \n" - "mov r1, %1 \n" - "b Reset_Handler_Cascade \n" - : /* output operands */ - : "l"(0x20000200), "l"(&Reset_Handler_1) /* input operands */ - : "r0", "r1", "cc" /* list of clobbered registers */ - ); + __asm("ldr sp, =0x20000200 \n"); + __asm("mov r0, sp \n"); + __asm("ldr r1, =Reset_Handler_1 \n"); + __asm("b Reset_Handler_Cascade \n"); } void Reset_Handler_Cascade(void *sp, void *pc) diff --git a/targets/TARGET_NUVOTON/TARGET_M480/mbed_overrides.c b/targets/TARGET_NUVOTON/TARGET_M480/mbed_overrides.c index 23838a50038..5f7c63cdbb7 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/mbed_overrides.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/mbed_overrides.c @@ -16,6 +16,20 @@ #include "analogin_api.h" +void WDT_IRQHandler(void) +{ + /* Check WDT interrupt flag */ + if (WDT_GET_TIMEOUT_INT_FLAG()) { + WDT_CLEAR_TIMEOUT_INT_FLAG(); + WDT_RESET_COUNTER(); + } + + /* Check WDT wake-up flag */ + if (WDT_GET_TIMEOUT_WAKEUP_FLAG()) { + WDT_CLEAR_TIMEOUT_WAKEUP_FLAG(); + } +} + void mbed_sdk_init(void) { // NOTE: Support singleton semantics to be called from other init functions @@ -69,4 +83,49 @@ void mbed_sdk_init(void) /* Lock protected registers */ SYS_LockReg(); + + /* Get around h/w issue with reset from power-down mode + * + * When UART interrupt enabled and WDT reset from power-down mode, in the next + * cycle, UART interrupt keeps breaking in and cannot block unless via NVIC. To + * get around it, we make up a signal of WDT wake-up from power-down mode in the + * start of boot process on detecting WDT reset. + */ + if (SYS_IS_WDT_RST()) { + /* Enable IP module clock */ + CLK_EnableModuleClock(WDT_MODULE); + + /* Select IP clock source */ + CLK_SetModuleClock(WDT_MODULE, CLK_CLKSEL1_WDTSEL_LIRC, 0); + + /* The name of symbol WDT_IRQHandler() is mangled in C++ and cannot + * override that in startup file in C. Note the NVIC_SetVector call + * cannot be left out when WDT_IRQHandler() is redefined in C++ file. + * + * NVIC_SetVector(WDT_IRQn, (uint32_t) WDT_IRQHandler); + */ + NVIC_EnableIRQ(WDT_IRQn); + + SYS_UnlockReg(); + + /* Configure/Enable WDT */ + WDT->CTL = WDT_TIMEOUT_2POW4 | // Timeout interval of 2^4 LIRC clocks + WDT_CTL_WDTEN_Msk | // Enable watchdog timer + WDT_CTL_INTEN_Msk | // Enable interrupt + WDT_CTL_WKF_Msk | // Clear wake-up flag + WDT_CTL_WKEN_Msk | // Enable wake-up on timeout + WDT_CTL_IF_Msk | // Clear interrupt flag + WDT_CTL_RSTF_Msk | // Clear reset flag + !WDT_CTL_RSTEN_Msk | // Disable reset + WDT_CTL_RSTCNT_Msk; // Reset up counter + + CLK_PowerDown(); + + /* Clear all flags & Disable WDT/INT/WK/RST */ + WDT->CTL = (WDT_CTL_WKF_Msk | WDT_CTL_IF_Msk | WDT_CTL_RSTF_Msk | WDT_CTL_RSTCNT_Msk); + + NVIC_DisableIRQ(WDT_IRQn); + + SYS_LockReg(); + } }