第三十七天:Tiny驱动开发之看门狗中断

1.    看门狗原理

Watchdog原理上就是一个定时器。定时器timer对时钟进行计数,当定时器溢出时,产生复位信号,使得整个系统复位。在程序或嵌入式系统中,需要 定期的对看门狗timer进行复位重新计数,定时器不会溢出复位系统,从而保证系统的正常运行。当某种原因(例如干扰)引起程序跑飞或者进入死循环时,程 序不能定期的复位看门狗timer, 计数溢出产生复位信号,导致系统复位。

设本系统程序完整运行一周期的时间是T1,看门狗的定时周期为T2,T2>T1,在程序运行一周期后就修改定时器的计数值,只要程序正常运行,定时 器就不会溢出,若因为程序“跑飞”或者进入死循环,那么系统不能在T1时刻修改时间的计数值,一直计数直到T2时刻溢出,引发系统复位,使系统重新运行, 从而起到监控作用。

从上面的解释中可以看出,Watchdog的作用就是为了防止系统因意外“跑飞”,导致整个系统瘫痪时,恢复(reset)系统运行。

2.    Tiny4412看门狗控制

1)作为常规定时器使用,并且可以产生中断

2)作为看门狗定时器使用,期满时,它可以产生128个时钟周期的复位信号

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

看门狗定时器计数值的计算公式如下:

1)输入到计数器的时钟周期

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

预分频器Prescaler及分频因子Division factor的值由用户在WTCON(看门狗时钟控制寄存器)中设置。

 

2)看门狗的定时周期

T = 计数值(WTCNT初值-WTCNT当前值) * t_watchdog

WTCNT为看门狗数据寄存器,用来设置计数多少个时钟周期。乘以时钟周期就是定时的总时间了。

具体代码:

  1 #include "regs.h"
  2
  3 int (*printf)(char *, ...) = 0xc3e114d8;
  4
  5 void init_ttb(unsigned long *ttb);
  6 void enable_mmu(void);
  7 void memcpy(unsigned char *dest, unsigned char *source, int len);
  8 void do_irq();
  9
 10 int main()
 11 {
 12
 13     enable_mmu();
 14     *(unsigned long *)0x67000000 = do_irq;
 15     unsigned long source = 0;
 16     __asm__ __volatile__(
 17         "ldr %0, =vector_start\n"
 18         : "=r" (source)
 19     );
 20     memcpy(0, source, 0x1000);
 21
 22     //step 1: set cpsr i bit
 23     __asm__ __volatile__(
 24         "mrs r0, cpsr\n"
 25         "bic r0, r0, #0x80\n"
 26         "msr cpsr, r0\n"
 27         ::: "r0"
 28     );
 29
 30     //step 2: enable gic
 31     ICCICR_CPU0 = 1;//终端总开关
 32     ICCPMR_CPU0 = 0xff;//设置最低优先级
 33
 34     ICDDCR = 1;
 35     ICDIPR18_CPU0 &= ~(0xff << 24);//设置本中断优先级
 36     ICDIPTR18_CPU0 &= ~(0xff << 24);// 选择指定的cpu0进行终端处理
 37     ICDIPTR18_CPU0 |= (1 << 24);// 选择指定的cpu0进行终端处理
 38     ICDISER2_CPU0 = (1 << 11);//设置本中断开启
 39
 40     //step 3: open interrupt source
 41     GPM4CON = 0x1111;
 42
 43     WTCON = 0 | (1 << 2) | (0 << 3 ) | (1 << 5) | (254 << 8);
 44     WTDAT = 0x4000;
 45     printf("send sgi\n");
 46 }
 47
 48 void do_irq()
 49 {
 50     printf("watch dog \n");
 51
 52     static unsigned long tmp = 0xf;
 53     GPM4DAT = ~tmp;
 54     tmp = GPM4DAT;
 55
 56     WTCLRINT = 0x1;
 57
 58 }
 59
 60 __asm__(
 61 "vector_start:\n"
 62     "b reset\n"
 63     "b undef\n"
 64     "b swi\n"
 65     "b pre_abt\n"
 66     "b data_abt\n"
 67     ".word 0x0\n"
 68     "b irq \n"
 69     "b fiq\n"
 70     "\n"
 71 "reset:\n"
 72 "undef:\n"
 73     "mov sp, #0x66000000\n"
 74     "stmfd sp!, {r0-r12, lr}\n"
 75     "\n"
 76     "mov r0, #0x67000000\n"
 77     "ldr r1, [r0]\n"
 78     "blx r1\n"
 79     "\n"
 80     "mov sp, #0x66000000\n"
 81     "ldmea sp, {r0-r12, pc}^\n"
 82 "swi:\n"
 83     "mov sp, #0x66000000\n"
 84     "stmfd sp!, {r0-r12, lr}\n"
 85     "\n"
 86     "mov r0, #0x67000000\n"
 87     "ldr r1, [r0]\n"
 88     "blx r1\n"
 89     "\n"
 90     "mov sp, #0x66000000\n"
 91     "ldmea sp, {r0-r12, pc}^\n"
 92     "\n"
 93 "pre_abt:\n"
 94 "data_abt:\n"
 95     "mov sp, #0x66000000\n"
 96     "sub lr, lr, #4\n"
 97     "stmfd sp!, {r0-r12, lr}\n"
 98     "\n"
 99     "mov r0, #0x67000000\n"
100     "ldr r1, [r0]\n"
101     "blx r1\n"
102     "\n"
103     "mov sp, #0x66000000\n"
104     "ldmea sp, {r0-r12, pc}^\n"
105 "irq:\n"
106     "mov sp, #0x66000000\n"
107     "sub lr, lr, #4\n"
108     "stmfd sp!, {r0-r12, lr}\n"
109
110     "mov r0, #0x67000000\n"
111     "ldr r1, [r0]\n"
112     "blx r1\n"
113
114     "mov sp, #0x66000000\n"
115     "ldmea sp, {r0-r12, pc}^\n"
116 "fiq:\n"
117
118 );
119
120 void init_ttb(unsigned long *ttb)
121 {
122     unsigned long va = 0;
123     unsigned long pa = 0;
124
125     //00000000~10000000  -> 60000000~64000000
126     for(va=0x00000000; va<0x10000000; va+=0x100000){
127         pa = va + 0x60000000;
128         ttb[va >> 20] = pa | 2;
129     }
130
131     //10000000~14000000  -> 10000000~14000000
132     for(va=0x10000000; va<0x14000000; va+=0x100000){
133         pa = va;
134         ttb[va >> 20] = pa | 2;
135     }
136
137     //40000000~80000000  -> 40000000~80000000
138     for(va=0x40000000; va<0x80000000; va+=0x100000){
139         pa = va;
140         ttb[va >> 20] = pa | 2;
141     }
142
143     //30000000~40000000  -> 50000000~60000000
144     for(va=0x30000000; va<0x40000000; va+=0x100000){
145         pa = va + 0x20000000;
146         ttb[va >> 20] = pa | 2;
147     }
148 }
149
150 void enable_mmu(void)
151 {
152     unsigned long ttb = 0x70000000;
153     init_ttb(ttb);
154     unsigned long mmu = 0;
155     mmu = 1 | (1 << 3) | (1 << 8);
156     __asm__ __volatile__(
157         "mov r0, #3\n"
158         "mcr p15, 0, r0, c3, c0, 0\n"
159         "mcr p15, 0, %0, c2, c0, 0\n"
160         "mcr p15, 0, %1, c1, c0, 0\n"
161         :
162         : "r" (ttb), "r" (mmu)
163     );
164 }
165
166 void memcpy(unsigned char *dest, unsigned char *source, int len)
167 {
168     int i = 0;
169     for(i=0; i<len; i++)
170         dest[i] = source[i];
171 }
 1 #define gpiobase        0x11000000
 2 #define GPM4CON         (*(volatile unsigned long *)(gpiobase + 0x02E0))
 3 #define GPM4DAT         (*(volatile unsigned long *)(gpiobase + 0x02E4))
 4 #define GPX3CON         (*(volatile unsigned long *)(gpiobase + 0x0C60))
 5 #define GPX3DAT         (*(volatile unsigned long *)(gpiobase + 0x0C64))
 6
 7 #define ICC 0x10480000
 8
 9 #define ICCICR_CPU0     (*(volatile unsigned long *)(ICC + 0x0000))
10 #define ICCPMR_CPU0     (*(volatile unsigned long *)(ICC + 0x0004))
11 #define ICCBPR_CPU0     (*(volatile unsigned long *)(ICC + 0x0008))
12 #define ICCIAR_CPU0     (*(volatile unsigned long *)(ICC + 0x000C))
13 #define ICCEOIR_CPU0    (*(volatile unsigned long *)(ICC + 0x0010))
14 #define ICCRPR_CPU0     (*(volatile unsigned long *)(ICC + 0x0014))
15 #define ICCHPIR_CPU0    (*(volatile unsigned long *)(ICC + 0x0018))
16 #define ICCABPR_CPU0    (*(volatile unsigned long *)(ICC + 0x001C))
17 #define INTEG_EN_C_CPU0 (*(volatile unsigned long *)(ICC + 0x0040))
18 #define ICCIIDR         (*(volatile unsigned long *)(ICC + 0x00FC))
19
20 #define ICD 0x10490000
21
22 #define ICDDCR            (*(volatile unsigned long *)(ICD + 0x0000))
23 #define ICDICTR           (*(volatile unsigned long *)(ICD + 0x0004))
24 #define ICDIIDR           (*(volatile unsigned long *)(ICD + 0x0008))
25 #define ICDISR0_CPU0      (*(volatile unsigned long *)(ICD + 0x0080))
26 #define ICDISER0_CPU0     (*(volatile unsigned long *)(ICD + 0x0100))
27 #define ICDISER2_CPU0     (*(volatile unsigned long *)(ICD + 0x0108))
28 #define ICDICER0_CPU0     (*(volatile unsigned long *)(ICD + 0x0180))
29 #define ICDISPR0_CPU0     (*(volatile unsigned long *)(ICD + 0x0200))
30 #define ICDICPR0_CPU0     (*(volatile unsigned long *)(ICD + 0x0280))
31 #define ICDABR0_CPU0      (*(volatile unsigned long *)(ICD + 0x0300))
32 #define ICDIPR0_CPU0      (*(volatile unsigned long *)(ICD + 0x0400))
33 #define ICDIPR1_CPU0      (*(volatile unsigned long *)(ICD + 0x0404))
34 #define ICDIPR2_CPU0      (*(volatile unsigned long *)(ICD + 0x0408))
35 #define ICDIPR3_CPU0      (*(volatile unsigned long *)(ICD + 0x040C))
36 #define ICDIPR4_CPU0      (*(volatile unsigned long *)(ICD + 0x0410))
37 #define ICDIPR5_CPU0      (*(volatile unsigned long *)(ICD + 0x0414))
38 #define ICDIPR6_CPU0      (*(volatile unsigned long *)(ICD + 0x0418))
39 #define ICDIPR7_CPU0      (*(volatile unsigned long *)(ICD + 0x041C))
40 #define ICDIPR18_CPU0      (*(volatile unsigned long *)(ICD + 0x0448))
41
42 #define ICDIPTR0_CPU0    (*(volatile unsigned long *)(ICD + 0x0800))
43 #define ICDIPTR1_CPU0    (*(volatile unsigned long *)(ICD + 0x0804))
44 #define ICDIPTR18_CPU0    (*(volatile unsigned long *)(ICD + 0x0848))
45 #define ICDSGIR        (*(volatile unsigned long *)(ICD + 0x0F00))
46
47
48 #define WTCON     (*(volatile unsigned long *)0x10060000)
49 #define WTDAT    (*(volatile unsigned long *)0x10060004)
50 #define WTCNT    (*(volatile unsigned long *)0x10060008)
51 #define WTCLRINT (*(volatile unsigned long *)0x1006000C) 
时间: 2024-10-21 14:38:23

第三十七天:Tiny驱动开发之看门狗中断的相关文章

Hasen的linux设备驱动开发学习之旅--中断

/** * Author:hasen * 参考 :<linux设备驱动开发详解> * 简介:android小菜鸟的linux * 设备驱动开发学习之旅 * 主题:中断 * Date:2014-11-13 */ 一.中断和定时器 所谓中断是指CPU在执行程序的过程中,出现了某些突发事件急待处理,CPU必须暂停执行当前的程序, 转而去处理突发事件,处理完毕后CPU又返回原程序被中断的位置并继续执行. 下图是中断的分类 嵌入式系统以及X86 PC中大多包含可编程中断控制器(PIC),许多MCU内部就

嵌入式Linux驱动开发实战视频教程

嵌入式Linux驱动开发实战教程(内核驱动.看门狗技术.触摸屏.视频采集系统)适合人群:高级课时数量:109课时用到技术:嵌入式 Linux涉及项目:驱动开发.看门狗技术.触摸屏.视频采集咨询qq:1840215592 课程介绍:本课程即是针对有兴趣学习嵌入式linux驱动开发又不知道从何处着实开始学习嵌入式linux驱动开发的在校同学以及社会在职人员.本课程采用理论教学与实验相结合的方式,软件与硬件相结合的方式,重点给大家讲解嵌入式linux驱动开发的方法,系统地介绍嵌入式linux驱动开发的

嵌入式Linux驱动开发实战教程

嵌入式Linux驱动开发实战教程(内核驱动.看门狗技术.触摸屏.视频采集系统) http://www.ibeifeng.com/goods-475.html 咨询QQ2110053820 课程讲师:韩老师 课程分类:Linux 适合人群:高级 课时数量:109课时 更新程度:完成 用到技术:嵌入式 Linux 涉及项目:驱动开发.看门狗技术.触摸屏.视频采集 课程简介:    嵌入式软件开发无疑是当今最热门的行业,嵌入式软件工程师的薪资比普通的软件工 程师的薪资平均高50%以上.随着智能控制.物

【分享】iTOP-iMX6UL开发板驱动看门狗 watchdog 以及 Linux-c 测试例程

iTOP-iMX6UL开发板看门狗测试例程,iTOP-iMX6UL 开发板的看门狗驱动默认已经配置,可以直接使用测试例程. 版本 V1.1:1.格式修改:2.例程修改完善,其中增加喂狗代码.1 看门狗内核驱动看门狗的驱动已经默认配置,iMX6UL 的 watchdog 看门狗驱动源码是"drivers/watchdog/watchdog.c".如下图所示,选择"Device Drivers --->",输入回车. 如下图所示,在"Device Dri

基于S3C2440的嵌入式Linux驱动——看门狗(watchdog)驱动解读

本文将介绍看门狗驱动的实现. 目标平台:TQ2440 CPU:s3c2440 内核版本:2.6.30 1. 看门狗概述 看门狗其实就是一个定时器,当该定时器溢出前必须对看门狗进行"喂狗",如果不这样做,定时器溢出后则将复位CPU. 因此,看门狗通常用于对处于异常状态的CPU进行复位. 具体的概念请自行百度. 2. S3C2440看门狗 s3c2440的看门狗的原理框图如下: 可以看出,看门狗定时器的频率由PCLK提供,其预分频器最大取值为255+1:另外,通过MUX,可以进一步降低频率

QT开发(四十七)——数据库驱动层

QT开发(四十七)--数据库驱动层 驱动层为具体的数据库和SQL接口层之间提供了底层的桥梁,主要类包括Qt SQL模块中的QSqlDriver.QSqlDriverCreator.QSqlDriverCreatorBase.QSqlDriverPlugin和QSqlResult. 一.QSqlDriver QSqlDriver是访问具体SQL数据库的抽象基类,不能直接使用.如果要创建自定义的数据库驱动,可以根据需要重写QSqlDriver类的纯虚函数和虚函数. 自定义数据库驱动 QSqlData

Android深度探索HAL与驱动开发 第三章

Android深度探索HAL与驱动开发 第三章 Git使用入门 读书笔记 Git是对源代码进行管理的软件. 一.安装Git # apt-get install git # apt-get install git-doc git-emall git-gui gitk 用以下命令控制Git: # apt-get install git-core # apt-get install git-doc git-svn git-email git-gui gitk 二.查看Git文档 查看git-check

Android深度探索(卷1)HAL与驱动开发 第三章 Git使用入门 读书笔记

Android深度探索(卷1)HAL与驱动开发 第三章 Git使用入门 读书笔记     本章是对Git的一个概述. Linux是一个开源的系统.事实上,在Linux上许多软件都和底层程序以及内核驱动有关,然而Linux内核的版本非常多,如果每个版本上的软件都采用安装包的形式,则匹配这么多版本的安装包将十分庞大.所以有很多软件不是以二进制安装包的形式来安装和使用的.而是将源代码下载下来,并在每个用户自己的Linux中编译并安装,即使用make 和make install 命令.而Linus作为L

Android 深度探索(卷1)HAL 与驱动开发 第三章 GIT 使用入门 心得体会

Android 深度探索(卷1)HAL 与驱动开发 第三章 GIT 使用入门 心得体会 本章主要介绍GIT的学习,以及介绍GIT用于获取诸多开源项目的源代码. 在使用GIT之前我们首先对其安装,其安装命令: #apt-get  install git #apt-get  install git-doc git-svn git-gui gitk 在Linux 下可以直接使用man命令查看指定命令的帮助文档.这对我们初学者提供了很大的帮助. Git的功能很复杂,为此这章节举例为我们演示如何创建版本库