极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18855|回复: 7

arduino uno 如何判断重启类型

[复制链接]
发表于 2015-5-2 11:21:54 | 显示全部楼层 |阅读模式
#include<avr/wdt.h>

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
Serial.print("setup__");
Serial.println(MCUSR);
  if(MCUSR&0x08)
  {
    pinMode(13,OUTPUT);
    digitalWrite(13,HIGH);
//do something else
  }
  wdt_enable (WDTO_4S);
  
}

void loop() {
  // put your main code here, to run repeatedly:
  MCUSR=8;
  Serial.print("loop__");
  Serial.println(MCUSR);
  //  wdt_reset();
  delay(5000);

}

opti版本的bootloader,看门狗重启后无法读取mcusr寄存器的值,即使给它赋值也不行。熔丝位中的看门狗未开启。不考虑看门狗中断,只需要复位后能判断出是看门狗导致的复位,arduino如何实现呢?谢谢
回复

使用道具 举报

发表于 2015-5-2 19:16:45 | 显示全部楼层
如果你是要分辨 Power On Cold Start vs. WDT reset
可以这样: (偷放一串字符串在 RAM 检查是否 Cold start)


// Coldstart vs. Not cold start
#include <Arduino.h>
#include <string.h>
const char SECRET[ ] PROGMEM = "Hey 168ggYouSecLaLa";  // 特殊字符串
boolean cold = false;
void checkCold( ) {
  static char*p;
  p = (char*)malloc( sizeof(SECRET) );
  cold = true;  // assume NOT cold start
  if(strcmp(p,  (char*)SECRET) == 0 ) cold = false;  // 0 是字符串相等
  if(cold)memcpy(p, SECRET, sizeof(SECRET));
} // checkCold(
void setup( ) {
  Serial.begin(9600);
  checkCold( );
  if(cold) Serial.println("ower On start--Cold start");
  else Serial.println("WDT reset or other Reset ..");
  //...
}
void loop( ) {
  //..
}


如果是要分辨 WDT Reset vs. 一般 Reset, 那我也不知道  
回复 支持 反对

使用道具 举报

发表于 2015-5-2 21:02:53 | 显示全部楼层
tsaiwn 发表于 2015-5-2 19:16
如果你是要分辨 Power On Cold Start vs. WDT reset
可以这样: (偷放一串字符串在 RAM 检查是否 Cold star ...

应该各种复位有优先顺序的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-2 23:20:41 | 显示全部楼层
谢谢
刚才实验了下程序   

cold = true;  // assume NOT cold start 这条赋值语句与注释好像有些问题
我这里实验后  即使冷启(直接reset接GND或拔电),程序打印的还是WDT reset or other Reset ..


前几天下雨打闪电,arduino板(有实时时钟数据写sd卡功能)“死机”,SD卡文件未能记录“死机”后的所需数据。未下雨时,arduino板可长时间工作。于是要加入看门狗,转而又想明白一下是看门狗复位了,还是其它的。


回复 支持 反对

使用道具 举报

发表于 2015-5-3 01:54:50 | 显示全部楼层
xiaoliumonitor 发表于 2015-5-2 23:20
谢谢
刚才实验了下程序   


我这里说的冷启动是指把供电拔掉
因这时 RAM 才是乱的
至于你 RESET 或是 WDT Reset 则 RAM 都还在,
所以我才说我也不知道如何区别 RESET vs. WDT Reset
不过忽然想到
我之前说的方法无法用 Serial.print 看出来
因为要查看串口必须开启串口监视器Serial Monitor
可是根据手册说法, 一旦开启Serial Monitor 就会自动对板子 Reset
所以这时已经不是 Cold Start 而是 Warm Start 了
就是说当我们从串口监视器看到信息
其实 Arduino IDE 已经对 arduino 板做了 RESET
何况如果把 USB 线拔掉, COM? 可能变不见又得把串口监视器关闭并RESET...
所以只能说那方法确实可辨认是否刚冷启动, 但无法用串口验证
也许可以改为闪烁不同 LED 来验证 !
关于 WDT Reset,
也许你可以参看这篇:

   https://ariverpad.wordpress.com/ ... for-fun-and-profit/
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-3 10:24:00 | 显示全部楼层
点击arduino串口按钮时,13脚灯频闪一下,证明已重启(如您所说),并且是从boot区启动,bootloader程序肯定已执行。
发帖前我也尝试把贴中所有Serial语句注释掉,13脚的灯也并未亮起,此时的MCUSR的值应该还是为0.
看了下optibootloader程序(安装于1.0.5版本中)有
void appStart() {
  watchdogConfig(WATCHDOG_OFF);
.....
相关内容,好像是在bootloader启动时关了一下看门狗。

在arduino环境下,如何区分wdt或是bod重启(或是其他)?暂时还是没搞清。有时间了我再试下avr下(不带bootloader)的重启。arduino蛮厉害,MCUSR已赋值(328PDF里明确注明可以赋值),就是打印不出来。
谢谢


回复 支持 反对

使用道具 举报

发表于 2015-5-4 12:56:22 | 显示全部楼层
xiaoliumonitor 发表于 2015-5-3 10:24
点击arduino串口按钮时,13脚灯频闪一下,证明已重启(如您所说),并且是从boot区启动,bootloader程序肯定 ...

根据手册
要查看  MCUSR 的 EXTRF 这 bit 是否被 set 就可知道是否看门狗引起的:
    if( (MCUSR  &  (1 << EXTRF) ) != 0) {
         // 外部 RESET
    }else{
        // 看门狗引起的
    } // if..else..

但是, MCUSR 貌似会被 Bootloader 设定为 0
你可以看看你 IDE 内的 bootloader:
   hardware\arduino\bootloaders\atmega\ATmegaBOOT_168.c

里面有一段显然会把 MCUSR 设为 0, 所以你打印出来应该都是 0
如下:

#ifdef WATCHDOG_MODS
        ch = MCUSR;
        MCUSR = 0;

        WDTCSR |= _BV(WDCE) | _BV(WDE);
        WDTCSR = 0;

        // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot.
        if (! (ch &  _BV(EXTRF))) // if its a not an external reset...
                app_start();  // skip bootloader
#else
        asm volatile("nop\n\t");
#endif

所以, 如果你要自己检查 MCUSR
必须修改 BootLoader
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-6 20:17:07 | 显示全部楼层
非常感谢              
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-9 05:20 , Processed in 0.035259 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表