2024-12-30 11:50:48 +08:00
|
|
|
|
|
|
|
|
|
#include "bsp_wdg.h"
|
|
|
|
|
|
|
|
|
|
#define LOG_TAG "bsp_wgd" // 该模块对应的标签。不定义时,默认:NO_TAG
|
|
|
|
|
#define LOG_LVL LOG_LVL_DBG // 该模块对应的日志输出级别。不定义时,默认:调试级别
|
|
|
|
|
#include <ulog.h> // 必须在 LOG_TAG 与 LOG_LVL 下面
|
|
|
|
|
|
|
|
|
|
ALIGN(RT_ALIGN_SIZE)
|
|
|
|
|
static char wdg_thread_stack[WDG_THREAD_STACK_SIZE];
|
|
|
|
|
static struct rt_thread wdg_thread;
|
|
|
|
|
|
|
|
|
|
#if USED_WWDG
|
|
|
|
|
// This routine demonstrates that the watchdog is fed between the window 0x40(64) and 0x7F(127) to
|
|
|
|
|
// prevent the watchdog from being reset.
|
|
|
|
|
#define WWDG_CNT 127
|
|
|
|
|
uint8_t wwdg_tr, wwdg_wr;
|
|
|
|
|
void WWDG_IRQHandler(void) __attribute__((interrupt("")));
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if USED_IWDG
|
|
|
|
|
/*************************************IWDG**********************************************/
|
|
|
|
|
/**
|
|
|
|
|
* @description: Initializes IWDG.
|
|
|
|
|
* @param {uint16_t} prescaler specifies the IWDG Prescaler value.
|
|
|
|
|
* IWDG_Prescaler_4: IWDG prescaler set to 4.
|
|
|
|
|
* IWDG_Prescaler_8: IWDG prescaler set to 8.
|
|
|
|
|
* IWDG_Prescaler_16: IWDG prescaler set to 16.
|
|
|
|
|
* IWDG_Prescaler_32: IWDG prescaler set to 32.
|
|
|
|
|
* IWDG_Prescaler_64: IWDG prescaler set to 64.
|
|
|
|
|
* IWDG_Prescaler_128: IWDG prescaler set to 128.
|
|
|
|
|
* IWDG_Prescaler_256: IWDG prescaler set to 256.
|
|
|
|
|
* @param {uint16_t} reload specifies the IWDG Reload value.
|
|
|
|
|
* This parameter must be a number between 0 and 0x0FFF(4095).
|
|
|
|
|
* @return {*}
|
|
|
|
|
*/
|
|
|
|
|
void IWDG_Init(uint16_t prescaler, uint16_t reload)
|
|
|
|
|
{
|
|
|
|
|
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
|
|
|
|
IWDG_SetPrescaler(prescaler);
|
|
|
|
|
IWDG_SetReload(reload);
|
|
|
|
|
IWDG_ReloadCounter();
|
|
|
|
|
IWDG_Enable();
|
|
|
|
|
|
|
|
|
|
LOG_I("IWDG_Feed_Init");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void IWDG_Feed(void)
|
|
|
|
|
{
|
|
|
|
|
// LOG_D("IWDG_Feed!");
|
|
|
|
|
IWDG_ReloadCounter(); //Feed dog
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#elif USED_WWDG
|
|
|
|
|
/*************************************WWDG**********************************************/
|
|
|
|
|
/*********************************************************************
|
|
|
|
|
* @fn WWDG_NVIC_Config
|
|
|
|
|
*
|
|
|
|
|
* @brief WWDG INT init.
|
|
|
|
|
*
|
|
|
|
|
* @return none
|
|
|
|
|
*/
|
|
|
|
|
static void WWDG_NVIC_Config(void)
|
|
|
|
|
{
|
|
|
|
|
NVIC_InitTypeDef NVIC_InitStructure = {0};
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
|
|
|
NVIC_Init(&NVIC_InitStructure);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @description:
|
|
|
|
|
* @param {uint32_t} prv 设置预分频器值
|
|
|
|
|
* WWDG_Prescaler - specifies the WWDG Prescaler
|
|
|
|
|
* WWDG_Prescaler_1 - WWDG counter clock = (PCLK1/4096)/1
|
|
|
|
|
* WWDG_Prescaler_2 - WWDG counter clock = (PCLK1/4096)/2
|
|
|
|
|
* WWDG_Prescaler_4 - WWDG counter clock = (PCLK1/4096)/4
|
|
|
|
|
* WWDG_Prescaler_8 - WWDG counter clock = (PCLK1/4096)/8
|
|
|
|
|
* @param {uint8_t} wr 设置上窗口值
|
|
|
|
|
* WindowValue - specifies the window value to be compared to the
|
|
|
|
|
* downcounter,which must be lower than 0x80
|
|
|
|
|
* @param {uint8_t} tr 设置计数器的值
|
|
|
|
|
* Counter - specifies the watchdog counter value,which must be a
|
|
|
|
|
* number between 0x40(64) and 0x7F(127)
|
|
|
|
|
* @return {*}
|
|
|
|
|
*/
|
|
|
|
|
void WWDG_Init(uint32_t prv, uint8_t wr, uint8_t tr)
|
|
|
|
|
{
|
|
|
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
|
|
|
|
|
|
|
|
|
|
WWDG_SetPrescaler(prv);
|
|
|
|
|
WWDG_SetWindowValue(wr);
|
|
|
|
|
WWDG_SetCounter(tr);
|
|
|
|
|
|
|
|
|
|
WWDG_Enable(WWDG_CNT);
|
|
|
|
|
WWDG_ClearFlag();
|
|
|
|
|
|
|
|
|
|
WWDG_NVIC_Config();
|
|
|
|
|
WWDG_EnableIT();
|
|
|
|
|
|
|
|
|
|
wwdg_wr = WWDG->CFGR & 0x7F;
|
|
|
|
|
|
|
|
|
|
LOG_D("WWDG_Feed_Init");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
|
* @fn WWDG_Feed
|
|
|
|
|
*
|
|
|
|
|
* @brief Feed WWDG.
|
|
|
|
|
*
|
|
|
|
|
* @return none
|
|
|
|
|
*/
|
|
|
|
|
void WWDG_Feed(void)
|
|
|
|
|
{
|
|
|
|
|
WWDG_SetCounter(WWDG_CNT);
|
|
|
|
|
// LOG_D("WWDG_Feed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WWDG_Loop(void)
|
|
|
|
|
{
|
|
|
|
|
wwdg_tr = WWDG->CTLR & 0x7F;
|
|
|
|
|
if(wwdg_tr < wwdg_wr)
|
|
|
|
|
{
|
|
|
|
|
WWDG_Feed();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static void wdg_thread_entry(void *param)
|
|
|
|
|
{
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
#if USED_IWDG
|
|
|
|
|
IWDG_Feed();
|
|
|
|
|
rt_thread_mdelay(IWDG_FEED_INTERVAL_MS);
|
|
|
|
|
#elif USED_WWDG
|
|
|
|
|
WWDG_Loop();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BSP_WDG_Init(void)
|
|
|
|
|
{
|
|
|
|
|
#if USED_IWDG
|
|
|
|
|
// t = 4000 * (IWDG计数时基 = LSI / 分频系数 = 40 KHz / 32 = 1250 Hz)= 3.2 s
|
|
|
|
|
IWDG_Init(IWDG_Prescaler_32, 4000); // 3.2s IWDG reset
|
|
|
|
|
#elif USED_WWDG
|
|
|
|
|
// WWDG counter clock = (PCLK1 / 4096) / 8 = (SystemCoreClock(96MHz) / 2) / 4096 / 8 ~= 1464 Hz
|
|
|
|
|
WWDG_Init(WWDG_Prescaler_8, 80, WWDG_CNT);
|
|
|
|
|
#endif
|
2025-01-18 12:07:23 +08:00
|
|
|
|
IWDG_Feed();
|
2024-12-30 11:50:48 +08:00
|
|
|
|
// /* 设置空闲线程钩子函数 */
|
|
|
|
|
// return rt_thread_idle_sethook(BSP_WDG_Loop);
|
|
|
|
|
if (RT_EOK == rt_thread_init(&wdg_thread,
|
|
|
|
|
"wdg_thread",
|
|
|
|
|
wdg_thread_entry,
|
|
|
|
|
RT_NULL,
|
|
|
|
|
&wdg_thread_stack[0],
|
|
|
|
|
sizeof(wdg_thread_stack),
|
|
|
|
|
WDG_THREAD_PRIORITY, WDG_THREAD_TIMESLICE))
|
|
|
|
|
{
|
|
|
|
|
rt_thread_startup(&wdg_thread);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#ifdef RT_USING_COMPONENTS_INIT
|
|
|
|
|
// INIT_DEVICE_EXPORT(BSP_WDG_Init);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if USED_WWDG
|
|
|
|
|
/*********************************************************************
|
|
|
|
|
* @fn WWDG_IRQHandler
|
|
|
|
|
*
|
|
|
|
|
* @brief This function handles WWDG exception.
|
|
|
|
|
*
|
|
|
|
|
* @return none
|
|
|
|
|
*/
|
|
|
|
|
void WWDG_IRQHandler(void)
|
|
|
|
|
{
|
|
|
|
|
GET_INT_SP();
|
|
|
|
|
/* enter interrupt */
|
|
|
|
|
rt_interrupt_enter();
|
|
|
|
|
|
|
|
|
|
WWDG_ClearFlag();
|
|
|
|
|
// WWDG_SetCounter(WWDG_CNT);
|
|
|
|
|
|
|
|
|
|
#error "此处加入在复位前需要处理的工作或保存数据"
|
|
|
|
|
|
|
|
|
|
/* leave interrupt */
|
|
|
|
|
rt_interrupt_leave();
|
|
|
|
|
FREE_INT_SP();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|