2Uboot添加硬件看门狗
uboot中默认看门狗策略由两个宏CONFIG_HW_WATCHDOG和CONFIG_WATCHDOG来使能。
此策略是在代码执行中的不同阶段,添加喂狗代码。
这种喂狗方法会使代码很乱,uboot中到处都充斥的喂狗代码。另外这种方法对代码执行时间是敏感的,如果有段代码执行时间很长(如搬运code),则需要添加喂狗代码,很繁。
uboot的默认策略比较适合外部看门狗。
我们现在用的是CPU内部看门狗,直接无视上述两宏。我们要在watchdog interrupt中喂狗,即只在watchdog interrupt handler中喂狗,比较简便。
2.1Watchdog Interrupt Handler
修改文件uboot/cpu/mpc85xx/start.S,修改默认的handler
/* STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException) */
STD_EXCEPTION(0x0c00, WatchdogTimer, WatchdogHandler)
修改文件uboot/cpu/mpc85xx/traps.c,实现自己的handler
void WatchdogHandle(struct pt_regs*regs){
unsigned long msr;//turn off all interrpt, may need it, not sure
msr = get_msr();
set_msr(0);
mtspr(SPRN_TSR, mfspr(SPRN_TSR)| TSR_WIS);//喂狗
set_msr(msr);
}
2.2Watchdog 配置及开启
修改uboot/lib_ppc/board.c,添加watchdog的配置及开启例程
init_fnc_t*init_sequence[]=
{
………
WatchdogCreate,//配置例程 这两个例程越靠前越好,没有强制要求
WatchdogStart,//开启例程
……
};
修改uboot/common/cmd_bootm.c,添加watchdog的配置例程,开启例程和暂停例程
void WatchdogCreate(void)
{
unsigned long register val;
//01.no time base counting now
mtspr(SPRN_HID0, mfspr(SPRN_HID0)& ~HID0_TBEN);
//02.set timer period
val = mfspr(SPRN_TCR);
val &= ~(0xc0000000| 0x001e0000);// clear WP and WP_EXT
val |= (0x00);// 此处可修改为宏实现
mtspr(SPRN_TCR, val);
//03.set period unit
val = mfspr(SPRN_HID0);
val &= ~(0x00040000);
mtspr(SPRN_HID0, val);
//04. enable Watchdog timer interrupt
set_msr (get_msr()| MSR_CE);
//05: enable watchdog timer
mtspr(SPRN_TCR, mfspr(SPRN_TCR)| TCR_WIE);
//06: deal with sec timer out
val = mfspr(SPRN_TCR);
val &= ~;
val |= 0x;//reboot
mtspr(SPRN_TCR, val);
asm(“isync”);
}
void WatchdogStart(void)
{
//01. clear time base
mtspr(SPRN_TBWL, 0);
mtspr(SPRN_TBWU, 0);
//02. now time base counting…
mtspr(SPRN_HID0, mfspr(SPRN_HID0)| HID0_TBEN);
asm(“isync”);
}
void WatchdogStop(void){// just for test,need to modify and more test
//01. clear tsr
mtspr( SPRN_TSR, 0xf0000000);
//02.clear watchdog timer period
mtspr( SPRN_TCR, mfspr(SPRN_TCR)& ~(0xc0000000| 0x001e0000) );
//03.disable watchdog timer
mtspr(SPRN_TCR, mfspr(SPRN_TCR)& ~(TCR_WIE));
}
2.3reset命令的实现
现在我们可以用wathdog来实现重启命令reset。
修改文件 uboot/cpu/mpc85xx/cpu.c
int do_reset(cmd_tbl_t *cmdtp, bd_t*bd, int flag, int argc,char *argv[])
{
#if 0 // leon del for HRESET
/*
* Initiate hard reset in debug control register DBCR0
* Make sure MSR[DE] = 1
*/
unsigned long val;
val = mfspr(DBCR0);
val |= 0x;
mtspr(DBCR0,val);
#endif
//leon add: just disable first time out,second time out will reset send HRESET_REQ
mtspr(SPRN_TCR, mfspr(SPRN_TCR)& ~TCR_WIE);
return 1;
}
2.4FLASH操作关闭看门狗 (??)
打开看门狗的话,对Flash进行写操作时,会使uboot崩溃。具体原因还没找到,一个比较靠谱的猜想是watchdog interrpt handler代码执行还会去flash中读指令。可是当你敲erase bank 1命令的时候,代码早就搬运到RAM中了啊,无解。。。望牛人指点,感激不尽。
所以,当对flash进行写操作指令前,首先要敲自己加的命令,如timer_stop,来关闭watchdog。
写操作完成后,敲命令timer_start,来启动watchdog。
命令timer_stop中再去调函数WatchdogStop().命令timer_start中调用WatchdogCreate()和WatchdogStart()
具体命令如何添加,参考
uboot添加命令,最快最简山寨法
3Linux添加硬件看门狗
Linux中watchdog机制是靠uboot传来的wdt和wdt_period启动参数来使能的。
wdt为1就使能watchdog机制,0就禁止;
wdt_perid就是上面所说的period值了。
WDT的配置和开启是在wdt驱动里实现的,入口函数是booke_wdt_init()
Linux的watchdog interrupt handler函数WatchdogException()会自旋直至CPU硬复位。
那我们在Decrementer Interrupt handler中喂狗,即在do_timer()中喂狗。
修改文件linux-2.6.24/kernel/timer.c
externint stop_feed;
void do_timer(unsignedlong ticks)
{
if( likely(stop_feed== 0))
mtspr(SPRN_TSR, mfspr(SPRN_TSR)| TSR_WIS);//喂狗
jiffies_64 += ticks;
update_times(ticks);
}
相应的reboot命令的实现就简单多了,文件linux-2.6.24/arch/ppc/syslib/ppc85xx_setup.c
void mpc85xx_restart(char*cmd){
local_irq_disable();
myabort();
}
int stop_feed= 0;
void myabort(void){
stop_feed = 1;
}
修改到此结束。
当我们敲reboot命令后,do_timer()中停止喂狗,watchdog timer first time out后,会执行Watchdog interrupt handler函数 WatchdogException(),then spin until second timeout occur,then reboot。
//文件linux-2.6.24/arch/ppc/kernel/head_fsl_booke.S
CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException)
//文件linux-2.6.24/arch/ppc/kernel/traps.c
void WatchdogException(struct pt_regs*regs)
{
printk (KERN_EMERG “PowerPC Book-E Watchdog Exception\n”);
WatchdogHandler(regs);
}
/*
* Default handler for a Watchdog exception,
* spins until a reboot occurs 这句和CRITICAL_EXCEPTION宏有关
*/
void __attribute__((weak)) WatchdogHandler(struct pt_regs*regs)
{
/* Generic WatchdogHandler, implement your own */
mtspr(SPRN_TCR, mfspr(SPRN_TCR)&(~TCR_WIE));//
return;
}
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227843.html原文链接:https://javaforall.net
