GNU ARM汇编--(八)s3c2440的watchdog

来源:互联网 发布:淘宝祛痘产品 编辑:程序博客网 时间:2024/06/06 09:44

        从单片机起,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进行分频,接下来还会再次分频.


    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 resetcopyleft@  dndxhej@gmail.com*/.equ   NOINT, 0xc0.equ GPBCON,0x56000010  @led.equGPBDAT,0x56000014  @led.equ   GPBUP,        0x56000018    @led.equ GPFCON, 0x56000050  @interrupt config.equEINTMASK, 0x560000a4.equ EXTINT0,  0x56000088.equ EXTINT1,  0x5600008c.equ EXTINT2,  0x56000090.equINTMSK, 0x4A000008.equ   EINTPEND,     0x560000a8.equSUBSRCPND,  0x4a000018 .equINTSUBMSK,  0x4a00001c.equ   SRCPND,   0X4A000000.equ   INTPND,   0X4A000010.equ GPB5_out,  (1<<(5*2))  .equ GPB6_out,  (1<<(6*2))  .equ GPB7_out,  (1<<(7*2))  .equ GPB8_out,  (1<<(8*2))        .equ GPBVALUE,    (GPB5_out | GPB6_out | GPB7_out | GPB8_out)  .equLOCKTIME, 0x4c000000.equMPLLCON, 0x4c000004.equUPLLCON, 0x4c000008.equM_MDIV, 92.equ   M_PDIV, 1.equM_SDIV, 1.equU_MDIV, 56.equ   U_PDIV, 2.equU_SDIV, 2.equCLKDIVN, 0x4c000014.equDIVN_UPLL, 0.equHDIVN,1.equPDIVN,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:bresetldr     pc, _undefined_instructionldr pc, _software_interruptldrpc, _prefetch_abortldrpc, _data_abortldrpc, _not_used@birqldr pc, _irqldr 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,0xdeadbeefreset:ldr     r3, =WTCONmovr4, #0x0                     strr4, [r3]@ disable watchdog    ldrr0, =GPBCONldrr1, =0x15400strr1, [r0]ldrr2, =GPBDATldrr1, =0x160strr1, [r2]bl clock_setupbl delay    msr cpsr_c, #0xd2 @进入中断模式    ldr sp, =3072 @中断模式的栈指针定义    msr cpsr_c, #0xd3 @进入系统模式    ldr sp, =4096 @设置系统模式的栈指针@--------------------------------------------ldrr0, =GPBUPldrr1, =0x03f0  strr1, [r0]         ldrr0, =GPFCONldrr1, =0x2ea@0x2    strr1, [r0]  ldrr0, =EXTINT0@ldrr1, =0x8f888@0x0@0x8f888      @~(7|(7<<4)|(7<<8)|(7<<16))   //低电平触发中断ldrr1, =0xafaaa@0x0@0x8f888      //下降沿触发中断strr1, [r0]  ldrr0, =EINTPENDldrr1, =0xf0@0b10000strr1, [r0]  ldrr0, =EINTMASKldrr1, =0x00@0b00000strr1, [r0]  ldrr0, =SRCPNDldrr1, =0x3ff@0x1@0b11111strr1, [r0]  ldrr0, =SUBSRCPNDldrr1, =0x1<<13strr1, [r0]  ldrr0, =INTPNDldrr1, =0x3ff@0x1@0b11111strr1, [r0]  ldrr0, =INTSUBMSKldrr1, =0x0<<13strr1, [r0]  ldrr0, =INTMSKldrr1, =0xfffff000@0b00000strr1, [r0]  MRS r1, cpsrBIC r1, r1, #0x80MSR cpsr_c, r1bl     mainirq:sub lr,lr,#4stmfdsp!,{r0-r12,lr}bl irq_isrldmfd  sp!,{r0-r12,pc}^ irq_isr:ldrr2, =GPBDATldrr1, =0x0e0strr1, [r2]         ldr r0,=EINTPEND         ldr r1,=0xf0         str r1,[r0] ldrr0, =SRCPNDldrr1, =0x3ff@0b11111strr1, [r0]  ldrr0, =SUBSRCPNDldrr1, =0x1<<13strr1, [r0]  ldrr0, =INTPNDldrr1, =0x3ff@0b11111strr1, [r0]  mov pc,lrdelay:ldr r3,=0xffffffdelay1:sub r3,r3,#1cmp r3,#0x0bne delay1mov pc,lrclock_setup:ldr r0,=LOCKTIMEldr r1,=0xffffffffstr r1, [r0]ldr r0,=CLKDIVNldr r1,=(DIVN_UPLL<<3) | (HDIVN<<1) | (PDIVN<<0)str r1, [r0]ldr r0,=UPLLCONldr r1,=(U_MDIV<<12) | (U_PDIV<<4) | (U_SDIV<<0)   @Fin=12M  UPLL=48Mstr r1, [r0]nopnopnopnopnopnopnopldr r0,=MPLLCONldr r1,=(M_MDIV<<12) | (M_PDIV<<4) | (M_SDIV<<0)    @Fin=12M  FCLK=400Mstr r1, [r0]mov pc,lrmain:ldrr0, =WTDATldrr1, =Count_reloadstrr1, [r0]ldrr0, =WTCNTldrr1, =Countstrr1, [r0]ldrr0, =WTCONldrr1, =(Pre_scaler<<8) | (wd_timer<<5) | (clock_select<<3) | (int_gen<<2) | (reset_enable)strr1, [r0]ledloop:ldr r1,=0x1c0str r1,[r2]bl delayldr r1,=0x1a0str r1,[r2]bl delayldr r1,=0x160str r1,[r2]bl delayldr r1,=0x0e0str r1,[r2]bl delayb ledloopundefined_instruction:nopsoftware_interrupt:nopprefetch_abort:nopdata_abort:nopnot_used:nopfiq:nop

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

        稍微该一下上面的代码:

.equ    int_gen,    0     @关中断
.equ    reset_enable,   1  @打开重启信号

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

如果在循环中加入:

ldrr0, =WTCNT     @喂狗
ldr r1, =Count
str r1, [r0]

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

原创粉丝点击