标签:
在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的值就会修改叫的频率!
标签:
原文地址:http://www.cnblogs.com/hongzhunzhun/p/4513072.html