linux watch cp,s3c2440的watchdog

从单片机起,watchdog就是必不可少的.在各种应用环境中,程序很可能跑飞或死掉,这时候就需要通过watchdog来保证整个系统重新恢复到正常状态.

照旧,给出s3c2440的datasheet说明:

概述:

watchdog timer用于由于噪声或者系统错误引起的程序跑飞了的情况下恢复处理器的正常操作.它可以被用作一个可以请求中断服务的普通16bit的内部定时器.watchdog timer产生128 PCLK的重启信号.

特点:

有中断请求的普通内部定时器模式

当定时器计数为0(超时)时,产生内部的长达128PCLK周期的重启信号

watchdog timer的操作:

F18-1显示watchdog timer的功能框图.watchdog timer只使用PCLK作为它的时钟源.PCLK先由一个8bit的prescaler进行分频,接下来还会再次分频.

ae3bcc7a69c005e93e67c15a014afefe.png

Prescaler的值和分频因子由watchdog timer控制寄存器(WTCON)决定.有效的预分频值的范围是(0--2^8-1),因为是8bit的分频器.分频因子可选为16,32,64,128.

WTDAT&WTCNT

一旦watchdog timer启用了,watchdog timer数据寄存器(WTDAT)的值不会自动的重新加载到计数寄存器(WTCNT).所以,在watchdog timer启动前一定要向watchdog timer的计数寄存器(WTCNT)中写入一个初始值.

watchdog timer special registers

WTCON

WTCON允许user打开或关闭watchdog timer,从4个不同的源中选择时钟信号,开关中断以及开关watchdog timer的输出.watchdog timer用来s3c2440启动后的重启,如果不想处理器重启,watchdog timer要被禁用.在loader开始时,watchdog timer又没初始化的时候,应该将watchdog timer禁用.

如果user想使用watchdog timer提供的正常定时器功能,那就打开中断,关闭watchdog timer.

Register   Address     R/W               Description            Reset Value

WTCON      0x53000000  R/W    Watchdog timer control register      0x8021

Bit                  Descrition                        Initial State

Prescaler value         [15:8]     预分频的值(0--255)                        0x80

Watchdog timer           [5]        watchdog timer的开关位                1(开)

Clock select               [4:3]      时钟分频因子 00:16 01:32               00

10:64 11:128

Interrupt generation     [2]       中断的开关位                                     0

Reset enable/diaable   [0]       输出重启信号的开关                         1

WTDAT

WTDAT用来指定超时的期限.在最开始的操作中WTDAT的值不会自动的加载到计数器中.使用初始值0x8000就可以驱动第一次超时.以后的话,WTDAT的值就会自动重加载到WTCNT中.

Register         Address       R/W            Description                        Reset Value

WTDAT        0x53000004  R/W    Watchdog timer data register        0x8000

Bit                Description                 Initial State

Count reload value    [15:0]         重加载的计数值                 0x8000

WTCNT

WTCNT包含正常操作下watchdog timer的当前计数值.值得注意的是,在watchdog timer最初被启用的时候,WTDAT的内容不会自动的加载到WTCNT中,所以WTCNT一定要给一个初始值.

Register     Address     R/W            Description                                   Reset Value

WTCNT        0x53000008  R/W    Watchdog timer count register          0x8000

Bit                Description               Initial State

Count value          [15:0]           定时器的当前计数值        0x8000

我们先将watchdog的输出重启信号的开关关掉,将中断打开,把watchdog timer当一个普通的定时器来用.设计如下:

/*

watchdog timer with disable reset

copyleft@  dndxhej@gmail.com

*/

.equ   NOINT, 0xc0

.equ    GPBCON, 0x56000010      @led

.equ    GPBDAT, 0x56000014      @led

.equ   GPBUP,        0x56000018    @led

.equ    GPFCON, 0x56000050      @interrupt config

.equ    EINTMASK, 0x560000a4

.equ    EXTINT0,  0x56000088

.equ    EXTINT1,  0x5600008c

.equ    EXTINT2,  0x56000090

.equ    INTMSK,  0x4A000008

.equ   EINTPEND,     0x560000a8

.equ    SUBSRCPND,  0x4a000018

.equ    INTSUBMSK,  0x4a00001c

.equ   SRCPND,   0X4A000000

.equ   INTPND,   0X4A000010

.equ GPB5_out,  (1<

.equ GPB6_out,  (1<

.equ GPB7_out,  (1<

.equ GPB8_out,  (1<

.equ GPBVALUE,    (GPB5_out | GPB6_out | GPB7_out | GPB8_out)

.equ    LOCKTIME, 0x4c000000

.equ    MPLLCON, 0x4c000004

.equ    UPLLCON, 0x4c000008

.equ    M_MDIV, 92

.equ   M_PDIV, 1

.equ    M_SDIV, 1

.equ    U_MDIV, 56

.equ   U_PDIV, 2

.equ    U_SDIV, 2

.equ    CLKDIVN, 0x4c000014

.equ    DIVN_UPLL, 0

.equ    HDIVN,  1

.equ    PDIVN,  1    @FCLK : HCLK : PCLK = 1:2:4

.equ    WTCON,  0x53000000

.equ    Pre_scaler,  249

.equ    wd_timer,   1

.equ    clock_select,   00   @316

.equ    int_gen,    1     @开中断

.equ    reset_enable,   0  @关掉重启信号

.equ    WTDAT,0x53000004

.equ    Count_reload,50000    @定时器定为2S PCLK = 100M   PCLK/(Pre_scaler+1)/clock_select = 100M/(249+1)/16=25k   50000/25k=2s

.equ    WTCNT,0x53000008

.equ    Count,50000

.global _start

_start:     b   reset

ldr     pc, _undefined_instruction

ldr     pc, _software_interrupt

ldr pc, _prefetch_abort

ldr pc, _data_abort

ldr pc, _not_used

@b  irq

ldr     pc, _irq

ldr     pc, _fiq

_undefined_instruction:     .word undefined_instruction

_software_interrupt:        .word software_interrupt

_prefetch_abort:        .word prefetch_abort

_data_abort:            .word data_abort

_not_used:          .word not_used

_irq:               .word irq

_fiq:               .word fiq

.balignl 16,0xdeadbeef

reset:

ldr     r3, =WTCON

mov r4, #0x0

str r4, [r3]    @ disable watchdog

ldr r0, =GPBCON

ldr r1, =0x15400

str r1, [r0]

ldr r2, =GPBDAT

ldr r1, =0x160

str r1, [r2]

bl clock_setup

bl delay

msr cpsr_c, #0xd2 @进入中断模式

ldr sp, =3072 @中断模式的栈指针定义

msr cpsr_c, #0xd3 @进入系统模式

ldr sp, =4096 @设置系统模式的栈指针

@--------------------------------------------

ldr r0, =GPBUP

ldr r1, =0x03f0

str r1, [r0]

ldr r0, =GPFCON

ldr r1, =0x2ea@0x2

str r1, [r0]

ldr r0, =EXTINT0

@ldr    r1, =0x8f888@0x0@0x8f888      @~(7|(7<<4)|(7<<8)|(7<<16))//低电平触发中断

ldr r1, =0xafaaa@0x0@0x8f888//下降沿触发中断

str r1, [r0]

ldr r0, =EINTPEND

ldr r1, =0xf0@0b10000

str r1, [r0]

ldr r0, =EINTMASK

ldr r1, =0x00@0b00000

str r1, [r0]

ldr r0, =SRCPND

ldr r1, =0x3ff@0x1@0b11111

str r1, [r0]

ldr r0, =SUBSRCPND

ldr r1, =0x1<<13

str r1, [r0]

ldr r0, =INTPND

ldr r1, =0x3ff@0x1@0b11111

str r1, [r0]

ldr r0, =INTSUBMSK

ldr r1, =0x0<<13

str r1, [r0]

ldr r0, =INTMSK

ldr r1, =0xfffff000@0b00000

str r1, [r0]

MRS r1, cpsr

BIC r1, r1, #0x80

MSR cpsr_c, r1

bl     main

irq:

sub     lr,lr,#4

stmfd   sp!,{r0-r12,lr}

bl irq_isr

ldmfd  sp!,{r0-r12,pc}^

irq_isr:

ldr r2, =GPBDAT

ldr r1, =0x0e0

str r1, [r2]

ldr r0,=EINTPEND

ldr r1,=0xf0

str r1,[r0]

ldr r0, =SRCPND

ldr r1, =0x3ff@0b11111

str r1, [r0]

ldr r0, =SUBSRCPND

ldr r1, =0x1<<13

str r1, [r0]

ldr r0, =INTPND

ldr r1, =0x3ff@0b11111

str r1, [r0]

mov pc,lr

delay:

ldr r3,=0xffffff

delay1:

sub r3,r3,#1

cmp r3,#0x0

bne delay1

mov pc,lr

clock_setup:

ldr r0,=LOCKTIME

ldr r1,=0xffffffff

str r1, [r0]

ldr r0,=CLKDIVN

ldr r1,=(DIVN_UPLL<<3) | (HDIVN<<1) | (PDIVN<<0)

str r1, [r0]

ldr r0,=UPLLCON

ldr r1,=(U_MDIV<<12) | (U_PDIV<<4) | (U_SDIV<<0)   @Fin=12M  UPLL=48M

str r1, [r0]

nop

nop

nop

nop

nop

nop

nop

ldr r0,=MPLLCON

ldr r1,=(M_MDIV<<12) | (M_PDIV<<4) | (M_SDIV<<0)    @Fin=12M  FCLK=400M

str r1, [r0]

mov pc,lr

main:

ldr r0, =WTDAT

ldr r1, =Count_reload

str r1, [r0]

ldr r0, =WTCNT

ldr r1, =Count

str r1, [r0]

ldr r0, =WTCON

ldr r1, =(Pre_scaler<<8) | (wd_timer<<5) | (clock_select<<3) | (int_gen<<2) | (reset_enable)

str r1, [r0]

ledloop:

ldr r1,=0x1c0

str r1,[r2]

bl delay

ldr r1,=0x1a0

str r1,[r2]

bl delay

ldr r1,=0x160

str r1,[r2]

bl delay

ldr r1,=0x0e0

str r1,[r2]

bl delay

b ledloop

undefined_instruction:

nop

software_interrupt:

nop

prefetch_abort:

nop

data_abort:

nop

not_used:

nop

fiq:

nop

程序实现的是:一个正常的流水灯,定时器每隔2s触发一次中断,中断处理中点亮第四个LED.

稍微该一下上面的代码:

.equ    int_gen,    0     @关中断

.equ    reset_enable,   1  @打开重启信号

打开重启信号,则可以看到每隔2s系统就重启一次.

如果在循环中加入:

ldrr0, =WTCNT     @喂狗

ldr r1, =Count

str r1, [r0]

那么,这又是一个标准的流水灯了.而且是有watchdog保护的流水灯了.0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值