码迷,mamicode.com
首页 > 其他好文 > 详细

ARM中的看门狗程序

时间:2015-05-18 22:52:25      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

在ARM中,有一个硬件部分叫WATCH DOG。这个硬件,一直在做一件事情:就是,从某一数值,一直数,各一段时间减一,隔一段时间减一,直到减到0的时候将会触发重启或者中断。而有时候,为了预防死机,我们在操作系统跑起来的时候会有一个特定的程序来做一件事情:减到特定是值的时候数值将会重新置到100.这样,看门狗将会循环往复做一件事情:一直数数,而不会死机。

这个程序叫做守护程序:又叫做喂狗程序。

看门狗的逻辑运算图如下:

技术分享

 

今天,有看门狗来写了一个程序:隔一段时间来触发一个中断,每次中断来的时候,将会让板子上面的灯和蜂鸣器做出相应的反映:

首先:在头文件中将具体的寄存器声明:

 1 
  2 #define gpiobase        0x11000000
  3 #define GPM4CON         (*(volatile unsigned long *)(gpiobase + 0x02E0)) 
  4 #define GPM4DAT         (*(volatile unsigned long *)(gpiobase + 0x02E4))
  5 #define GPX3CON         (*(volatile unsigned long *)(gpiobase + 0x0C60))
  6 #define GPX3DAT         (*(volatile unsigned long *)(gpiobase + 0x0C64))
  7 #define GPD0CON         (*(volatile unsigned long *)(gpiobase + 0x4000A0))
  8 #define GPD0DAT         (*(volatile unsigned long *)(gpiobase + 0x4000A4))
  9 
 10 #define ICC 0x10480000
 11 
 12 #define ICCICR_CPU0     (*(volatile unsigned long *)(ICC + 0x0000)) 
 13 #define ICCPMR_CPU0     (*(volatile unsigned long *)(ICC + 0x0004)) 
 14 #define ICCBPR_CPU0     (*(volatile unsigned long *)(ICC + 0x0008)) 
 15 #define ICCIAR_CPU0     (*(volatile unsigned long *)(ICC + 0x000C)) 
 16 #define ICCEOIR_CPU0    (*(volatile unsigned long *)(ICC + 0x0010)) 
 17 #define ICCRPR_CPU0     (*(volatile unsigned long *)(ICC + 0x0014)) 
 18 #define ICCHPIR_CPU0    (*(volatile unsigned long *)(ICC + 0x0018)) 
 19 #define ICCABPR_CPU0    (*(volatile unsigned long *)(ICC + 0x001C)) 
 20 #define INTEG_EN_C_CPU0 (*(volatile unsigned long *)(ICC + 0x0040)) 
 21 #define ICCIIDR         (*(volatile unsigned long *)(ICC + 0x00FC))
 22 
 23 #define ICD 0x10490000
 24 
 25 #define ICDDCR            (*(volatile unsigned long *)(ICD + 0x0000))
 26 #define ICDICTR           (*(volatile unsigned long *)(ICD + 0x0004))
 27 #define ICDIIDR           (*(volatile unsigned long *)(ICD + 0x0008))
 28 #define ICDISR0_CPU0      (*(volatile unsigned long *)(ICD + 0x0080))
 29 #define ICDISER0_CPU0     (*(volatile unsigned long *)(ICD + 0x0100))
 30 #define ICDISER2_CPU0     (*(volatile unsigned long *)(ICD + 0x0108))
 31 #define ICDICER0_CPU0     (*(volatile unsigned long *)(ICD + 0x0180))
 32 #define ICDISPR0_CPU0     (*(volatile unsigned long *)(ICD + 0x0200))
 33 #define ICDICPR0_CPU0     (*(volatile unsigned long *)(ICD + 0x0280))
 34 #define ICDABR0_CPU0      (*(volatile unsigned long *)(ICD + 0x0300))
 35 #define ICDIPR0_CPU0      (*(volatile unsigned long *)(ICD + 0x0400))
 36 #define ICDIPR1_CPU0      (*(volatile unsigned long *)(ICD + 0x0404))
 37 #define ICDIPR2_CPU0      (*(volatile unsigned long *)(ICD + 0x0408))
 38 #define ICDIPR3_CPU0      (*(volatile unsigned long *)(ICD + 0x040C))
 39 #define ICDIPR4_CPU0      (*(volatile unsigned long *)(ICD + 0x0410))
 40 #define ICDIPR5_CPU0      (*(volatile unsigned long *)(ICD + 0x0414))
 41 #define ICDIPR6_CPU0      (*(volatile unsigned long *)(ICD + 0x0418))
 42 #define ICDIPR7_CPU0      (*(volatile unsigned long *)(ICD + 0x041C))
 43 #define ICDIPR18_CPU0      (*(volatile unsigned long *)(ICD + 0x448))
 44 
 45 #define ICDIPTR0_CPU0   (*(volatile unsigned long *)(ICD + 0x0800))
 46 #define ICDIPTR1_CPU0   (*(volatile unsigned long *)(ICD + 0x0804))
 47 #define ICDIPTR18_CPU0  (*(volatile unsigned long *)(ICD + 0x0848))
 48 #define ICDSGIR     (*(volatile unsigned long *)(ICD + 0x0F00))
 49 
 50 
 51 #define WTCON    (*(volatile unsigned long *)0x10060000)
 52 #define WTDAT    (*(volatile unsigned long *)0x10060004)
 53 #define WTCNT    (*(volatile unsigned long *)0x10060008)
 54 #define WTCLRINT (*(volatile unsigned long *)0x1006000C) 
 55 
 56 
 57 

在主要的文件中:

  1 #include"regs.h"
  2 
  3 int (*printf)(char *, ...) = 0xc3e114d8;
  4 int(*delay)(int)=0xc3e25f90;
  5 
  6 void init_ttb(unsigned long *addr);
  7 void enable_mmu(void);
  8 unsigned long data_abort_init();
  9 void memcopy(unsigned long* dest,unsigned long* source,int len);
 10 void do_irq();
 11 void pwm_on(void);
 12 void pwm_off(void);
 13 void led_on(void);
 14 void led_on(void);
 15 
 16 
 17 
 18 int main()
 19 {
 20      *(unsigned long *)0x66000000 = do_irq;
 21 
 22     //发生异常时会进入异常模式跳转到0000 0004地址处理异常事件   
 23     unsigned long source_addr=data_abort_init();
 24     //异常事件处理函数
 25     printf("swi_souce addr is %x\n",source_addr);
 26     //将异常处理地址的值放到0x60000004
 27     memcopy(0x60000000,source_addr,0x1000);
 28 
 29     enable_mmu();
 30     //内存映射将0x00000004映射到0x6000000004    
 31 
 32      //step 1: cpu cpsr
 33       __asm__ __volatile__(
 34           "mrs r0, cpsr\n"
 35           "bic r0, r0, #0x80\n"//设置CPSR的I位,将IRQ位打开
 36           "msr cpsr, r0\n"
 37           ::: "r0"
 38       );
 39 
 40       //step 2: GIC 
 41       ICCICR_CPU0 = 1;//CPU接口控制寄存器
 42       ICCPMR_CPU0 = 0xff;//中断优先标志寄存器
 43 
 44      //75
 45      ICDDCR = 1;
 46      //ICDIPR0_CPU0 = (0x00 << 0);
 47      ICDIPR18_CPU0 = (0x0 << 24);
 48      //ICDIPTR0_CPU0 = 1;
 49      ICDIPTR18_CPU0 = (0x1 << 24);
 50      //ICDISER0_CPU0 = (1 << 0);
 51      ICDISER2_CPU0 = (1 << 11);
 52 
 53      //step 3: interrupt source watchdog
 54      WTCON = 0 | (1 << 2) | (3 << 3) | (1 << 5) | (250 << 8);
 55      WTCNT = 0x8000;
 56      WTDAT = 0x1000;
 57 
 58     printf("welcome back! \n");
 59 
 60 
 61 }
 62 
 63 void pwm_on(void)
 64     {
 65         GPD0CON &= ~0xffff;
 66         GPD0CON |= 0x1;//配置寄存器为2
 67         GPD0DAT |= 0x1;//date=0xf
 68     }
 69 
 70 void pwm_off(void)
 71     {
 72         GPD0CON &= ~0xffff;
 73         GPD0CON |= 0x0;
 74     //  GPD0DAT &=0x0 ;//date=0xf
 75 
 76     }
 77 void led_off(void)
 78     {
 79         GPM4CON &= ~0xffff;//清零
 80         GPM4CON |= 0x0000;//0---3位清零
 81         GPM4DAT |= 0x0;//date=0xf关闭置一
 82     }
83 void led_on(void)
 84     {
 85         GPM4CON &= ~0xffff;
 86         GPM4CON |= 0x1111;//配置寄存器3-0-----3-3全为1111,全为输出模式
 87         GPM4DAT &= ~0xf;//打开置0-4位为0000
 88     }
 89 
 90 void do_irq()
 91     {
 92         unsigned long data = ICCIAR_CPU0;
 93         unsigned long irq_id = data & 0x3ff;
 94         unsigned long cpu_id = (data >> 10) & 0x7;
 95         ICCEOIR_CPU0 = irq_id | (cpu_id << 10);
 96         printf("irq is %d, cpu is %d\n", irq_id, cpu_id);
 97 
 98          pwm_on();
 99          led_on();
100         printf("hello dog!\n");
101          delay(6000000);
102          pwm_off();
103          led_off();
104         WTCLRINT = 0x1;
105     }
106 
107 void memcopy(unsigned long* dest, unsigned long* source,int len)
108 {
109     int i=0;;
110     for(i=0;i<len;i++)
111         dest[i]=source[i];
112 }
113 
114 unsigned long  data_abort_init()
115 {
116     unsigned long source;
117     __asm__ __volatile__(
118          "ldr %0, =voliate_start\n"
119          : "=r" (source)
120      );
121 
122 
123     return source;
124 
125 }
126 
127 __asm__(
128 
129 "voliate_start:\n"
130     //跳转目录
131     " b reset\n"
132     " b undefined\n"
133     " b swi\n"
134     " b pre_abt\n"
135     " b data_abt\n"
136     " .word 0\n"//占位符号,一个位占4个字节
137     " b irq\n"
138     " b fiq\n"
139 "\n"
140 
141     //跳转要分三部:
142     //1:将PC保存到新模式下的lr中;
143     //2:将CPSR保存在SPSR中
144     //3:初始化SP
145     //前两步由硬件完成,而第三部需要手动完成
146 "reset:\n"
147 
148 "undefined:\n"
149      "mov sp, #0x66000000\n"//初始化SP
150      "stmfd sp!, {r0-r12, lr}\n"//初始化sp,入栈保护寄存器 
151     //打印一句话 
152      "ldr r0, =und_string\n"
153      "ldr r2, show\n"
154      "blx r2\n"
155     //跳回来分两部
156     //1:将CPSR保存在SPSR中
157     //2:将PC保存到新模式下的lr中;
158      "mov sp, #0x66000000\n"//
159      "ldmea sp, {r0-r12, pc}^\n"// 
160 
 161 "swi:\n"
162 
163 "pre_abt:\n"
164 "data_abt:\n"
165      "sub lr, lr, #4\n"
166      "mov sp, #0x66000000\n"//初始化SP
167      "stmfd sp!, {r0-r12, lr}\n"//初始化sp,入栈保护寄存器 
168     //打印一句话 
169      "ldr r0, =data_string\n"
170      "ldr r2, show\n"
171      "blx r2\n"
172     //跳回来分两部
173     //1:将CPSR保存在SPSR中
174     //2:将PC保存到新模式下的lr中;
175      "mov sp, #0x66000000\n"//
176      "ldmea sp, {r0-r12, pc}^\n"// 
177 
178 "irq:\n"
179     "sub lr, lr, #4\n"
180      "mov sp, #0x66000000\n"//初始化SP
181      "stmfd sp!, {r0-r12, lr}\n"//初始化sp,入栈保护寄存器 
182     //打印一句话 
183      "mov r2, #0x66000000\n"
184      "ldr r1, [r2]\n"
185      "blx r1\n"
186 
187    //  "ldr r0, =irq_string\n"
188    //  "ldr r2, show\n"
189    //  "blx r2\n"
190     //跳回来分两部
191     //1:将CPSR保存在SPSR中
192     //2:将PC保存到新模式下的lr中;
193      "mov sp, #0x66000000\n"//
194      "ldmea sp, {r0-r12, pc}^\n"//
195 "fiq:\n"
196     "show:\n"
197      ".word 0xc3e114d8\n"
198 
199     "und_string:\n"
200      ".asciz \"This is  UND!\\n\" \n"
201      "data_string:\n"
202      ".asciz \"This DATA_ABORT!\\n\" \n"
203      "irq_string:\n"
204      ".asciz \"This IRQ!\\n\" \n"
205 
206         );
207 
208 void init_ttb(unsigned long *addr)
209 {
210     unsigned long va = 0;//定义虚拟地址
211     unsigned long pa = 0;//定义物理地址
212 
213     //40000000-------80000000   ====  40000000------80000000
214     for(va=0x40000000; va<=0x80000000; va+=0x100000){
215         pa = va;
216         addr[va >> 20] = pa | 2;
217         //|2的目的是将0-2位置为10此时将是小页模式4K
218     }
219 
220     //00000000-------10000000   ====  60000000------70000000
221     for(va=0x00000000; va<=0x10000000; va+=0x100000){
222         pa = va+0x60000000;
223         addr[va >> 20] = pa | 2;
224     }
225 
226     //10000000-------14000000   ====  10000000------14000000
227     for(va=0x10000000; va<=0x14000000; va+=0x100000){
228         pa = va;
229         addr[va >> 20] = pa | 2;
230     }
231 
232     //30000000-------40000000   ====  50000000------60000000
233     for(va=0x30000000; va<0x40000000; va+=0x100000){
234         pa = va + 0x20000000;
235         addr[va >> 20] = pa | 2;
236     }
237 }
                                                                  

主要看主函数部分:

39
 40       //step 2: GIC
 41       ICCICR_CPU0 = 1;//CPU接口控制寄存器
 42       ICCPMR_CPU0 = 0xff;//中断优先标志寄存器
 43
 44      //75
 45      ICDDCR = 1;
 46      //ICDIPR0_CPU0 = (0x00 << 0);
 47      ICDIPR18_CPU0 = (0x0 << 24);
 48      //ICDIPTR0_CPU0 = 1;
 49      ICDIPTR18_CPU0 = (0x1 << 24);
 50      //ICDISER0_CPU0 = (1 << 0);
 51      ICDISER2_CPU0 = (1 << 11);
 52
 53      //step 3: interrupt source watchdog
 54      WTCON = 0 | (1 << 2) | (3 << 3) | (1 << 5) | (250 << 8);
 55      WTCNT = 0x8000;
 56      WTDAT = 0x1000;
 57
 58     printf("welcome back! \n");
还有:

90 void do_irq()
 91     {
 92         unsigned long data = ICCIAR_CPU0;
 93         unsigned long irq_id = data & 0x3ff;
 94         unsigned long cpu_id = (data >> 10) & 0x7;
 95         ICCEOIR_CPU0 = irq_id | (cpu_id << 10);
 96         printf("irq is %d, cpu is %d\n", irq_id, cpu_id);
 97
 98          pwm_on();
 99          led_on();
100         printf("hello dog!\n");
101          delay(6000000);
102          pwm_off();
103          led_off();
104         WTCLRINT = 0x1;
105     }
其中,各个寄存器详见:1352芯片手册。

技术分享

技术分享

 

 

技术分享

运行成功:

技术分享

将会发现板子,各一段时间就会叫一次。LED会闪烁一次!

改变WTDAT的值就会修改叫的频率!

 

ARM中的看门狗程序

标签:

原文地址:http://www.cnblogs.com/hongzhunzhun/p/4513072.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!