📄 wdt.c
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009, lst.
//版权所有 (C), 2004-2009, lst.
//所属模块: 看门狗模块
//作者:lst
//版本:V1.0.0
//文件描述: 看门狗模块
//其他说明:
//修订历史:
// 2. 日期:2009-02-25
// 作者:lst
// 新版本号:1.0.1
// 修改说明: 修正了wdt_create函数的一处错误,该bug由网友sniper提交
// 1. 日期:
// 作者:
// 新版本号:
// 修改说明:
//------------------------------------------------------
#include "inc_os.h"
static struct hard_reg_wdt volatile * const pg_wdt_reg
= (struct hard_reg_wdt *)0x53000000;
static struct wdt_rsc tg_wdt_rsc_pool[cn_wdt_limit];
static struct mem_cell_pool *pg_wdt_rsc_pool; //内存池头指针。
static struct wdt_rsc *pg_wdt_rsc;
static uint32_t u32g_timeout_GCD; //看门狗溢出时间的最大公约数
static uint16_t u16g_wdt_evtt;
void __wdt_init_hard(void);
void __wdt_star(void);
void __wdt_reset(void);
void __wdt_clear(void);
//----初始化看门狗模块--------------------------------------------------------
//功能:初始化看门狗模块,建立根资源结点,创建信号量(用于保护看门狗资源队列)
//参数:无
//返回:true = 成功创建,false = 创建失败。因为无需申请动态资源,总是会成功
//----------------------------------------------------------------------------
bool_t module_init_wdt(void)
{
static struct wdt_rsc wdt_root;
__wdt_init_hard();
pg_wdt_rsc_pool = mb_create(&tg_wdt_rsc_pool,cn_wdt_limit,
sizeof(struct wdt_rsc),"wdt pool");
//建立根资源节点
pg_wdt_rsc = (struct wdt_rsc*)
rsc_add_root_node(&wdt_root.wdt_node,sizeof(struct wdt_rsc),"watch dog");
__semp_create_knl(&wdt_root.wdt_semp,1,1,"watch dog");
u32g_timeout_GCD = 1;
u16g_wdt_evtt = y_evtt_regist(true,false,cn_prio_wdt,1,wdt_check,
100,"wdt service");
if(u16g_wdt_evtt != cn_invalid_evtt_id)
return true;
else
return false;
}
//----求新的最大公约数---------------------------------------------------------
//功能: 加入溢出周期为new_num的看门狗以后,重新计算看门狗溢出周期的最大公约数
//参数:new_num,新看门狗的溢出周期
//返回:最大公约数
//----------------------------------------------------------------------------
uint32_t __wdt_inc_GCD(uint32_t new_num)
{
return 1;
}
//----重新计算最大公约数-------------------------------------------------------
//功能: 删除一只看门狗以后,需重新计算最大公约数
//参数:无
//返回:最大公约数
//----------------------------------------------------------------------------
uint32_t __wdt_get_GCD(void)
{
return 1;
}
//----添加一只看门狗-----------------------------------------------------------
//功能:创建一个看门狗
//参数:wdt,被初始化的看门狗指针
// judge,用户提供的用于判断是否狗叫的函数指针
// timeout,调用judge的时间间隔,单位是毫秒,不能为0,将被向上调整为
// cn_tick_ms的整数倍
//返回:无
//-----------------------------------------------------------------------------
struct wdt_rsc * wdt_create(bool_t (*judge)(void),
uint32_t (*yip_remedy)(void),
uint32_t timeout,char *wdt_name)
{
struct wdt_rsc *wdt;
if(judge == NULL)
return NULL;
wdt = mb_malloc(pg_wdt_rsc_pool,0);
if(wdt == NULL)
return NULL;
wdt->judge = judge;
wdt->yip_remedy = yip_remedy;
if(wdt->timeout == 0)
wdt->timeout = 1;
wdt->timeout = (timeout + cn_tick_ms -1)/cn_tick_ms;
semp_pend(&pg_wdt_rsc->wdt_semp,cn_timeout_forever);
if(rsc_get_son(&pg_wdt_rsc->wdt_node)) //资源队列中已经有看门狗
{
rsc_add_son(&pg_wdt_rsc->wdt_node,&wdt->wdt_node,
sizeof(struct wdt_rsc),wdt_name);
u32g_timeout_GCD = __wdt_inc_GCD(wdt->timeout);
}else //这是添加的第一只看门狗
{
rsc_add_son(&pg_wdt_rsc->wdt_node,&wdt->wdt_node,
sizeof(struct wdt_rsc),wdt_name);
u32g_timeout_GCD = wdt->timeout;
y_event_pop(u16g_wdt_evtt,0,0,0);
}
semp_post(&pg_wdt_rsc->wdt_semp);
return wdt;
}
//----删除一只看门狗-----------------------------------------------------------
//功能:删除一只存在的看门狗,重新计算狗溢出时间的最大公约数
//参数:wdt,被初始化的看门狗指针
//返回:无
//-----------------------------------------------------------------------------
void wdt_delete(struct wdt_rsc *wdt)
{
if(wdt == NULL)
return;
semp_pend(&pg_wdt_rsc->wdt_semp,cn_timeout_forever);
rsc_del_node(&wdt->wdt_node);
u32g_timeout_GCD = __wdt_get_GCD();
semp_post(&pg_wdt_rsc->wdt_semp);
mb_free(pg_wdt_rsc_pool,wdt);
return;
}
//----看门狗事件处理函数-------------------------------------------------------
//功能:本事件除非被信号量阻塞,一致就绪,持续监视系统tick,只要tick有变化,就
// 扫描一遍所有看门狗,按各看门狗设定的时间间隔调用judge函数,如果发现异常,
// 就调用“狗叫善后”函数,按善后函数的指示复位或者清除看门狗。如果没有发现
// 异常,就清除看门狗。
//参数:my_event,看门狗事件指针。
//返回:无
//-----------------------------------------------------------------------------
void wdt_check(struct event_script *my_event)
{
static uint32_t old_tick,new_tick;
struct rsc_node *current_node;
struct wdt_rsc *wdt;
uint32_t wdt_action;
old_tick = y_get_time();
while(1)
{
y_timer_sync(u32g_timeout_GCD);
new_tick = y_get_time(); //取系统tick
if(new_tick != old_tick) //看系统tick是否变化
{
current_node = &pg_wdt_rsc->wdt_node; //取看门狗的根资源指针
while(1) //遍历看门狗资源树并处理之
{
//取下一个看门狗资源结点,需要用信号量保护
semp_pend(&pg_wdt_rsc->wdt_semp,cn_timeout_forever);
current_node = rsc_trave_scion(&pg_wdt_rsc->wdt_node,
current_node);
semp_post(&pg_wdt_rsc->wdt_semp);
if(current_node == NULL) //已经遍历完所有看门狗节点
break;
else //尚未遍历完所有看门狗节点
{
wdt = (struct wdt_rsc *)current_node;
//看时钟是否已经跨过timeout时间点
if(new_tick / wdt->timeout != old_tick / wdt->timeout)
{
if(! wdt->judge()) //狗叫
{
y_error_login(enum_wdt_yip,"watch dog yip");
wdt_action = wdt->yip_remedy(); //调用善后程序
switch(wdt_action)
{
case cn_wdt_action_none:break;
case cn_wdt_action_reset: //需复位
{
__wdt_reset();
}break;
default:break;
}
}
}
}
}
old_tick = new_tick;
}
__wdt_clear(); //清除看门狗
}
}
//以下函数移植敏感
//----看门狗硬件初始化---------------------------------------------------------
//功能:看门狗硬件初始化
//参数:无
//返回:无
//-----------------------------------------------------------------------------
void __wdt_init_hard(void)
{
}
void __wdt_star(void)
{
}
void __wdt_reset(void)
{
while(1);
}
void __wdt_clear(void)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -