//---------------------------------------------------- //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. 日期: 2009-01-04 // 作者: lst // 新版本号: V1.0.0 // 修改说明: 原始版本 //------------------------------------------------------ #include "inc_os.h" static struct wdt_reg volatile * const pg_wdt_reg = (struct wdt_reg *)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_tree; 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_tree = (struct wdt_rsc*) rsc_add_tree_root(&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 = djy_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_tree->wdt_semp,cn_timeout_forever); if(rsc_get_son(&pg_wdt_rsc_tree->wdt_node)) //资源队列中已经有看门狗 { rsc_add_son(&pg_wdt_rsc_tree->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_tree->wdt_node,&wdt->wdt_node, sizeof(struct wdt_rsc),wdt_name); u32g_timeout_GCD = wdt->timeout; djy_event_pop(u16g_wdt_evtt,0,0,0); } semp_post(&pg_wdt_rsc_tree->wdt_semp); return wdt; } //----删除一只看门狗----------------------------------------------------------- //功能:删除一只存在的看门狗,重新计算狗溢出时间的最大公约数 //参数:wdt,被初始化的看门狗指针 //返回:无 //----------------------------------------------------------------------------- void wdt_delete(struct wdt_rsc *wdt) { if(wdt == NULL) return; semp_pend(&pg_wdt_rsc_tree->wdt_semp,cn_timeout_forever); rsc_del_node(&wdt->wdt_node); u32g_timeout_GCD = __wdt_get_GCD(); semp_post(&pg_wdt_rsc_tree->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 = djy_get_time(); while(1) { djy_timer_sync(u32g_timeout_GCD); new_tick = djy_get_time(); //取系统tick if(new_tick != old_tick) //看系统tick是否变化 { current_node = &pg_wdt_rsc_tree->wdt_node; //取看门狗的根资源指针 while(1) //遍历看门狗资源树并处理之 { //取下一个看门狗资源结点,需要用信号量保护 semp_pend(&pg_wdt_rsc_tree->wdt_semp,cn_timeout_forever); current_node = rsc_trave_scion(&pg_wdt_rsc_tree->wdt_node, current_node); semp_post(&pg_wdt_rsc_tree->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()) //狗叫 { djy_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) { }


Created by 2beanet Embedded Group : http://www.2beanet.com