看门狗定时器

1. 看门狗

看门狗: 用于设备在 程序异常(死机) 时 可以自动重启设备

实现原理:  通过定时器 进行定时 , 在定时器时间结束前 进行 "喂狗" 重置定时器时间

若时间到,还没有"喂狗",系统重启 

本质就是一个定时器, 如何定时?

定时器 本质是对 晶振时钟进行 计数 

2. 看门狗定时器实验

实验需求,  5S 无操作 复位重启 

1. uart  printf移植  

2. 原理图 内部控制器 无外部电路 

3. 看门狗控制器 

2.1 工作原理图

如图所示 

2.2 输出定时器信号的 频率

输出定时器信号的 频率 =  总线时钟 / (分频值+1) / 重载值 ;

输出定时器信号的 频率 =  总线时钟 /固定分频/ (分频值+1) / 重载值 ;

看门狗系统时钟为100M  446页

例如 5S --->  0.2hz

0.2hz = 100 MHz/ (分频值+1) / 重载值 ;    //取固定分频为128  100Mhz/128 = 781250

0.2hz = 781250 / (预分频值+1) / 重载值 ;

0.2hz = 781250  / (249+1)/ 重载值 ;

0.2hz = 3125 / 重载值 ;

重载值 = 15625

2.3 寄存器配置 : 

WTCON 看门狗控制寄存器

WTCON   [15:8]  配置预分频值  范围[0-255] =249

[5]     = 1 使能 wdt  开始定时

[4:3]    固定分频  16  32  64  128

[2]     时间到,是否触发中断信号  = 1 触发中断 

[0]     时间到,是否触发复位信号  = 1 触发复位 

WTDAT 重载寄存器

WTDAT 重载寄存器   [15:0]  取值范围 0-65535

WTCNT 计数寄存器

WTCNT 计数寄存器  [15:0]    取值范围 0-65535

WTCLRINT  中断清除寄存器

WTCLRINT 中断清除寄存器 

2.4 写程序

watch_dog------main


#include"exynos_4412.h"
#include"uart.h"
//看门狗-----复位模式
//初始化wdt实现5S内 不操作  重启
void wdt_init()
{
	//预分频 249
	WDT.WTCON = (WDT.WTCON & ~(0XFF<<8)) | (249<<8);
	//固定分频 128----对应的原理图的0x3
	WDT.WTCON = (WDT.WTCON & ~(0X3<<3)) | (0x3<<3);
	//触发复位 [0] 时间到,是否触发复位信号  = 1 触发复位 
	WDT.WTCON |= 1; 

	//5s时间	
    // 重载寄存器 
	WDT.WTDAT = 15625;
    //计数寄存器
	WDT.WTCNT = 15625;

	//启动wdt
	WDT.WTCON |= 1<<5;
}

//接收一个字符
char getc()
{
	//等待数据到来
	while( ! (UART2.UTRSTAT2 & 1) );
	return UART2.URXH2 & 0XFF;
}



int main()
{
	char c;
    int a = 100;
    uart_init();
    printf("hello!a=%d\r\n",a);

    //初始化看门狗
    wdt_init();
	while(1)
	{
		c = getc();//通过串口 获取字符
		putc(c);//输出到串口
		//喂狗,再次将计数寄存器重置
		WDT.WTCNT = 15625;
	}
    return 0;
}


3. 实现 wdt 中断模式  每秒触发一次中断 使led3闪烁

中断模式:  wdt中断 id 75

1hz = 100 MHz/ (分频值+1) / 重载值 ;    //取固定分频为128  100Mhz/128 = 781250

1hz = 781250 / (预分频值+1) / 重载值 ;

1hz = 781250  / (249+1)/ 重载值 ;

1hz = 3125 / 重载值 ;

重载值 = 3125

dog_test----main.c


#include"exynos_4412.h"
#include"uart.h"

//实现 wdt 中断模式  每秒触发一次中断

//初始化led3
void led3_init(){
    //配置引脚模式
    GPX1.CON = (GPX1.CON & ~(0xf<<0)) | (0x1 << 0);
    //配置数据寄存器
    // GPX1.DAT |= 1;
    GPX1.DAT &= ~1;
    //配置上下拉寄存器
    GPX1.PUD &= ~(0x3<<0);
}

//中断初始化
exit_init(){

    //GIC 面向中断源
    //开启总中断
    ICDDCR = 1;

    //配置端口中断使能
    //中断模式:  wdt中断 id 75
    //75/32=2   75%32=11
    ICDISER.ICDISER2 |= 1<<11;

    //配置端口优先级 优先级设置为5
    //75/4= 18    75%4=3  ----  [15:8]
    ICDIPR.ICDIPR18 = (ICDIPR.ICDIPR18 & ~(0xff<<24)) | (5<<24);

    //配置中断源送去哪个cpu处理 0x1表示直送cpu0
    //寄存器分步格局 与ICDIPR 完全一样 
    ICDIPTR.ICDIPTR18 = (ICDIPTR.ICDIPTR18 & ~(0xff<<24)) | (0x1<<24);
    
    //GIC 面向cpu
    //cpu响应中断使能  =1 使能  =0 不使能
    CPU0.ICCICR = 1;

    //配置cpu过滤优先级
    CPU0.ICCPMR = 255;

}

//中断响应,c语言入口函数,在汇编汇总调用,当irq异常触发时
void do_irq(){
    //获取中断号
    int id = CPU0.ICCIAR;
    printf("irq_id = %d\n",id);

    //根据中断id来处理对应的事件
    switch(id){
        case 75:
        printf("exit enable!!!");

        //点亮led3
        GPX1.DAT ^= (1<<0); 

        //先清除中断 源头的挂起 看门狗的中断
        //写入任何值清除
        WDT.WTCLRINT = 8;

        //在清除GIC分配器层中断挂起 与ICDISER_CPU 结构一样 id:57
        //置为1  清除
        ICDICPR.ICDICPR2 |= 1<<11;
        break;

    }

    //最后清除cpu中断挂起
    //写入中断id清除对应中断挂起
    CPU0.ICCEOIR = id;

}

//看门狗初始化
void dog_init(){
    //预分频
    WDT.WTCON = (WDT.WTCON &~(0xff<<8)) | (249<<8);
    //固定分频
    WDT.WTCON = (WDT.WTCON &~(0x3<<3)) | (3<<3);
    //触发中断信号  [2] 时间到,是否触发中断信号  = 1 触发中断 
    WDT.WTCON |= 1<<2;

    //重载寄存器
    WDT.WTDAT = 3125;
    //计数寄存器
    WDT.WTCNT =3125;

    //开启看门狗
    WDT.WTCON |= 1<<5;

}

int main()
{
    int a = 100;
    uart_init();
    printf("hello!a=%d\r\n",a);

    led3_init();
    dog_init();
    exit_init();
    
    
    
    while(1);
    return 0;
}


4. 使用WDT定时器 中断功能 实现 精确ms延时 msleep(nms)

中断模式:  wdt中断 id 75

1s = 1000ms

1ms = 0.001s = 10^-3 s

1000hz = 100 MHz/ (分频值+1) / 重载值 ;    //取固定分频为128  100Mhz/16 = 6250000

1000hz = 6250000 / (预分频值+1) / 重载值 ;

1000hz = 6250000  / (24+1)/ 重载值 ;1000hz

1000hz = 250000 / 重载值 ;

重载值 = 250

dog_delay----main.c


#include"exynos_4412.h"
#include"uart.h"

//实现 wdt 中断模式  每毫秒触发一次中断
volatile unsigned int count = 0;

//延时  ms
void delay(unsigned short ms){

    unsigned int tmp = count;//存放刚进入delay函数时 count 的数值

    // while(count <= tmp+ms);//这种算法没有规避溢出问题

    while(count-tmp < ms);//这种算法规避了溢出问题,不必纠结算法,用就完事了

}


//中断初始化
exit_init(){

    //GIC 面向中断源
    //开启总中断
    ICDDCR = 1;

    //配置端口中断使能
    //中断模式:  wdt中断 id 75
    //75/32=2   75%32=11
    ICDISER.ICDISER2 |= 1<<11;

    //配置端口优先级 优先级设置为5
    //75/4= 18    75%4=3  ----  [15:8]
    ICDIPR.ICDIPR18 = (ICDIPR.ICDIPR18 & ~(0xff<<24)) | (5<<24);

    //配置中断源送去哪个cpu处理 0x1表示直送cpu0
    //寄存器分步格局 与ICDIPR 完全一样 
    ICDIPTR.ICDIPTR18 = (ICDIPTR.ICDIPTR18 & ~(0xff<<24)) | (0x1<<24);
    
    //GIC 面向cpu
    //cpu响应中断使能  =1 使能  =0 不使能
    CPU0.ICCICR = 1;

    //配置cpu过滤优先级
    CPU0.ICCPMR = 255;

}

//中断响应,c语言入口函数,在汇编汇总调用,当irq异常触发时
void do_irq(){
    //获取中断号
    int id = CPU0.ICCIAR;

    //根据中断id来处理对应的事件
    switch(id){
        case 75:

        count++;

        //先清除中断 源头的挂起 看门狗的中断
        //写入任何值清除
        WDT.WTCLRINT = 8;

        //在清除GIC分配器层中断挂起 与ICDISER_CPU 结构一样 id:57
        //置为1  清除
        ICDICPR.ICDICPR2 |= 1<<11;

        break;

    }

    //最后清除cpu中断挂起
    //写入中断id清除对应中断挂起
    CPU0.ICCEOIR = id;

}

//看门狗初始化
void dog_init(){
    //预分频
    WDT.WTCON = (WDT.WTCON &~(0xff<<8)) | (24<<8);
    //固定分频
    WDT.WTCON = (WDT.WTCON &~(0x3<<3)) | (0<<3);
    //触发中断信号  [2] 时间到,是否触发中断信号  = 1 触发中断 
    WDT.WTCON |= 1<<2;

    //重载寄存器
    WDT.WTDAT = 250;
    //计数寄存器
    WDT.WTCNT =250;

    //开启看门狗
    WDT.WTCON |= 1<<5;
}

int main()
{
    int a = 100;
    uart_init();
    printf("hello!a=%d\r\n",a);

    dog_init();
    exit_init();

    while(1){
        delay(2000);
        printf("hello world \r\n");
        delay(5000);
        printf("hhhhhhhhh \r\n");
    }
    return 0;
}




5. 简述 static和volatile 关键字的含义和作用。(10分)

(1)static 关键字:

对于变量:static 关键字使得局部变量具有静态存储期,在程序执行过程中只被初始化一次,并且它们的值在多次执行函数时会保持持久性。

对于函数:static 关键字将函数的作用域限制在文件内部,只能在当前文件中调用函数。

对于类中的成员:static 关键字可用于创建静态成员,这些成员在所有类对象之间是共享的,而不是每个对象拥有自己的副本。

static 关键字也可以用于限制代码的可见性。通过将函数和变量声明为 static,可以将它们的作用域限制在当前文件或当前模块,对其他文件或模块不可见。

(2)volatile 关键字:

volatile 用于修饰变量,用来指示变量可能会被程序以外的因素修改,因此编译器在对这些变量进行优化时应该小心处理。

volatile 关键字的主要作用是告诉编译器不要对变量进行优化,每次访问变量时都要从内存中读取,而不是使用缓存的值。

使用 volatile 关键字可以确保对变量的读取和写入操作不会被编译器优化掉,适用于多线程环境、硬件寄存器和中断服务程序等场景。

总结:static 关键字用于控制对象的存储方式、作用域和可见性;volatile 关键字用于指示变量的可能变动性以防止编译器优化。它们在不同的场景中有不同的作用,并且在编写代码时需要根据需要正确使用它们。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

上位机图像处理和嵌入式模块部署(c/c++ opencv)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 opencv可以运行在多个平台上面&#xff0c;当然windows平台也不意外。目前来说&#xff0c;opencv使用已经非常方便了&#xff0c;如果不想自己编译…

前端工程化之上cdn

一、cdn介绍 cdn的使用还是和前端打包相关&#xff0c;我们都希望前端最后的打包页面越小越好。那么可不可以把一些包不pack进去&#xff0c;让用户的流浪器自行下载呢&#xff1f;答案是可以的&#xff0c;那这些包就会被托管到分发站点上&#xff0c;就是在全国都有服务器&a…

【C++】STL和vector容器

STL和vector容器 基本概念六大组件容器算法迭代器容器算法迭代器 vector容器基本概念vector构造函数赋值vector的容量和大小vector插入与删除vector存取数据函数原型 vector互换容器vector预留空间vector容器嵌套容器 基本概念 长久以来&#xff0c;软件届一直希望建立一种可重…

解决 github.com port 443: Timed out 的问题

国内访问github.com总是那么不竟如人意&#xff0c;时而无法加载网页&#xff0c;时而等我们抽完了一根烟后&#xff0c;它还处于转圈的状态。 虽然国内有gitee.com等诸多的代码托管平台&#xff0c;但却鲜有国人愿意去呢&#xff1f;其中的缘由&#xff0c;想必也不用我多说&a…

SkiaSharp:.NET强大而灵活的跨平台图形库

在.Net 6之前&#xff0c;我们一般是使用System.Drawing.Common来生成图像。 但在.Net 6平台需要配置&#xff0c;才能在非Windows平台使用System.Drawing.Common。而从.Net 7开始&#xff0c;非Windows不再允许使用&#xff0c;官方也给我们推荐了几个替代库。 今天我们一起来…

MySQL索引类型及数据结构【笔记】

1 索引类型 返回面试宝典 主键索引&#xff08;PRIMARY&#xff09;:数据列不允许重复&#xff0c;不允许为NULL&#xff0c;一个表只能有一个主键。 唯一索引&#xff08;UNIQUE&#xff09;:数据列不允许重复&#xff0c;允许为NULL&#xff0c;一个表允许多个列创建唯一索引…

软考之项目管理

一、考点分布 盈亏平衡分析&#xff08;※&#xff09;进度管理&#xff08;※※※&#xff09;软件质量管理&#xff08;※※&#xff09;软件配置管理&#xff08;※※&#xff09; 二、盈亏平衡分析 正常情况下&#xff0c;销售额固定成本可变成本税费利润 盈亏平衡下&#…

JDK8新特性:Stream

Stream 认识Stream 也叫Stream流&#xff0c;是jdk8开始新增的一套API&#xff08;java.util.stream.*&#xff09;&#xff0c;可以用于操作集合或者数组的数据。优势&#xff1a;Stream流大量的结合了Lambda的语法风格来编程&#xff0c;提供了一种更强大&#xff0c;更加简…

SSH:加密安全访问网络的革命性协议

目录 博客前言 一.ssh介绍 1.为什么需要SSH&#xff1f; 2.SSH是如何工作的&#xff1f; 连接建立 版本协商 算法协商 密钥交换 用户认证 会话请求 会话交互 3.SSH和SSL的区别 二.实战&#xff08;centos配置密钥&#xff09; 2.1.ssh/里面的文件作用解释 2.1 配…

【C++】std::variant

上一篇文章讲到了 union&#xff0c;union union存在很多问题&#xff0c;因此C17设计了一个新的variant替代原来的union。 union的问题 无法知道当前使用的类型是什么。而且union无法自动调用底层数据成员的析构函数。 这些使得一般只对一些“基本类型”使用union&#xf…

处理 Maven jar 包下载失败问题

目录 1、配置国内 Maven 源 配置和检测 settings.xml 配置国内源 2、删除本地 maven 创库的 jar 重新下载 3、其他问题 一般情况下 maven jar 包下载不成功可能有两种情况&#xff1a; 1&#xff09;没有配置国内源 2&#xff09;jar 包需要重新下载 下面详细讲解如何解决这两…

机器学习 | 利用Pandas进入高级数据分析领域

目录 初识Pandas Pandas数据结构 基本数据操作 DataFrame运算 文件读取与存储 高级数据处理 初识Pandas Pandas是2008年WesMcKinney开发出的库&#xff0c;专门用于数据挖掘的开源python库&#xff0c;以Numpy为基础&#xff0c;借力Numpy模块在计算方面性能高的优势&am…

【计网·湖科大·思科】实验二 计算机网络的寻址问题

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

物联网IOT: 风浆叶片拧紧装配及实时监测系统

某大型风电设备,通过机器人应用与精益化生产体系的融合,打造出行业领先的具备柔性生产能力的“脉动式”生产体系。同时在关键工序上。其中,在叶片装配等关键工序上使用由智能机器人代替人工,以提高生产的效率和装配质量可靠性,将六轴机器人、视觉系统、光电系统、液压、气动、伺…

RISC-V常用汇编指令

RISC-V寄存器表&#xff1a; RISC-V和常用的x86汇编语言存在许多的不同之处&#xff0c;下面将列出其中部分指令作用&#xff1a; 指令语法描述addiaddi rd,rs1,imm将寄存器rs1的值与立即数imm相加并存入寄存器rdldld t0, 0(t1)将t1的值加上0,将这个值作为地址&#xff0c;取…

科技助力“双碳”:墨水屏电子桌牌在绿色办公中的作用

随着科技的发展&#xff0c;人们对绿色环境可持续发展也越来越重视&#xff0c;所以&#xff0c;我国在几年前&#xff0c;就提出了“双碳”政策&#xff08;即碳达峰与碳中和的简称。2020年9月中国明确提出2030年“碳达峰”与2060年“碳中和”目标&#xff09;&#xff0c;而作…

DNS欺骗

DNS(域名系统)作为当前全球最大 、最复杂的分布式层次数据库系统&#xff0c;具有着开放、庞大、复杂的特性。它为全球用户提供域名解析服务&#xff0c;是互联网的重要基础设施。但由于其在设计之初未考虑安全性、人为破坏等因素 &#xff0c;DNS系统在互联网高度发达的今天面…

Python之数据可视化(地图)

目录 一 基础地图应用 二 全国疫情图 一 数据准备 二 数据处理 二 湖北省疫情图 一 数据准备 二 数据处理 一 基础地图应用 导入map地图对象 from pyecharts.charts import Map map Map() 写入数据 data [("北京市",100),("上海市"…

详细解读vcruntime140_1.dll修复的手段,如何快速解决vcruntime140_1.dll丢失问题

当出现“无法找到vcruntime140_1.dll”或程序“未能正常启动”时&#xff0c;这通常指示系统中缺失了一个关键文件&#xff1a;vcruntime140_1.dll。作为Visual C Redistributable组件的一部分&#xff0c;这个小文件在很多用Visual Studio编译的C程序运行时发挥着重要作用。解…

OJ_叠框问题

问题描述 c语言实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> using namespace std;int main() {int n; //存放外框尺寸int a,b; //存放两个字符char matrix[100][100] { 0 };//全部初始化为休止符/0while (scanf("%d %c %c&…