Tiny4412中断之看门狗

  一:看门狗(WDT watch dog timer)

  看门狗其实是一个计数器,它的作用就是防止程序陷入死循环或者程序运行跑飞;看门狗是一个硬件,它的工作原理是,初始化给他一个值,它会过一段时间减一,直到这个数减为0,它将会产生一个中断信号或者reset信号,致使我们系统复位,而又时候我们不想让它过一会儿就重启又想预防死机,那么我们就可以在这个数减到快要接进0的时候,给它重新赋值;这样就不会触发reset信号,但当程序跑飞时机器死机时,它就会减到零,进行操作系统复位;

  具体看下图所示:输入时钟为PCLK(该时钟频率等于系统的主频),它经过两级分频(Prescaler和frequency division factor),最后将分频后的时钟作为该定时器的输入时钟,当计数器期满后可以产生中断或者复位信号。

 

  看门狗计数器公式如下:

  t_watchdog = 1/( PCLK / (Prescaler value + 1) / Division_factor )

  通过tiny4412用户手册我们可以找到看门狗的中断号为75(如下图):

  预分频器Prescaler及分频因子Division factor的值在WTCON(看门狗时钟控制寄存器)中设置,如下图:

  今天的程序是使用watchdog来实现led灯的闪烁,下面贴出代码:

 1 #ifndef __BUNFLY_H
 2 #define __BUNFLY_H
 3 
 4 #define ICCICR_CPU0        (*(volatile unsigned long *)0x10480000)
 5 #define ICCPMR_CPU0        (*(volatile unsigned long *)0x10480004)
 6 #define ICDDCR            (*(volatile unsigned long *)0x10490000)
 7 #define ICDIPR0_CPU0    (*(volatile unsigned long *)0x10490400)
 8 #define ICDIPTR0_CPU0    (*(volatile unsigned long *)0x10490800)
 9 #define ICDISER0_CPU0    (*(volatile unsigned long *)0x10490100)
10 #define ICDSGIR            (*(volatile unsigned long *)0x10490f00)
11 #define ICCEOIR_CPU0    (*(volatile unsigned long *)0x10480010)
12 #define ICCIAR_CPU0        (*(volatile unsigned long *)0x1048000c)
13 #define ICDIPR2_CPU0    (*(volatile unsigned long *)0x10490408)
14 #define ICDIPTR2_CPU0    (*(volatile unsigned long *)0x10490808)
15 #define ICDIPR3_CPU0    (*(volatile unsigned long *)0x1049040c)
16 #define ICDIPTR3_CPU0    (*(volatile unsigned long *)0x1049080c)
17 #define ICDIPR16_CPU0    (*(volatile unsigned long *)0x10490440)
18 #define ICDIPTR16_CPU0    (*(volatile unsigned long *)0x10490840)
19 #define ICDIPR18_CPU0    (*(volatile unsigned long *)0x10490448)
20 #define ICDIPTR18_CPU0    (*(volatile unsigned long *)0x10490848)
21 #define ICDISER2_CPU0    (*(volatile unsigned long *)0x10490108)
22 
23 #define WTCON             (*(volatile unsigned long *)0x10060000)
24 #define WTDAT             (*(volatile unsigned long *)0x10060004)
25 #define WTCNT             (*(volatile unsigned long *)0x10060008)
26 #define WTCLRINT         (*(volatile unsigned long *)0x1006000C)
27 
28 #define EXT_INT43CON    (*(volatile unsigned long *)0x11000e0c)
29 #define EXT_INT43_MASK    (*(volatile unsigned long *)0x11000f0c)
30 #define EXT_INT43_PEND    (*(volatile unsigned long *)0x11000f4c)
31 #define GPX3CON         (*(volatile unsigned long *)0x11000c60)
32 
33 #define GPM4CON    (*(volatile unsigned long *)0x110002e0)
34 #define GPM4DAT (*(volatile unsigned long *)0x110002e4)
35 
36 #endif    //__BUNFLY_H
  1 #include "bunfly.h"
  2 
  3 void (*udelay)(int) = 0xc3e25f90;
  4 int (*printf)(char *, ...) = 0xc3e114d8;
  5 void enable_mmu();
  6 void init_table(unsigned long *addr);
  7 void memcpy(unsigned char *dest, unsigned char *src, int len);
  8 extern unsigned long  vector_start;
  9 void do_irq();
 10 void led_on();
 11 void led_off();
 12 
 13 int main()
 14 {    
 15     memcpy(0x70000000, vector_start, 0x1000);    
 16     enable_mmu();
 17 
 18     *(unsigned long *)0x47000000 = do_irq;
 19 
 20     //step 1: set cpu permit interrupt
 21     __asm__ __volatile__(
 22         "mrs r0, cpsr\n"
 23         "bic r0,r0, #0x80\n"
 24         "msr cpsr, r0\n"
 25         :::"r0"
 26     );
 27 
 28     //step 2: set GIC (cgi) enable
 29     ICCICR_CPU0 = 1; //中断总开关
 30     ICCPMR_CPU0 =0xff;//设置最低优先级(门槛)
 31     ICDDCR = 1; //本中断开关
 32     ICDIPR18_CPU0 = (100 << 24);//设置本中断优先级
 33     ICDIPTR18_CPU0 = (1 << 24);//选择指定的cpu进行中断处理
 34     ICDISER2_CPU0 = (1 << 11);//启用本中断
 35     
 36     //step 3: set watch dog timer
 37     WTCNT = 32768;
 38     WTDAT = 32768;
 39     WTCON = (1 << 2) | (3 << 3) | (1 << 5) | (95 << 8);
 40             
 41     printf("welcom back\n");
 42 }
 43 
 44 void do_irq()
 45 {
 46     WTCLRINT = 0;//清中断
 47     printf("wang wang wang\n");
 48     static int flags = 1;
 49     if(flags) {
 50         led_on();
 51         flags = 0;
 52     }
 53     else {
 54         led_off();
 55         flags = 1;
 56     }
 57 }
 58 
 59 void led_on()
 60 {
 61     GPM4CON &= ~0xffff;
 62     GPM4CON |= 0x1111;
 63     GPM4DAT &= ~0xf;
 64 }
 65 
 66 void led_off()
 67 {
 68 
 69     GPM4CON &= ~0xffff;
 70     GPM4CON |= 0x1111;
 71     GPM4DAT |= 0xf;
 72 }
 73 
 74 void memcpy(unsigned char *dest, unsigned char *src, int len)
 75 {
 76     int i = 0;
 77     for(i = 0; i < len; i++) {
 78         dest[i] = src[i];
 79     }
 80 }
 81 
 82 void enable_mmu()
 83 {
 84     /*构建表*/
 85     unsigned long addr = 0x50000000;
 86     init_table(addr);
 87     /*打开mmu*/
 88     unsigned long mmu = 0;
 89     mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8);
 90     __asm__ __volatile__ (
 91         "mov r0, #3\n"
 92         "MCR p15, 0, r0, c3, c0, 0\n"//设置为管理员
 93         "MCR p15, 0, %0, c2, c0, 0\n"//设置表的地址
 94         "MCR p15, 0, %1, c1, c0, 0\n"//开启mmu
 95         :    
 96         :    "r" (addr), "r" (mmu)
 97         :
 98     );
 99 
100 }
101 
102 __asm__(
103 
104 "vector: \n"
105 "    b reset\n"
106 "    b und\n"
107 "    b swi\n"
108 "    b pre_abt\n"
109 "    b data_abt\n"
110 "    .word 0x0\n"
111 "    b irq\n"
112 "    b fiq\n"
113 "reset:\n"
114 "und:\n"
115 "    mov sp, #0x47000000\n"
116 "    stmdb sp!, {r0-r12, lr}\n"
117 
118 "    ldr r3, =0x47000004\n"
119 "    ldr r2, [r3]\n"
120 "    blx r2\n"
121 
122 "    mov sp, #0x47000000\n"
123 "    ldmdb sp, {r0-r12, pc}^    \n"
124 
125 "swi:\n"
126 "    mov sp, #0x47000000\n"
127 "    stmdb sp!, {r0-r12, lr}^\n"
128 
129 "    mov sp, #0x47000000\n"
130 "    ldmdb sp, {r0-r12, pc}^    \n"
131 
132 "pre_abt:\n"
133 
134 "data_abt:\n"
135 "    mov sp, #0x47000000\n"
136 "    sub lr, lr, #4\n"
137 "    stmdb sp!, {r0-r12, lr}\n"
138 
139 "    ldr r3, =0x47000008\n"
140 "    ldr r2, [r3]\n"
141 "    blx r2\n"
142 
143 "    mov sp, #0x47000000\n"
144 "    ldmdb sp, {r0-r12, pc}^    \n"
145 "irq:\n"
146 
147 "    mov sp, #0x47000000\n"
148 "    sub lr, lr, #4\n"
149 "    stmdb sp!, {r0-r12, lr}\n"
150 
151 "    ldr r3, =0x47000000\n"
152 "    ldr r2, [r3]\n"
153 "    blx r2\n"
154 
155 "    mov sp, #0x47000000\n"
156 "    ldmdb sp, {r0-r12, pc}^    \n"
157 
158 "fiq:\n"
159 
160     ".global vector_start\n"
161 "vector_start: \n"
162     ".word vector \n "
163 
164 );
165 
166 void init_table(unsigned long *addr)
167 {
168     unsigned long va = 0;
169     unsigned long phys = 0;
170 
171     //0x40000000-0x80000000 -> 0x40000000-0x80000000    
172     for(va = 0x40000000; va < 0x80000000; va += 0x100000) {
173         phys = va;
174         addr[va >> 20] = phys | 2;
175     }
176 
177     //0x10000000-0x14000000 -> 0x10000000-0x140000000    
178     for(va = 0x10000000; va < 0x14000000; va += 0x100000) {
179         phys = va;
180         addr[va >> 20] = phys | 2;
181     }
182     //0x10000000-0x14000000 -> 0x10000000-0x140000000    
183     for(va = 0x0; va < 0x10000000; va += 0x100000) {
184         phys = va + 0x70000000;
185         addr[va >> 20] = phys | 2;
186     }
187             
188 }

 

posted @ 2015-09-04 11:49  zhangwju  阅读(1317)  评论(0编辑  收藏  举报