

#include "WDT.h"

/*! key for unlocking HW-WDG regs */
#define   WDG_PROT_UNLOCK                   (0xEDACCE55UL)

static __irq __arm void WDT_PreWarn_ISR(void);
static __fiq __arm void WDT_NMI_ISR(void);

void WDT_Init(void)
{
  /*** Access registers ***/
  /* Disable IRQs for protected sequences */
  IRQ_DISABLE_LOCAL()
  
  /* Clear interrupt flags */
  HWDG_PROT = WDG_PROT_UNLOCK;
  HWDG_INTCLR_IRQCLR = 1U;
  HWDG_PROT = WDG_PROT_UNLOCK;
  HWDG_INTCLR_NMICLR = 1U;
  
  /* Clear reset cause */
  HWDG_PROT = WDG_PROT_UNLOCK;
  HWDG_RSTCAUSE = 0x00000000UL;
  
  /* Unlock software watchdog */
  SWDG_PROT = WDG_PROT_UNLOCK; 
  SWDG_CFG_LOCK = 0U;
  
  /* Disable software watchdog */
  SWDG_PROT = WDG_PROT_UNLOCK; 
  SWDG_CFG  = 0x00000104UL;
  
  /* Lock software watchdog */
  SWDG_PROT = WDG_PROT_UNLOCK; 
  SWDG_CFG_LOCK = 1U;
  
  /* Register ISR */
  Interrupt_NMI_ISR_Register(INTERRUPTS_NMI_NUMBER_6, (uint32_t)WDT_NMI_ISR, 15U);
  Interrupt_IRQ_ISR_Register(INTERRUPTS_IRQ_NUMBER_2, (uint32_t)WDT_PreWarn_ISR, 31U);
  
  /* restore IRQ state */
  IRQ_RESTORE()
}


void WDT_Clear(void)
{
  /*** Access registers ***/
  /* Clear HWDG */
  IRQ_DISABLE_LOCAL()
  HWDG_TRG0 = HWDG_TRG0CFG;
  HWDG_TRG1 = HWDG_TRG1CFG;
  IRQ_RESTORE()
}

static __irq __arm void WDT_PreWarn_ISR(void)
{
  /* Reset MCU while entering this interrupt accidentally */
  SYSC0_PROTKEYR      = 0x5CACCE55UL;  
  SYSC_RSTCNTR_SWHRST = 0xA5U;
  
  IRC0_IRQHC = INTERRUPTS_IRQ_NUMBER_2;
}

static __fiq __arm void WDT_NMI_ISR(void)
{
  /* Reset MCU while entering this interrupt accidentally */
  SYSC0_PROTKEYR      = 0x5CACCE55UL;  
  SYSC_RSTCNTR_SWHRST = 0xA5U;
  
  IRC0_IRQHC = INTERRUPTS_NMI_NUMBER_6;
}
