mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #12557 from OpenNuvoton/nuvoton_m487_wdt_reset_powerdown
M487: Fix crash on WDT reset from power-downpull/12463/head
						commit
						4f07086d85
					
				| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue