学习KEA之看门狗

    技术2022-07-10  134

    KEA的看门狗是一个独立的特殊定时器。当启动看门狗后,如果你不定时去喂狗,它就认为程序跑飞了,将会复位MCU。

    特点

    时钟源可选: bus clockInternal 32 kHz RC oscillatorInternal 1 kHz RC oscillatorExternal clock source Programmable timeout period Programmable 16-bit timeout valueOptional 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 valueProvides robust check that program flow is faster than expectedEarly 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 bitsSoftware 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; }
    Processed: 0.012, SQL: 9