linux怎么加硬件看门狗,嵌入式 在uboot中添加硬件看门狗小示例

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 |= (0x00120000);// 此处可修改为宏实现

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 &= ~30000000;

val |= 0x20000000;//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 |= 0x70000000;

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;

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值