197 lines
5.4 KiB
C
197 lines
5.4 KiB
C
|
||
#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
|
||
IWDG_Feed();
|
||
// /* 设置空闲线程钩子函数 */
|
||
// 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
|
||
|