KEA的看门狗是一个独立的特殊定时器。当启动看门狗后,如果你不定时去喂狗,它就认为程序跑飞了,将会复位MCU。
特点
- 时钟源可选:
- bus clock
- Internal 32 kHz RC oscillator
- Internal 1 kHz RC oscillator
- External clock source
- Programmable timeout period
- Programmable 16-bit timeout value
- Optional fixed 256 clock prescaler when longer timeout periods are needed
- Robust write sequence for counter refresh
- Refresh sequence of writing 0x02A6 and then 0x80B4 within 16 bus clocks
- Window mode option for the refresh mechanism
- Programmable 16-bit window value
- Provides robust check that program flow is faster than expected
- Early refresh attempts trigger a reset.
- Optional timeout interrupt to allow post-processing diagnostics
- Interrupt request to CPU with interrupt vector for an interrupt service routine
(ISR) - Forced reset occurs 128 bus clocks after the interrupt vector fetch.
- Interrupt request to CPU with interrupt vector for an interrupt service routine
- Configuration bits are write-once-after-reset to ensure watchdog configuration cannotbe mistakenly altered.
- Robust write sequence for unlocking write-once configuration bits
- Unlock sequence of writing 0x20C5 and then 0x28D9 within 16 bus clocks forallowing updates to write-once configuration bits
- Software must make updates within 128 bus clocks after unlocking and beforeWDOG closing unlock window.
例程
看门狗设置为:Internal 1 kHz RC oscillator, timeout 1s
main.c
#include "derivative.h" /* include peripheral declarations SSKEAZN64M2 */
#include "wdog.h"
void Clk_Init(void);
void Delay(void);
int main(void)
{
Clk_Init();
LED_Init();
WDOG_ConfigType WDOGConfig = {{0}}; /*! < watchdog configuration structure */
WDOGConfig.sBits.bIntEnable = TRUE;
WDOGConfig.sBits.bWaitEnable = TRUE;
WDOGConfig.sBits.bStopEnable = TRUE;
WDOGConfig.sBits.bDbgEnable = TRUE;
WDOGConfig.sBits.bUpdateEnable = FALSE;
WDOGConfig.sBits.bDisable = FALSE; /* enable WDOG */
WDOGConfig.sBits.bClkSrc = WDOG_CLK_INTERNAL_1KHZ;
WDOGConfig.u16TimeOut = 1000; /*< 1s */
WDOGConfig.u16WinTime = 0;
WDOG_Init(&WDOGConfig);
if(WDOG_IsReset()) /*!< check if wathdog reset happens */
{
/*! watchdog happens */
while(1)
{
WDOG_Feed();
LED_Toggle();
Delay(); //400ms
}
}
for(;;)
{
//WDOG_Feed(); /* 这里要是不喂狗,则看门狗将会复位MCU *
}
return 0;
}
/***********************************************************************************************
*
* @brief CLK_Init - Initialize Core Clock to 40MHz, Bus Clock to 20MHz
* @param none
* @return none
*
************************************************************************************************/
void Clk_Init(void)
{
ICS_C1|= ICS_C1_IRCLKEN_MASK; /* Enable the internal reference clock*/
ICS_C3 = 0x50; /* Reference clock frequency = 31.25 kHz*/
while(!(ICS_S & ICS_S_LOCK_MASK)); /* Wait for PLL lock, now running at 40 MHz (1024*39.0625 kHz) */
ICS_C2 |= ICS_C2_BDIV(1) ; /* BDIV=b001, Bus clock = 20 MHz*/
ICS_S |= ICS_S_LOCK_MASK ; /* Clear Loss of lock sticky bit */
}
/* Generate Delay using nested loops */
void Delay(void)
{
uint32_t i,j;
for(i=0 ; i<8 ; i++)
for(j=0 ; j<65535 ; j++);
}
wdog.h
#ifndef __WDOG_H__
#define __WDOG_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "derivative.h"
#define WDOG_CLK_BUS 0 /*!< clock source is bus clock */
#define WDOG_CLK_INTERNAL_32KHZ 2 /*!< clock source is internal oscillator 32 kHz (ICSIRCLK) */
#define WDOG_CLK_INTERNAL_1KHZ 1 /*!< clock source is internal LPO 1 KHz */
#define WDOG_CLK_EXTERNAL 3 /*!< clock source is external clock */
/*! @} End of wdog_clock_sources */
/* WDOG clock source selection */
#define WDOG_CLK (WDOG_CLK_INTERNAL_1KHZ)
/*!
* @brief watchdog unlock routine.
*/
#define WDOG_Unlock() WDOG->CNT = 0x20C5; WDOG->CNT = 0x28D9
/*!
* @brief watchdog configuration structure.
*
*/
typedef struct {
struct {
uint16_t bIntEnable : 1; /*!< watchdog interrupt enable */
uint16_t bDisable : 1; /*!< disable watchdog */
uint16_t bWaitEnable : 1; /*!< enable watchdog in wait mode */
uint16_t bStopEnable : 1; /*!< enable watchdog in stop mode */
uint16_t bDbgEnable : 1; /*!< enable watchdog in debug mode */
uint16_t bWinEnable : 1; /*!< enable watchdog window mode */
uint16_t bUpdateEnable : 1; /*!< enable update of watchdog control */
uint16_t bClkSrc : 2; /*!< watchdog clock source selection */
uint16_t bPrescaler : 1; /*!< prescaler */
}sBits; /*!< bitfield structure */
uint16_t u16TimeOut; /*!< watchdog timeout value */
uint16_t u16WinTime; /*!< watchdog window value */
} WDOG_ConfigType, *WDOG_ConfigPtr; /*!< watchdog configuration structure type */
/*! @} End of wdog_config_type */
/*****************************************************************************//*!
*
* @brief check if watchdog reset occurs.
*
* @param none.
*
* @return TRUE if watchdog reset occurs, FALSE otherwise.
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
static inline uint8_t WDOG_IsReset(void)
{ uint32_t u32Status;
u32Status = SIM->SRSID & SIM_SRSID_WDOG_MASK;
if(u32Status)
{
return (1);
}
return (0);
}
void WDOG_Init(WDOG_ConfigPtr pConfig);
void WDOG_Feed(void);
uint8_t WDOG_IsReset(void);
#ifdef __cplusplus
}
#endif
/********************************************************************/
#endif /* __WDOG_H__ */
wdog.c
#include "wdog.h"
#include "derivative.h"
#define DisableInterrupts asm(" CPSID i");
#define EnableInterrupts asm(" CPSIE i");
/*****************************************************************************//*!
*
* @brief initialize watchdog.
*
* @param[in] pConfig poiner to watchdog configuration strcture.
*
* @return none
*
* @ Pass/ Fail criteria: none
*
* @warning make sure that WDOG is not initialized after reset or WDOG update is enabled
* after reset by calling WDOG_EnableUpdate / WDOG_DisableWDOGEnableUpdate.
*
* @see WDOG_EnableUpdate, WDOG_DisableWDOGEnableUpdate
*
*****************************************************************************/
void WDOG_Init(WDOG_ConfigPtr pConfig)
{
uint8_t u8Cs1;
uint8_t u8Cs2;
uint16_t u16Toval;
uint16_t u16Win;
u8Cs1 = 0x80; /* default CS1 register value */
u8Cs2 = 0;
u16Toval = pConfig->u16TimeOut;
u16Win = pConfig->u16WinTime;
if(pConfig->sBits.bDisable)
{
u8Cs1 &= ~WDOG_CS1_EN_MASK;
}
else
{
u8Cs1 |= WDOG_CS1_EN_MASK;
}
if(pConfig->sBits.bIntEnable)
{
u8Cs1 |= WDOG_CS1_INT_MASK;
Enable_Interrupt(WDOG_EWM_IRQn);
}
else
{
u8Cs1 &= ~WDOG_CS1_INT_MASK;
Disable_Interrupt(WDOG_EWM_IRQn);
}
if(pConfig->sBits.bStopEnable)
{
u8Cs1 |= WDOG_CS1_STOP_MASK;
}
else
{
u8Cs1 &= ~WDOG_CS1_STOP_MASK;
}
if(pConfig->sBits.bDbgEnable)
{
u8Cs1 |= WDOG_CS1_DBG_MASK;
}
else
{
u8Cs1 &= ~WDOG_CS1_DBG_MASK;
}
if(pConfig->sBits.bWaitEnable)
{
u8Cs1 |= WDOG_CS1_WAIT_MASK;
}
else
{
u8Cs1 &= ~WDOG_CS1_WAIT_MASK;
}
if(pConfig->sBits.bUpdateEnable)
{
u8Cs1 |= WDOG_CS1_UPDATE_MASK;
}
else
{
u8Cs1 &= ~WDOG_CS1_UPDATE_MASK;
}
if(pConfig->sBits.bWinEnable)
{
u8Cs2 |= WDOG_CS2_WIN_MASK;
}
else
{
u8Cs2 &= ~WDOG_CS2_WIN_MASK;
}
if(pConfig->sBits.bPrescaler)
{
u8Cs2 |= WDOG_CS2_PRES_MASK;
}
u8Cs2 |= (pConfig->sBits.bClkSrc & 0x03);
/* write regisers */
WDOG_Unlock(); /* unlock watchdog first */
WDOG->CS2 = u8Cs2;
WDOG->TOVAL8B.TOVALL = u16Toval;
WDOG->TOVAL8B.TOVALH = u16Toval >> 8;
WDOG->WIN8B.WINL = u16Win;
WDOG->WIN8B.WINH = u16Win >> 8;
WDOG->CS1 = u8Cs1;
}
/*****************************************************************************//*!
*
* @brief feed/refresh watchdog.
*
* @param none
*
* @return none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void WDOG_Feed(void)
{
DisableInterrupts;
WDOG->CNT = 0x02A6;
WDOG->CNT = 0x80B4;
EnableInterrupts;
}