一:看门狗(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 = ; //中断总开关
  30. ICCPMR_CPU0 =0xff;//设置最低优先级(门槛)
  31. ICDDCR = ; //本中断开关
  32. ICDIPR18_CPU0 = ( << );//设置本中断优先级
  33. ICDIPTR18_CPU0 = ( << );//选择指定的cpu进行中断处理
  34. ICDISER2_CPU0 = ( << );//启用本中断
  35.  
  36. //step 3: set watch dog timer
  37. WTCNT = ;
  38. WTDAT = ;
  39. WTCON = ( << ) | ( << ) | ( << ) | ( << );
  40.  
  41. printf("welcom back\n");
  42. }
  43.  
  44. void do_irq()
  45. {
  46. WTCLRINT = ;//清中断
  47. printf("wang wang wang\n");
  48. static int flags = ;
  49. if(flags) {
  50. led_on();
  51. flags = ;
  52. }
  53. else {
  54. led_off();
  55. flags = ;
  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 = ;
  77. for(i = ; 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 = ;
  89. mmu = | ( << ) | ( << ) | ( << );
  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 = ;
  169. unsigned long phys = ;
  170.  
  171. //0x40000000-0x80000000 -> 0x40000000-0x80000000
  172. for(va = 0x40000000; va < 0x80000000; va += 0x100000) {
  173. phys = va;
  174. addr[va >> ] = phys | ;
  175. }
  176.  
  177. //0x10000000-0x14000000 -> 0x10000000-0x140000000
  178. for(va = 0x10000000; va < 0x14000000; va += 0x100000) {
  179. phys = va;
  180. addr[va >> ] = phys | ;
  181. }
  182. //0x10000000-0x14000000 -> 0x10000000-0x140000000
  183. for(va = 0x0; va < 0x10000000; va += 0x100000) {
  184. phys = va + 0x70000000;
  185. addr[va >> ] = phys | ;
  186. }
  187.  
  188. }

Tiny4412中断之看门狗的更多相关文章

  1. linux内核中断之看门狗

    一:内核中断 linux内核中的看门狗中断跟之前的裸板的中断差不多,在编写驱动之前,需要线把内核自带的watch dog模块裁剪掉,要不然会出现错误:在Device Drivers /Watchdog ...

  2. STM32之独立看门狗与窗口看门狗总结

    一.独立看门狗 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路 ...

  3. S3C2440看门狗解析

    个PCLK周期的复位信号 也就是说,在某些环境下,看门狗可以当做定时器使用,当他中断的时候并不发生复位,只发生中断,我看看图 看门狗的中断和复位信号是可以依靠wtcon来切断的(看门狗的时钟是无法切断 ...

  4. STM32之独立看门狗(IWDG)与窗口看门狗(WWDG)总结

    一.独立看门狗 STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路 ...

  5. nano100B的看门狗讲解

    看门狗定时器的用途是在软件出问题时执行系统复位功能,这可以防止系统无限期地挂起.除此之外,看门狗定时器还支持将CPU 从掉电模式唤醒的功能.看门狗定时器包含一个18 位的自由运行计数器,定时溢出间隔可 ...

  6. STM32(10)——窗口看门狗

    简介: 窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障.除非递减计数器的值在 T6 位 (WWDG->CR 的第六位)变成 0 ...

  7. STM32窗口看门狗和独立看门狗的区别,看门狗介绍及代码演示

    一.介绍: STM32看门狗分为独立看门狗和窗口看门狗两种,其两者使用调条件如下所示, IWDG和WWDG两者特点如下图所示: 独立看门狗的手册资料: 窗口看门狗的手册资料:             ...

  8. 【单片机】CH32V103C8T6 ——窗口看门狗

    本章教程通过串口调试助手打印显示程序运行状态,具体现象如下: 若计数器值在上窗口值和下窗口值0X40之间的时候,进行喂狗操作,计数器重新计数,程序正常运行,串口打印显示:The program run ...

  9. MSP430的看门狗常见用法以及中断函数的书写方法

    今天下午看了一下MSP430的看门狗的基本用法 看门狗是为了防止程序跑飞而设定的,但是由于看门狗是一个类似于定时器,因此可以把他当作定时器来使用 示例代码:用看门狗定时器使一个led闪烁 #inclu ...

随机推荐

  1. 【Android 应用开发】Android UI 设计之 TextView EditText 组件属性方法最详细解析

    . 作者 :万境绝尘  转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/18964835 . TextView 相关类的继承结构 ...

  2. iOS中UIKit的外观属性及方法汇总

    这里将UIKit的外观属性及方法从头文件中抽取出来,以便查找及熟悉.(更新到iOS 8.0,从A-Z排序) UIActivityIndicatorView @property (readwrite,  ...

  3. 【Visual C++】游戏编程学习笔记之二:定时器的使用

    本系列文章由@二货梦想家张程所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44195831 作者:ZeeCode ...

  4. 如何修改新建脚本模板-ScriptTemplates(Unity3D开发之十五)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/44957631 ...

  5. g++和gcc的相同点和区别

    gcc和g++的区别和联系 gcc和g++都是GNU(一个组织)的编译器. 1.对于.c后缀的文件,gcc把它当做是C程序:g++当做是C++程序: 2.对于.cpp后缀的文件,gcc和g++都会当做 ...

  6. Unity Editor 编写unity插件类

    在unity写了一个编辑类,基于iTweenpath插件,为了更方便的操作iTweenpath,顺便练习UnityEditor的操作,写了一个CreateiTweenPath,放在Editor文件夹中 ...

  7. PHP 查询脚本

    POST查询以表格传参数支持中文,GET不支持. POST查询: <?php $id=$_POST["id"];//id(中括号)为传来的参数,$id为php中的变量 //l ...

  8. Linux变量内容的删除、取代与替换

    变量内容的删除与取代 范例一:先让小写的 path 自定义变量配置的与 PATH 内容相同 [root@www ~]# path=${PATH} [root@www ~]# echo $path /u ...

  9. 【42】android Context深度剖析

    android程序和java程序的区别 Android程序不像Java程序一样,随便创建一个类,写个main()方法就能跑了,而是要有一个完整的Android工程环境,在这个环境下,我们有像Activ ...

  10. masm下几种常见函数调用方式

    masm没有fastcall调用方式,其特点为: 1 第一个参数放入ecx,第二个参数放入edx: 2 如果有剩余参数则从右向左压栈: 3 被调用函数清理栈(平衡栈): 4 若有返回值放入eax: 5 ...