zoukankan      html  css  js  c++  java
  • ARM中的看门狗程序

    在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
    ",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
    "
     35           "bic r0, r0, #0x80
    "//设置CPSR的I位,将IRQ位打开
     36           "msr cpsr, r0
    "
     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! 
    ");
     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
    ", irq_id, cpu_id);
     97 
     98          pwm_on();
     99          led_on();
    100         printf("hello dog!
    ");
    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
    "
    119          : "=r" (source)
    120      );
    121 
    122 
    123     return source;
    124 
    125 }
    126 
    127 __asm__(
    128 
    129 "voliate_start:
    "
    130     //跳转目录
    131     " b reset
    "
    132     " b undefined
    "
    133     " b swi
    "
    134     " b pre_abt
    "
    135     " b data_abt
    "
    136     " .word 0
    "//占位符号,一个位占4个字节
    137     " b irq
    "
    138     " b fiq
    "
    139 "
    "
    140 
    141     //跳转要分三部:
    142     //1:将PC保存到新模式下的lr中;
    143     //2:将CPSR保存在SPSR中
    144     //3:初始化SP
    145     //前两步由硬件完成,而第三部需要手动完成
    146 "reset:
    "
    147 
    148 "undefined:
    "
    149      "mov sp, #0x66000000
    "//初始化SP
    150      "stmfd sp!, {r0-r12, lr}
    "//初始化sp,入栈保护寄存器 
    151     //打印一句话 
    152      "ldr r0, =und_string
    "
    153      "ldr r2, show
    "
    154      "blx r2
    "
    155     //跳回来分两部
    156     //1:将CPSR保存在SPSR中
    157     //2:将PC保存到新模式下的lr中;
    158      "mov sp, #0x66000000
    "//
    159      "ldmea sp, {r0-r12, pc}^
    "// 
    160 
     161 "swi:
    "
    162 
    163 "pre_abt:
    "
    164 "data_abt:
    "
    165      "sub lr, lr, #4
    "
    166      "mov sp, #0x66000000
    "//初始化SP
    167      "stmfd sp!, {r0-r12, lr}
    "//初始化sp,入栈保护寄存器 
    168     //打印一句话 
    169      "ldr r0, =data_string
    "
    170      "ldr r2, show
    "
    171      "blx r2
    "
    172     //跳回来分两部
    173     //1:将CPSR保存在SPSR中
    174     //2:将PC保存到新模式下的lr中;
    175      "mov sp, #0x66000000
    "//
    176      "ldmea sp, {r0-r12, pc}^
    "// 
    177 
    178 "irq:
    "
    179     "sub lr, lr, #4
    "
    180      "mov sp, #0x66000000
    "//初始化SP
    181      "stmfd sp!, {r0-r12, lr}
    "//初始化sp,入栈保护寄存器 
    182     //打印一句话 
    183      "mov r2, #0x66000000
    "
    184      "ldr r1, [r2]
    "
    185      "blx r1
    "
    186 
    187    //  "ldr r0, =irq_string
    "
    188    //  "ldr r2, show
    "
    189    //  "blx r2
    "
    190     //跳回来分两部
    191     //1:将CPSR保存在SPSR中
    192     //2:将PC保存到新模式下的lr中;
    193      "mov sp, #0x66000000
    "//
    194      "ldmea sp, {r0-r12, pc}^
    "//
    195 "fiq:
    "
    196     "show:
    "
    197      ".word 0xc3e114d8
    "
    198 
    199     "und_string:
    "
    200      ".asciz "This is  UND!\n" 
    "
    201      "data_string:
    "
    202      ".asciz "This DATA_ABORT!\n" 
    "
    203      "irq_string:
    "
    204      ".asciz "This IRQ!\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! ");
    还有:

    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 ", irq_id, cpu_id);
     97
     98          pwm_on();
     99          led_on();
    100         printf("hello dog! ");
    101          delay(6000000);
    102          pwm_off();
    103          led_off();
    104         WTCLRINT = 0x1;
    105     }
    其中,各个寄存器详见:1352芯片手册。

    运行成功:

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

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

  • 相关阅读:
    nodejs 实现简单的文件上传功能
    url地址数据转换成json数据格式
    html布局,左侧固定右侧自适应
    JavaScript事件
    如何用CSS进行网页布局
    选项卡教程(源代码)
    css切图教程
    前端学习的大概路线
    AJAX之学习笔记(持续更新......)
    nginx命令详解
  • 原文地址:https://www.cnblogs.com/hongzhunzhun/p/4513072.html
Copyright © 2011-2022 走看看