text: /**************************************************************************//**
   * @file     main.c
   * @version  V3.00
   * @brief    Implement WDT time-out interrupt event to wake up system and generate time-out reset system event while WDT time-out reset delay period expired.
   *
   * @copyright SPDX-License-Identifier: Apache-2.0
   * @copyright Copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
   ******************************************************************************/
  #include <stdio.h>
  #include "NuMicro.h"
  
  /*---------------------------------------------------------------------------------------------------------*/
  /* Functions and variables declaration                                                                     */
  /*---------------------------------------------------------------------------------------------------------*/
  static volatile uint8_t g_u8IsINTEvent;
  static volatile uint32_t g_u32WakeupCounts;
  
  void WDT_IRQHandler(void);
  void SYS_Init(void);
  void UART_Init(void);
  
  
  /**
   * @brief       IRQ Handler for WDT Interrupt
   * @param       None
   * @return      None
   * @details     The WDT_IRQHandler is default IRQ of WDT, declared in startup_m460.s.
   */
  void WDT_IRQHandler(void)
  {
      if(g_u32WakeupCounts < 10)
      {
          WDT_RESET_COUNTER();
      }
  
      if(WDT_GET_TIMEOUT_INT_FLAG() == 1)
      {
          /* Clear WDT time-out interrupt flag */
          WDT_CLEAR_TIMEOUT_INT_FLAG();
  
          g_u8IsINTEvent = 1;
      }
  
      if(WDT_GET_TIMEOUT_WAKEUP_FLAG() == 1)
      {
          /* Clear WDT time-out wake-up flag */
          WDT_CLEAR_TIMEOUT_WAKEUP_FLAG();
  
          g_u32WakeupCounts++;
      }
  }
  
  void SYS_Init(void)
  {
      /*---------------------------------------------------------------------------------------------------------*/
      /* Init System Clock                                                                                       */
      /*---------------------------------------------------------------------------------------------------------*/
      /* Set PCLK0 and PCLK1 to HCLK/2 */
      CLK->PCLKDIV = (CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2);
  
      /* Set core clock to 200MHz */
      CLK_SetCoreClock(200000000);
  
      /* Enable all GPIO clock */
      CLK->AHBCLK0 |= CLK_AHBCLK0_GPACKEN_Msk | CLK_AHBCLK0_GPBCKEN_Msk | CLK_AHBCLK0_GPCCKEN_Msk | CLK_AHBCLK0_GPDCKEN_Msk |
                      CLK_AHBCLK0_GPECKEN_Msk | CLK_AHBCLK0_GPFCKEN_Msk | CLK_AHBCLK0_GPGCKEN_Msk | CLK_AHBCLK0_GPHCKEN_Msk;
      CLK->AHBCLK1 |= CLK_AHBCLK1_GPICKEN_Msk | CLK_AHBCLK1_GPJCKEN_Msk;
  
      /* Enable UART0 module clock */
      CLK_EnableModuleClock(UART0_MODULE);
  
      /* Select UART0 module clock source as HIRC and UART0 module clock divider as 1 */
      CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));  
      
      /*---------------------------------------------------------------------------------------------------------*/
      /* Init I/O Multi-function                                                                                 */
      /*---------------------------------------------------------------------------------------------------------*/
      /* Set multi-function pins for UART0 RXD and TXD */
      SET_UART0_RXD_PB12();
      SET_UART0_TXD_PB13();
  
  
      /*---------------------------------------------------------------------------------------------------------*/
      /* Initialization for sample code                                                                          */
      /*---------------------------------------------------------------------------------------------------------*/
      /* Enable LIRC and waiting for clock ready */
      CLK_EnableXtalRC(CLK_PWRCTL_LIRCEN_Msk);
      CLK_WaitClockReady(CLK_STATUS_LIRCSTB_Msk);
  
      /* Enable WDT module clock */
      CLK_EnableModuleClock(WDT_MODULE);
      CLK_SetModuleClock(WDT_MODULE, CLK_CLKSEL1_WDTSEL_LIRC, 0);
  }
  
  void UART_Init(void)
  {
      /*---------------------------------------------------------------------------------------------------------*/
      /* Init UART                                                                                               */
      /*---------------------------------------------------------------------------------------------------------*/
      /* Reset UART0 */
      SYS_ResetModule(UART0_RST);
  
      /* Configure UART0 and set UART0 baud rate */
      UART_Open(DEBUG_PORT, 115200);
  }
  
  /*---------------------------------------------------------------------------------------------------------*/
  /*  Main Function                                                                                          */
  /*---------------------------------------------------------------------------------------------------------*/
  int main(void)
  {
      uint32_t u32TimeOutCnt;
  
      /* Unlock protected registers */
      SYS_UnlockReg();
  
      /* Init System, peripheral clock and multi-function I/O */
      SYS_Init();
  
      /* Init UART for printf */
      UART_Init();
  
      /* Lock protected registers */
      SYS_LockReg();
  
      printf("\n\nCPU @ %d Hz\n", SystemCoreClock);
      printf("+----------------------------------------+\n");
      printf("|    WDT Time-out Wake-up Sample Code    |\n");
      printf("+----------------------------------------+\n\n");
  
      /* To check if system has been reset by WDT time-out reset or not */
      if(WDT_GET_RESET_FLAG() == 1)
      {
          WDT_CLEAR_RESET_FLAG();
          printf("*** System has been reset by WDT time-out event ***\n\n");
          while(1) {}
      }
  
      printf("# WDT Settings:\n");
      printf("    - Clock source is LIRC                  \n");
      printf("    - Time-out interval is 2^14 * WDT clock \n");
      printf("      (around 1.6 s)                        \n");
      printf("    - Interrupt enable                      \n");
      printf("    - Wake-up function enable               \n");
      printf("    - Reset function enable                 \n");
      printf("    - Reset delay period is 18 * WDT clock  \n");
      printf("# System will generate a WDT time-out interrupt event after 1.6 s, \n");
      printf("    and will be wake up from power-down mode also.\n");
      printf("    (Use PA.2 high/low period time to check WDT time-out interval)\n");
      printf("# When WDT interrupt counts large than 10, \n");
      printf("    we will not reset WDT counter value and system will be reset immediately by WDT time-out reset signal.\n");
  
      /* Use PA.2 to check time-out interrupt period time */
      PA->MODE = (PA->MODE & ~GPIO_MODE_MODE2_Msk) | (GPIO_MODE_OUTPUT << GPIO_MODE_MODE2_Pos);
      PA2 = 1;
  
      /* Enable WDT NVIC */
      NVIC_EnableIRQ(WDT_IRQn);
  
      /* Because of all bits can be written in WDT Control Register are write-protected;
         To program it needs to disable register protection first. */
      SYS_UnlockReg();
  
      /* Configure WDT settings and start WDT counting */
      g_u8IsINTEvent = g_u32WakeupCounts = 0;
      WDT_Open(WDT_TIMEOUT_2POW14, WDT_RESET_DELAY_18CLK, TRUE, TRUE);
  
      /* Enable WDT interrupt function */
      WDT_EnableInt();
  
      while(1)
      {
          /* System enter to Power-down */
          /* To program PWRCTL register, it needs to disable register protection first. */
          SYS_UnlockReg();
          printf("\nSystem enter to power-down mode ...\n");
          /* To check if all the debug messages are finished */
          u32TimeOutCnt = SystemCoreClock; /* 1 second time-out */
          while(!UART_IS_TX_EMPTY(DEBUG_PORT))
              if(--u32TimeOutCnt == 0) break;
          CLK_PowerDown();
  
          /* Check if WDT time-out interrupt and wake-up occurred or not */
          u32TimeOutCnt = SystemCoreClock; /* 1 second time-out */
          while(g_u8IsINTEvent == 0)
          {
              if(--u32TimeOutCnt == 0)
              {
                  printf("Wait for WDT interrupt time-out!\n");
                  break;
              }
          }
          PA2 ^= 1;
  
          g_u8IsINTEvent = 0;
          printf("System has been waken up done. WDT wake-up counts: %d.\n\n", g_u32WakeupCounts);
      }
  }
  