分类: LINUX
2011-01-17 19:27:17
整个状态机是由TSR(Timer State Register)寄存器的两个field bit,[ENW,WIS ]来控制的。
Bit field |
解释 |
||
ENW |
此bit若置1,代表Watchdog Timer当前是使能状态 |
||
WIS |
此bit置1,代表Watchdog Interrupt发生过 |
硬件会不断地周期地对[ENW,WIS]进行set操作,软件可以对[ENW,WIS]进行clear操作,软硬件结合起来维护此状态机。
简单来说就是,WDT的超时分为两种情况:
状态[1,0]时发生time out,是第一次超时,将状态置为[1,1],并触发watchdog 中断(可配)
状态[1,1]时发生time out,是第二次超时,会发出HRESET_REQ,请求CPU硬复位(可配)
事实上,WDT的两次超时触发的动作都是可配置的,通过TCR(Timer Control Register)和MSR(Machine State Register)
第一次超时,会更新状态为[1,1],TCR[WIE]和MSR[CE]若被set则触发中断,否则不触发中断
第二次超时,会根据TCR[WRC]来选择进行何种操作。
TCR[WRC] |
解释 |
00 |
Do nothing |
01 |
触发Machine Check中断(前提是MSR[ME]使能) |
10 |
发出HRESET_REQ信号,请求硬复位HRESET |
11 |
保留 |
一个参考流程如下:
1.为产生watchdog interrupt,对TCR[WIE],MSR[CE]进行set;为使CPU硬复位,使TCR[WRC]为[1,0]
2. 当前状态[0,0],此为CPU上电后的初始状态
3.一个周期后状态变为[1,0],注意 [0,0] ->[1,0]什么都不做
4.一个周期后状态变为[1,1],触发watchdog interrupt
5.watchdog interrupt hanlder对状态进行clear操作(“喂狗”),状态变为[0,0],接下来又从步骤2开始
6.用户敲重启命令(如reboot),对TCR[WIE]进行clear,使watchdoginterrupt不触发,停止“喂狗”
7.一个周期后超时[1,0],又一个周期后超时[1,1],又一个周期超时,CPU发出HRESET_REQ
8.外部芯片(如CPLD)收到HRESET_REQ,发HRESET给CPU
9.CPU收到HRESET,进行硬复位
E500内部有个计数器Time Base Register。这个计数器由HID0(Hardware Implementation-Dependent Register 0)和TCR控制。
Time Base Register是由TBU(Time Base Upper)和TBL(Time Base Lower)组成,即一个64bit的值。
寄存器的相关配置bit
Bit field |
解释 |
SEL_TBCLK |
若0,Time base is based on the processor clock,erery 8 clock加1 若1,Time base is based on the TBCLK (RTC) input,RTC上升沿加1 |
TBEN |
若1,计数器使能,Time Base Register开始累加。 若0,计时器停止累加。 |
当Time Base Register的某位bit由0变1,则代表发生一次time out。
而TCR的[WPEXT, WP]就是来定义这个bit的。如
WPTXT WP
1001 00 0b(1001 00) = 0x(24) = 36
这个36就是所谓的period值,用于触发time out的bit的位置就是 63-36+1 = 28。
当HID0[SEL_TBCLK]为1时,即选用CCB(假设为266MHz)作为计时基准时,有如下:
·在0.5倍timeout时间后,第28bit将被由0变1,使状态由[0,0]变为[1,0],什么事都不发生
·在1倍timeout时间后,第28bit又由0变1,使状态由[1,0]变[1,1],第一次超时
·在[1,1]状态下,1倍timeout时间后,第28bit由0变1,第二次超时
第一次超时所花时间:
1.5 X (2^28) / (CCB /8) = 12.11 秒
第二次超时所处时间:
2.5 X (2^28) / (CCB /8) = 20.18 秒uboot中默认看门狗策略由两个宏CONFIG_HW_WATCHDOG和CONFIG_WATCHDOG来使能。
此策略是在代码执行中的不同阶段,添加喂狗代码。
这种喂狗方法会使代码很乱,uboot中到处都充斥的喂狗代码。另外这种方法对代码执行时间是敏感的,如果有段代码执行时间很长(如搬运code),则需要添加喂狗代码,很繁。
uboot的默认策略比较适合外部看门狗。
我们现在用的是CPU内部看门狗,直接无视上述两宏。我们要在watchdog interrupt中喂狗,即只在watchdog interrupt handler中喂狗,比较简便。
修改文件uboot/cpu/mpc85xx/start.S,修改默认的handler
修改文件uboot/cpu/mpc85xx/traps.c,实现自己的handler
2.2 Watchdog 配置及开启
修改uboot/lib_ppc/board.c,添加watchdog的配置及开启例程
修改uboot/common/cmd_bootm.c,添加watchdog的配置例程,开启例程和暂停例程
现在我们可以用wathdog来实现重启命令reset。
修改文件 uboot/cpu/mpc85xx/cpu.c
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
相应的reboot命令的实现就简单多了,文件linux-2.6.24/arch/ppc/syslib/ppc85xx_setup.c
当我们敲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
//文件linux-2.6.24/arch/ppc/kernel/traps.c