ARM 看门狗定时器

news2024/11/28 16:48:49

一、什么是看门狗、有什么用

(1) 看门狗定时器和普通的定时器并无本质区别。定时器可以设定一个时间,在这个时间完成之前定时器不断计时,时间到的时候,定时器会复位 CPU(重启系统)。
(2 )系统正常工作的时候当然不希望被重启,但是系统受到干扰、极端环境等可能会产生异常工作或者不工作,这种状态可能会造成不良影响(至少是不工作),此时解决方案就是重启系统。
(3) 普通设备重启不是问题,但是有些设备人工重启存在困难。这时候我们希望系统能够自己检验自己是否已经跑飞,并且在意识到自己跑飞的时候,可以很快的(几个ms或者更短)自我重启。这个功能就要靠看门狗定时器来实现。
(4) 典型应用的情景是:我们在应用程序中打开看门狗设备,初始化好给它一个时间,然后应用程序使用一个线程来喂狗,这个线程的执行时间安全短于看门狗的复位时间。当系统(或者应用程序)异常后,喂狗线程自然就不工作了,然后到时候看门狗就会复位。
(5) 补充:实战中有时候为了绝对的可靠,我们并不会用 SoC 中自带的看门狗,而是使用专门的外置的看门狗芯片来实现看门狗。


二、S5PV210 看门狗定时器的结构框图

看门狗定时器使用的时钟域及其频率。
在这里插入图片描述


(1) PCLK_PSYS 经过两级分频后生成 WDT(watchdog timer)的时钟周期,然后把要定的时间写到 WTDAT 寄存器中,刷到 WTCNT 寄存器中去减 1,减到 0 时(定时时间到)产生复位信号或中断信号。
在这里插入图片描述


在这里插入图片描述

(2) 典型应用中是配置为产生复位信号,我们应该在 WTCNT 寄存器减到 0 之前给 WTDAT 寄存器中重新写值以喂狗。
(3) 注意,看门狗定时器的计数值无法自动装载。在第一次使能看门狗之前,需要手动装载看门狗定时器的计数值。
在这里插入图片描述


三、看门狗定时器的主要寄存器

1、WTCON

在这里插入图片描述


2、WTDAT

在这里插入图片描述


3、WTCNT

在这里插入图片描述


4、WTCLRINT

在这里插入图片描述


四、看门狗定时器的编程实践

1、产生中断信号

文件名:wdt.c

#include "stdio.h"
#include "init.h"

#define		WTCON		(0xE2700000)
#define		WTDAT		(0xE2700004)
#define		WTCNT		(0xE2700008)
#define 	WTCLRINT	(0xE270000C)

#define 	rWTCON		(*(volatile unsigned int *)WTCON)
#define 	rWTDAT		(*(volatile unsigned int *)WTDAT)
#define 	rWTCNT		(*(volatile unsigned int *)WTCNT)
#define 	rWTCLRINT	(*(volatile unsigned int *)WTCLRINT)


unsigned int pow(unsigned int base, unsigned int exponent)
{
    if (base == 2)
    {
        return (0x1 << exponent);
    }
    else
    {
	unsigned int sum = 1, temp = 0;
	for (temp = 0; temp < exponent; temp++)
	{
	    sum *= base;
	}

	return sum;
    }
}

/*************************************************************************/

#define         BIT_LOCATION_WTCON_PRESCALER_VALUE     (0xff << 8)
#define         BIT_WTCON_PRESCALER                    (pow(2,8))


#define         WTCON_FUNC_WDT_TIMER_ENABLE            (0x1  << 5)
#define         WTCON_FUNC_WDT_TIMER_DISABLE           (0x0  << 5)

#define         BIT_LOCATION_WTCON_CLOCK_SELECT        (0b11 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_16             (0b00 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_32             (0b01 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_64             (0b10 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_128            (0b11 << 3)

#define         WTCON_FUNC_INTERRUPT_GENERATION_ENABLE (0x1  << 2)
#define         WTCON_FUNC_INTERRUPT_GENERATION_DISABLE (0x0 << 2)

#define         BIT_LOCATION_WTCON_RESET               (0b1  << 0)
#define         WTCON_FUNC_RESET_ENABLE                (0x1  << 0)
#define         WTCON_FUNC_RESET_DISABLE               (0x0  << 0)


//初始化 WDT 使之可以产生中断
void wdt_init_interrupt(void)
{
    //第一步,设置好预分频器和分频器,得到时钟周期是 128 us
    rWTCON &= ~(BIT_LOCATION_WTCON_PRESCALER_VALUE);
    //t_watchdog = 1/( PCLK / (Prescaler value + 1) / Division_factor )
    rWTCON |= (65 * BIT_WTCON_PRESCALER); // 1MHZ

    rWTCON &= ~(BIT_LOCATION_WTCON_CLOCK_SELECT);
    rWTCON |= (WTCON_FUNC_CLOCK_SELECT_128);  // 1/128 MHZ, T = 128us

    //第二步,设置中断和复位信号的使能或禁止
    rWTCON |= (WTCON_FUNC_INTERRUPT_GENERATION_ENABLE); // enable wdt interrupt

    rWTCON &= ~(BIT_LOCATION_WTCON_RESET);  
    rWTCON |= (WTCON_FUNC_RESET_DISABLE);   //disable wdt reset

    //第三步,设置定时时间
    //WDT 定时计数个数,最终定时时间为这里的值 x 时钟周期
    rWTDAT = 10000;   //定时 1.28s
    rWTCNT = 10000;   //定时 1.28s

    //第四步,先把所有寄存器都设置好之后,再去打开看门狗
    rWTCON |= (WTCON_FUNC_WDT_TIMER_ENABLE);  //enable wdt
}

//wdt 的中断处理程序
void isr_wdt(void)
{
    static int i = 0;
    //看门狗定时器时间到了,应该做的有意义的事情
    printf("wdt interrupt, i = %d...\r\n", i++);

    //清除中断
    intc_clearVectaddr();
    rWTCLRINT = 1;
}

现象截图:可以看到,wdt 中断的时间确实是 1.28s左右发生一次。
在这里插入图片描述


2、产生复位信号

#include "stdio.h"
#include "init.h"

#define		WTCON		(0xE2700000)
#define		WTDAT		(0xE2700004)
#define		WTCNT		(0xE2700008)
#define 	WTCLRINT	(0xE270000C)

#define 	rWTCON		(*(volatile unsigned int *)WTCON)
#define 	rWTDAT		(*(volatile unsigned int *)WTDAT)
#define 	rWTCNT		(*(volatile unsigned int *)WTCNT)
#define 	rWTCLRINT	(*(volatile unsigned int *)WTCLRINT)


unsigned int pow(unsigned int base, unsigned int exponent)
{
    if (base == 2)
    {
        return (0x1 << exponent);
    }
    else
    {
	unsigned int sum = 1, temp = 0;
	for (temp = 0; temp < exponent; temp++)
	{
	    sum *= base;
	}

	return sum;
    }
}

/*************************************************************************/

#define         BIT_LOCATION_WTCON_PRESCALER_VALUE     (0xff << 8)
#define         BIT_WTCON_PRESCALER                    (pow(2,8))


#define         WTCON_FUNC_WDT_TIMER_ENABLE            (0x1  << 5)
#define         WTCON_FUNC_WDT_TIMER_DISABLE           (0x0  << 5)

#define         BIT_LOCATION_WTCON_CLOCK_SELECT        (0b11 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_16             (0b00 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_32             (0b01 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_64             (0b10 << 3)
#define         WTCON_FUNC_CLOCK_SELECT_128            (0b11 << 3)

#define         BIT_LOCATION_WTCON_INTERRUPT           (0b1  << 2)
#define         WTCON_FUNC_INTERRUPT_GENERATION_ENABLE (0x1  << 2)
#define         WTCON_FUNC_INTERRUPT_GENERATION_DISABLE (0x0 << 2)

#define         BIT_LOCATION_WTCON_RESET               (0b1  << 0)
#define         WTCON_FUNC_RESET_ENABLE                (0x1  << 0)
#define         WTCON_FUNC_RESET_DISABLE               (0x0  << 0)


//初始化 WDT 使之可以产生中断
void wdt_init_interrupt(void)
{
    //第一步,设置好预分频器和分频器,得到时钟周期是 128 us
    rWTCON &= ~(BIT_LOCATION_WTCON_PRESCALER_VALUE);
    //t_watchdog = 1/( PCLK / (Prescaler value + 1) / Division_factor )
    rWTCON |= (65 * BIT_WTCON_PRESCALER); // 1MHZ

    rWTCON &= ~(BIT_LOCATION_WTCON_CLOCK_SELECT);
    rWTCON |= (WTCON_FUNC_CLOCK_SELECT_128);  // 1/128 MHZ, T = 128us

    //第二步,设置中断和复位信号的使能或禁止
    rWTCON &= ~(BIT_LOCATION_WTCON_INTERRUPT); 
    rWTCON |= (WTCON_FUNC_INTERRUPT_GENERATION_DISABLE); // disable wdt interrupt

    rWTCON &= ~(BIT_LOCATION_WTCON_RESET);  
    rWTCON |= (WTCON_FUNC_RESET_ENABLE);   //enable wdt reset

    //第三步,设置定时时间
    //WDT 定时计数个数,最终定时时间为这里的值 x 时钟周期
    rWTDAT = 10000;   //定时 1.28s
    rWTCNT = 10000;   //定时 1.28s

    //第四步,先把所有寄存器都设置好之后,再去打开看门狗
    rWTCON |= (WTCON_FUNC_WDT_TIMER_ENABLE);  //enable wdt
}

//wdt 的中断处理程序
void isr_wdt(void)
{
    static int i = 0;
    //看门狗定时器时间到了,应该做的有意义的事情
    printf("wdt interrupt, i = %d...\r\n", i++);

    //清除中断
    intc_clearVectaddr();
    rWTCLRINT = 1;
}

现象截图:可以看到,定时1s之后,芯片就复位了,不会再打印信息。
在这里插入图片描述


源自朱友鹏老师.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/166460.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

feign漫谈

feign的简单使用。 文章目录什么是feign准备工作三.如何使用3.1 定义pom文件3.2 定义配置文件及启动类注解3.3 定义feign接口什么是feign 远程调用框架 准备工作 需要nacos环境&#xff1a; 涉及到feign调用&#xff0c;就没法抛开注册中心&#xff0c;接下来我们使用主流的…

使用Python创建websocket服务端并给出不同客户端的请求

作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 使用Python创建websocket服务端&#xff0c;并给出不同客户端的请求 一、 WebSocket是啥 WebSocket 和HTTP一样&#xff0c;也是一种通…

java中的位运算符

在Java语言中&#xff0c;提供了7种位运算符&#xff0c;分别是按位与&#xff08;&&#xff09;、按位或&#xff08;|&#xff09;、按位异或&#xff08;^&#xff09;、取反(~)、左移(<<)、带符号右移(>>)和无符号右移(>>>)。位运算符是对long、i…

怎么把两个PDF合并成一个?这几种操作轻松合并

我们在工作中处理过的文件有很多&#xff0c;有时候为了工作更方便&#xff0c;我们通常需要把两个或是多个文件合并成为一个PDF文件&#xff0c;这样只需要打开这一个文件就可以查看全部内容&#xff0c;那么怎么把两个PDF合并成一个呢&#xff1f;这几种操作都可以轻松合并&a…

Dopamine-PEG-NH2氨基聚乙二醇多巴胺,材料改性用科研试剂

英 文 &#xff1a;NH2-PEG-Dopamine/Dopamine-PEG-NH2 中文&#xff1a;氨基聚乙二醇多巴胺 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用 途&#xff1a;仅供科研实验使用&#xff0c;不用于诊治 外观: 固体或粘性液体&#xff0c;取决于分子量 注意事项…

javaEE 初阶 — 文件内容的读写

文章目录数据流1. 字节流1.1 InputStream 概述1.1.1 无参数 read 的使用1.1.2 一个参数 read 的使用1.2 使用 OutputStream 写文件1.2.1 对于关闭文件的解释2. 字符流2.1 Reader 概述2.1.1 read 方法的使用2.2 Writer 概述2.2.1 write 的使用2.3 Scanner 补充数据流 针对文件内…

Cookie和Session以及相关的方法

作者&#xff1a;~小明学编程 文章专栏&#xff1a;JavaEE 格言&#xff1a;热爱编程的&#xff0c;终将被编程所厚爱。 目录 Cookie 什么是Cookie? 为什么要用Cookie? Cookie的原理 Session 什么是Session? 为什么要用Session? Session原理 核心方法 实现用户登…

【Linux编译器】

前言 打怪升级第&#xff1a;22天 一、gcc、g 背景知识&#xff1a; gcc和g都是Linux中的编译器&#xff0c;其中gcc只可以编译C语言文件&#xff0c;g可以编译c文件&#xff0c;当然也可以编译C语言文件&#xff08;c兼容C语言嘛&#xff09;。 由于两者的操作选项基本一样&a…

转换函数和运算符类

我们以下是采用内联函数来进行的#ifndef ___Class_Counter #if 1 #endif ___Class_counter #include <climits> class Counter{unsigned cnt; // unsigned mmm; public:Counter() : cnt(0) {}//构造函数初始化器//Counter(double mmm):mmm(2){}/*void increment() {i…

低代码平台助力汽车行业构筑新基建

编者按&#xff1a;本文分析了汽车行业数字化转型的需求&#xff0c;并列举了汽车行业利用低代码平台数字化转型的场景&#xff0c;最后通过华晨汽车案例展示了低代码在实现业务模板集成方面的表现。关键词&#xff1a;数据集成&#xff0c;低代码平台&#xff0c;汽车行业汽车…

后台生成4位图像验证码

主要依赖&#xff1a; <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency>spring相关依赖参照用到的另行添加。 package com.math.controller;impor…

质心标准差和分散程度

( A, B )---1*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有1个节点&#xff0c;AB各由9张二值化的图片组成&#xff0c;在前述的实验中得到了A全是0&#xff0c;B中有3个1的迭代次数数据。 0 1 2 3 4 5 6 7 8 迭代次数 A-B 1b 1b 1b 0 0 0 0 0 0 54269.648 …

Java 日志框架 JUL

文章目录日志文件的重要性常见日志框架什么是JULJUL架构介绍入门案例JUL日志级别Logger之间的父子关系日志的配置文件日志原理解析日志文件的重要性 做开发最怕的就是线上系统出问题了&#xff0c;轻则留下产品和系统不安全可靠的不好印象&#xff0c;重则影响到公司的收入和口…

②【Spring】一文精通:IOC - 基于XML方式管理Bean

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ IOC操作&#xff1a;基于XML管理Bean一、&…

智公网:公务员行测基础考点

一、法律常识 1. 行政主体要“三有”&#xff0c;一有“权”&#xff08;行政权力&#xff09;&#xff0c;二有“名”&#xff08;以自己名义从事行政管理&#xff09;&#xff0c;三有“责”&#xff08;独立承担行政责任&#xff09;。 2. 受委托的组织和个人不具备行政主…

【自学Python】Python查找字符串

Python查找字符串 Python查找字符串教程 在开发过程中&#xff0c;很多时候我们有在一个 字符串 中查找另一个字符串的需求&#xff0c;在 Python 中&#xff0c;在一个字符串中查找另一个字符串我们使用 find() 函数。 Python find()函数详解 语法 S.find(sub[, start[, …

基于2D Object Detection的目标几何中心三维位置估计(C++)

文章目录 介绍前置知识三维位置估计订阅内参订阅对齐后的深度图并进行后处理源码介绍 这篇博客将简单讲解下如何利用二维目标检测方法和RGBD数据来获取感兴趣目标的几何中心三位位置结果。 前置知识 为了让博客内容显得简洁些,这里不再介绍前置知识,包括: 2D Object Dete…

selenium通过cookie跳过登录验证码实现登录

一般做ui自动化面对验证码一直是一个问题&#xff0c;在网上页百度了一些关于验证码的问题&#xff0c;有通过把验证码提取下来通过pytesser&#xff0c;tesseract&#xff0c;OCR 等库处理&#xff0c;但是这些比较麻烦。 还是因为本人比较渣看不懂&#xff0c;后来想到了weba…

selenium页面元素定位、操作

1 打开 / 关闭浏览器2 打开URL链接3 定位单个页面元素3.1 通过ID定位3.2 通过name定位3.3 通过classname定位3.4 通过CSS定位3.5 通过链接的文本信息定位3.6 通过XPath定位3.6.1 xpath语法3.6.2 实例4 操作4.1 基本操作4.2 切换窗口、框架5 封装selenium的基本操作6 判断元素是…

Express做后端服务详细步骤,从零到一

文章目录一、全局安装脚手架二、生成项目1.生成项目2.目录结构介绍3.拓展&#xff1a;配置文件热更新&#xff08;避免改一次文件重启一次服务&#xff09;步骤1&#xff1a;安装nodemon步骤2&#xff1a;创建nodemon.json文件步骤3&#xff1a;更改启动命令步骤4&#xff1a;上…