2440中使用看门狗定时器作为普通定时器

来源:互联网 发布:2012年西部决赛数据 编辑:程序博客网 时间:2024/05/22 00:32

好吧,看s3c2440的看门狗看了好长时间,因为看门一般很少使用,所以我就想让看门狗作为一般的定时器来触发中断,简单一点,就做一个LED灯的定时闪烁。看了好多资料,百度、数据手册中英文版、学习板光盘资料。。。。。。确实是一个纠结的过程,但是最后懂了收获到的也是满满的快乐。

我要说的:

1、不能全相信手册,手册上说看门狗计时器作为一般定时器时,应使能中断并且禁止看门狗定时器。然而实践证明是不对的;应该使能中断并且使能看门狗定时器,同时禁止看门狗的复位功能。主程序中的rWTCON |= (1<<5)|(1<<2);就是见证。
2、清中断简单粗暴就行,不需要那么多的函数。

       rSRCPND = 0x1<<9;       rSUBSRCPND = 0x1<<13;       rINTPND = 0x1<<9;


以下贴出代码:

2440init.s

GET option.incGET memcfg.incGET 2440addr.incBIT_SELFREFRESH EQU(1<<22);Pre-defined constantsUSERMODE    EQU 0x10FIQMODE     EQU 0x11IRQMODE     EQU 0x12SVCMODE     EQU 0x13ABORTMODE   EQU 0x17UNDEFMODE   EQU 0x1bMODEMASK    EQU 0x1fNOINT       EQU 0xc0;The location of stacksUserStackEQU(_STACK_BASEADDRESS-0x3800);0x33ff4800 ~SVCStackEQU(_STACK_BASEADDRESS-0x2800);0x33ff5800 ~UndefStackEQU(_STACK_BASEADDRESS-0x2400);0x33ff5c00 ~AbortStackEQU(_STACK_BASEADDRESS-0x2000);0x33ff6000 ~IRQStackEQU(_STACK_BASEADDRESS-0x1000);0x33ff7000 ~FIQStackEQU(_STACK_BASEADDRESS-0x0);0x33ff8000 ~;Check if tasm.exe(armasm -16 ...@ADS 1.0) is used.GBLL    THUMBCODE[ {CONFIG} = 16THUMBCODE SETL  {TRUE}    CODE32 |THUMBCODE SETL  {FALSE}    ] MACROMOV_PC_LR [ THUMBCODE    bx lr |    movpc,lr ]MEND MACROMOVEQ_PC_LR [ THUMBCODE        bxeq lr |    moveq pc,lr ]MEND MACRO$HandlerLabel HANDLER $HandleLabel$HandlerLabelsubsp,sp,#4;decrement sp(to store jump address)stmfdsp!,{r0};PUSH the work register to stack(lr does not push because it return to original address)ldr     r0,=$HandleLabel;load the address of HandleXXX to r0ldr     r0,[r0] ;load the contents(service routine start address) of HandleXXXstr     r0,[sp,#4]      ;store the contents(ISR) of HandleXXX to stackldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)MENDIMPORT  Main    ; The main entry of mon programAREA    Init,CODE,READONLYENTRYEXPORT__ENTRY__ENTRYResetEntry;1)The code, which converts to Big-endian, should be in little endian code.;2)The following little endian code will be compiled in Big-Endian mode.;  The code byte order should be changed as the memory bus width.;3)The pseudo instruction,DCD can not be used here because the linker generates error.ASSERT:DEF:ENDIAN_CHANGE[ ENDIAN_CHANGE    ASSERT  :DEF:ENTRY_BUS_WIDTH       [ ENTRY_BUS_WIDTH=16andeqr14,r7,r0,lsl #20   ;DCD 0x0007ea00    ]    [ ENTRY_BUS_WIDTH=8streqr0,[r0,-r10,ror #1] ;DCD 0x070000ea    ]|    bResetHandler    ]bHandlerUndef;handler for Undefined modebHandlerSWI;handler for SWI interruptbHandlerPabort;handler for PAbortbHandlerDabort;handler for DAbortb.;reservedbHandlerIRQ;handler for IRQ interruptbHandlerFIQ;handler for FIQ interrupt;@0x20;bEnterPWDN; Must be @0x20.HandlerFIQ      HANDLER HandleFIQHandlerIRQ      HANDLER HandleIRQHandlerUndef    HANDLER HandleUndefHandlerSWI      HANDLER HandleSWIHandlerDabort   HANDLER HandleDabortHandlerPabort   HANDLER HandlePabortIsrIRQsubsp,sp,#4       ;reserved for PCstmfdsp!,{r8-r9}ldrr9,=INTOFFSETldrr9,[r9]ldrr8,=HandleEINT0addr8,r8,r9,lsl #2ldrr8,[r8]strr8,[sp,#8]ldmfdsp!,{r8-r9,pc}LTORG;=======; ENTRY;=======ResetHandlerldrr0,=WTCON       ;watch dog disableldrr1,=0x0strr1,[r0]ldrr0,=INTMSKldrr1,=0xffffffff  ;all interrupt disablestrr1,[r0]ldrr0,=INTSUBMSKldrr1,=0x7fff;all sub interrupt disablestrr1,[r0];To reduce PLL lock time, adjust the LOCKTIME register.ldrr0,=LOCKTIMEldrr1,=0xffffffstrr1,[r0]    [ PLL_ON_START; Added for confirm clock divide. for 2440.; Setting value Fclk:Hclk:Pclkldrr0,=CLKDIVNldrr1,=CLKDIV_VAL; 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.strr1,[r0];program has not been copied, so use these directly,[ CLKDIV_VAL>1 ; means Fclk:Hclk is not 1:1.mrc p15,0,r0,c1,c0,0orr r0,r0,#0xc0000000;R1_nF:OR:R1_iAmcr p15,0,r0,c1,c0,0|mrc p15,0,r0,c1,c0,0bic r0,r0,#0xc0000000;R1_iA:OR:R1_nFmcr p15,0,r0,c1,c0,0];Configure UPLLldrr0,=UPLLCONldrr1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)  strr1,[r0]nop; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.nopnopnopnopnopnop;Configure MPLLldrr0,=MPLLCONldrr1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV)  ;Fin=16.9344MHzstrr1,[r0]    ];Check if the boot is caused by the wake-up from SLEEP mode.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;       When EINT0 is pressed,  Clear SDRAM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; check if EIN0 button is pressed1blInitStacks;===========================================================  ; Setup IRQ handlerldrr0,=HandleIRQ       ;This routine is neededldrr1,=IsrIRQ  ;if there is not 'subs pc,lr,#4' at 0x18, 0x1cstrr1,[r0]    [ :LNOT:THUMBCODE blMain;Do not use main() because ...... b.    ]    [ THUMBCODE ;for start-up code for Thumb mode orrlr,pc,#1 bxlr CODE16 blMain;Do not use main() because ...... b.CODE32    ];function initializing stacksInitStacks;Do not use DRAM,such as stmfd,ldmfd......;SVCstack is initialized before;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'mrsr0,cpsrbicr0,r0,#MODEMASKorrr1,r0,#UNDEFMODE|NOINTmsrcpsr_cxsf,r1;UndefModeldrsp,=UndefStack; UndefStack=0x33FF_5C00orrr1,r0,#ABORTMODE|NOINTmsrcpsr_cxsf,r1;AbortModeldrsp,=AbortStack; AbortStack=0x33FF_6000orrr1,r0,#IRQMODE|NOINTmsrcpsr_cxsf,r1;IRQModeldrsp,=IRQStack; IRQStack=0x33FF_7000orrr1,r0,#FIQMODE|NOINTmsrcpsr_cxsf,r1;FIQModeldrsp,=FIQStack; FIQStack=0x33FF_8000bicr0,r0,#MODEMASK|NOINTorrr1,r0,#SVCMODEmsrcpsr_cxsf,r1;SVCModeldrsp,=SVCStack; SVCStack=0x33FF_5800;USER mode has not be initialized.movpc,lr;The LR register will not be valid if the current mode is not SVC mode.;===========================================================;=====================================================================; Clock division test; Assemble code, because VSYNC time is very short;=====================================================================ALIGNAREA RamData, DATA, READWRITE^   _ISR_STARTADDRESS; _ISR_STARTADDRESS=0x33FF_FF00HandleReset #   4HandleUndef #   4HandleSWI#   4HandlePabort    #   4HandleDabort    #   4HandleReserved  #   4HandleIRQ#   4HandleFIQ#   4;Do not use the label 'IntVectorTable',;The value of IntVectorTable is different with the address you think it may be.;IntVectorTable;@0x33FF_FF20HandleEINT0#   4HandleEINT1#   4HandleEINT2#   4HandleEINT3#   4HandleEINT4_7#   4HandleEINT8_23#   4HandleCAM#   4; Added for 2440.HandleBATFLT#   4HandleTICK#   4HandleWDT#   4HandleTIMER0 #   4HandleTIMER1 #   4HandleTIMER2 #   4HandleTIMER3 #   4HandleTIMER4 #   4HandleUART2  #   4;@0x33FF_FF60HandleLCD #   4HandleDMA0#   4HandleDMA1#   4HandleDMA2#   4HandleDMA3#   4HandleMMC#   4HandleSPI0#   4HandleUART1#   4HandleNFCON#   4; Added for 2440.HandleUSBD#   4HandleUSBH#   4HandleIIC#   4HandleUART0 #   4HandleSPI1 #   4HandleRTC #   4HandleADC #   4;@0x33FF_FFA0END
2440addr.h
#define _IRQ_BASEADDRESS 0x33ffff00  /*#define pISR_RESET(*(unsigned *)(_IRQ_BASEADDRESS+0x0))#define pISR_UNDEF(*(unsigned *)(_IRQ_BASEADDRESS+0x4))#define pISR_SWI(*(unsigned *)(_IRQ_BASEADDRESS+0x8))#define pISR_PABORT(*(unsigned *)(_IRQ_BASEADDRESS+0xc))#define pISR_DABORT(*(unsigned *)(_IRQ_BASEADDRESS+0x10))#define pISR_RESERVED(*(unsigned *)(_IRQ_BASEADDRESS+0x14))#define pISR_IRQ(*(unsigned *)(_IRQ_BASEADDRESS+0x18))#define pISR_FIQ(*(unsigned *)(_IRQ_BASEADDRESS+0x1c))*/#define pISR_WDT  (*(unsigned *)(_IRQ_BASEADDRESS+0x44))#define U32 unsigned int//GPBIO(使用GPB5)#define rGPBCON    (*(unsigned *) 0x56000010) #define rGPBDAT   ( *(unsigned *) 0x56000014)#define rGPBUP    ( *(unsigned *) 0x56000018)//UART0#define rUTRSTAT0   (*(volatile unsigned *)0x50000010)//UART 0 Tx/Rx status#define rULCON0     (*(volatile unsigned *)0x50000000)//UART 0 Line control#define rUCON0      (*(volatile unsigned *)0x50000004)//UART 0 Control#define rUFCON0     (*(volatile unsigned *)0x50000008)//UART 0 FIFO control#define rUBRDIV0    (*(volatile unsigned *)0x50000028)//UART 0 Baud rate divisor#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)//WDT#define rWTCON  (*(volatile unsigned *)0x53000000)#define rWTDAT  (*(volatile unsigned *)0x53000004)#define rWTCNT  (*(volatile unsigned *)0x53000008)//INTRRUPT#define rSRCPND     (*(volatile unsigned *)0x4A000000)#define rINTMOD     (*(volatile unsigned *)0x4A000004)#define rINTMSK    (*(volatile unsigned *)0x4A000008)#define rPRIORITY   (*(volatile unsigned *)0x4A00000c)#define rINTPND     (*(volatile unsigned *)0x4A000010)#define rINTOFFSET  (*(volatile unsigned *)0x4A000014)#define rSUBSRCPND     (*(volatile unsigned *)0x4A000018)#define rINTSUBMSK     (*(volatile unsigned *)0x4A00001C)#define prescaler_value  127#define clock_select     3#define  BIT_WDT_AC97 (1<<9)#define  BIT_WDT (1<<13)#define  BIT_AC97 (1<<14)#defineEnableIrq(bit)rINTMSK &= ~(bit)#defineDisableIrq(bit)rINTMSK |= (bit)#defineEnableSubIrq(bit)rINTSUBMSK &= ~(bit)#defineDisableSubIrq(bit)rINTSUBMSK |= (bit)

main.c
#include "2440addr.h"void delay(int a){       int k;       for(k=0;k<a;k++)              ;}void __irq watchdog(void); void Main(void){    //GPB5设置为输出rGPBCON |= 0x400;rGPBCON &= 0xFFFFF7FF; //GPB5设为灭状态rGPBDAT |= 0x20;//输出上拉rGPBUP  &=0xFDF;    rWTCON = 0xf9<<8;                  //Prescaler = 249,Division = 16,时钟频率为12.5kHz        rWTDAT = 40000;               //设置看门狗定时器超时时间为4秒(50÷12.5)    rWTCNT = 40000;    rWTCON |= (1<<5)|(1<<2);         //开启看门狗定时器中断    rSRCPND = 0x1<<9;    rSUBSRCPND = 0x1<<13;    rINTPND = 0x1<<9;    rINTSUBMSK = ~(0x1<<13);      //打开中断子屏蔽    rINTMSK = ~(0x1<<9);                     //打开中断屏蔽     pISR_WDT= (U32)watchdog;    while(1) ;       }void __irq watchdog(void){      rGPBDAT &=0xfdf;delay(6400000); rGPBDAT |= 0x20;       rSRCPND = 0x1<<9;       rSUBSRCPND = 0x1<<13;       rINTPND = 0x1<<9; }

1 0
原创粉丝点击