學習KEA之看門狗

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.
  • 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章