• ARM 汇编写启动代码之关看门狗


    一、什么是看门狗

    看门狗(watch dog timer 看门狗定时器)。大家想象这样一个场景:家门口有一只狗,这个狗定时会饿(譬如说 2 小时一饿),够饿了会胡乱咬死人。人进进出出要想保证安全必须提前喂狗(必须在上次喂过后的2小时内喂狗才行)。如果超时没喂狗就会被咬死,如果提前喂狗没关系,但是本次喂狗时间就会从这里开始计算。

    现实中因为一些外部因素,电子设备经常会跑飞或者死机(譬如极端炎热、极端寒冷、工业复杂场合)。在这种情况下我们希望设备自动复位而不需要人工干预(无人值守)。看门狗用来完成这个工作。看门狗其实是我们 SoC 内部的一个定时器(类似于闹钟,类似于门口的狗),定好时间之后看门狗定时器会去计时,时间到之前(狗饿了之前)必须去重新置位看门狗定时器(喂狗),如果没有喂狗则系统会被强制复位。

    系统在正常工作时,系统软件会自己去喂狗,所以看门狗定时器不会复位。但是系统一旦故障跑飞啥的,看门狗就没人喂了,然后下一个周期就会自动复位,达到我们期望的效果。


    二、分析硬件物理特性、原理图、数据手册

    物理特性上看门狗其实是个定时器(跟现实中的闹钟类似),硬件上就是SoC内部的一个内部外设。

    原理图:看门狗不用分析原理图,因为看门狗属于内部外设,且没有外部相关的原件与他有关,所以不需要原理图分析,原理图上根本找不到和看门狗有关的地方。

    数据手册:在数据手册的Section7.3。

    找到关键性操作SFR(特殊功能寄存器)

    WTCON(0xE2700000),其中bit5是看门狗的开关:0代表关,1代表开
    
    • 1

    源代码

    root@ubuntu:/home/aston/workspace/git_xxxx# cat led.S 
    /*
     * 文件名: led.S
     * 作者: xxx
     * 描述: 演示汇编关闭看门狗  
     */
    
    #define GPJ0CON 0xE0200240
    #define GPJ0DAT 0xE0200244 
    
    #define WTCON   0xE2700000
    
    .global _start  //解决 make 编译警告: arm-linux-ld: warning: cannot find entry symbol _start; defaulting to 00000000
                    // 把 _start 链接属性改为外部,这样其他文件就可以看见 _start 了
    _start:
    	//第 1 步,关看门狗(向 WTCON 的 bit5 写入 0 即可)
    	ldr r0, =WTCON
    	ldr r1, =0x0
    	str r1, [r0]
    	
    	
    
    	//之后的为功能代码
    	//第一步: 把所有引脚设置成输出模式 
    	ldr r0, =0x11111111     //从后面的 = 可以看出用的是 ldr 伪指令,因为需要编译器来判断这个数
    	ldr r1, =GPJ0CON        //是合法立即数还是非法立即数,一般写代码都用 ldr 伪指令
    	str r0, [r1]            // 寄存器间接寻址。功能是把 r0 中的数写入到 r1 中的数为地址的内存中去
    
    	//要实现流水灯,只要在主循环中实现 1 圈的流水显示效果即可
    flash:
    	//第 1 步: 点亮 LED1, 其他熄灭
    	ldr r0, =~(1 << 3) 
    	ldr r1, =GPJ0DAT
    	str r0, [r1]            //把 0 写入到 GPJ0DAT 寄存器中,引脚即输出低电平,LED 点亮
    	//然后延时
    	bl  delay               // 使用 bl 进行函数调用
    
    
    	//第 2 步: 点亮 LED2, 其他熄灭
    	ldr r0, =~(1 << 4) 
    	ldr r1, =GPJ0DAT
    	str r0, [r1]            //把 0 写入到 GPJ0DAT 寄存器中,引脚即输出低电平,LED 点亮
    	//然后延时
    	bl  delay               // 使用 bl 进行函数调用
    
    
    	//第 3 步: 点亮 LED3, 其他熄灭
    	ldr r0, =~(1 << 5) 
    	ldr r1, =GPJ0DAT
    	str r0, [r1]            //把 0 写入到 GPJ0DAT 寄存器中,引脚即输出低电平,LED 点亮
    	//然后延时
    	bl  delay               // 使用 bl 进行函数调用
    
    	
    	b flash
    
    
    	b .                     // . 代表当前这一句指令的地址,这个就是高大上的死循环
    
    
    
    
    //延时函数
    delay:
    	ldr r2, =10000000
    	ldr r3, =0x0
    delay_loop:
    	sub r2, r2, #1          // r2 = r2 -1
    	cmp r2, r3              // cmp 会影响 z 标志位,如果 r2 等于 r3 则 z =1,下一句中 eq 就会成立
    	bne delay_loop
    	mov pc, lr              // 函数调用返回
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    三、总结 210 中看门狗特性(iROM 中已经关看门狗)

    为什么要关看门狗?

    • 一般 CPU 设计,在 CPU 启动后看门狗默认是工作的(为什么默认不关闭而要工作?我猜测是因为怕你的程序在启动代码前端就死机了或者跑飞了没人管),好处就是没有空挡和漏洞,坏处就是在启动代码段我们不方便去喂狗(或者说懒得去喂狗)时看门狗会复位,所以为了偷懒我们就在启动代码前端先去关闭看门狗,然后在后面系统启动起来之后再根据需要决定是否要打开看门狗(一旦打开就必须同时提供喂狗)。
    • 在 S5PV210 内部的 iROM 代码( BL0 )中,其实已经关过看门狗了。所以我们的启动代码实际上是不用去关也没事的,也就是说今天写的关闭看门狗的代码运行后没有任何现象(没有现象就是正常现象).
    • 很多 CPU 内部是没有 BL0 的,因此也没人给你关看门狗,都要在启动代码前段自己写代码关看门狗,所以今天学习的内容也是有价值的。

    源自朱有鹏老师.

  • 相关阅读:
    mysql安装完全排坑指南
    设计模式的思考
    【从零开始学习 SystemVerilog】1.1、SystemVerilog 概述
    【控制】动力学建模简介 --> 牛顿-欧拉 (Newton-Euler) 法和拉格朗日 (Lagrange) 法
    【Java 进阶篇】深入了解 Bootstrap 插件
    基于现代深度学习的目标检测方法综述
    【Unity3D】GUI控件
    Vxlan协议原理及基本配置——网络测试仪实操手册
    基于C++ 11的简单线程池实现
    【观点】区块链的未来:分布式商业;企业的未来:分布式商业生态战略
  • 原文地址:https://blog.csdn.net/weixin_42109053/article/details/128170182