optiboot 6.2 + watchdog

Ho provato l'opitboot 6.2 su un paio di arduini originali, il watchdog funziona, e non continua a riavviare l'Arduino come nelle versioni vecchie.
Ho provato lo schetch d'esempio e l'ho anche modificato per mettere il reset dopo otto secondi:

/*
 * test_reset
 * May 2015 by Bill Westfield (WestfW)
 * Released to the public domain.
 *
 * This sketch demonstrates retrival of the Reset Cause register (MCUSR) of the AVR.
 * Normally, MCUSR itself is destroyed by the use of a bootloader, but Optiboot v4.6
 * and later save the contents in register r2, where it can be accessed by an
 * application.
 */
#include <avr/wdt.h>

/*
 * First, we need a variable to hold the reset cause that can be written before
 * early sketch initialization (that might change r2), and won't be reset by the
 * various initialization code.
 * avr-gcc provides for this via the ".noinit" section.
 */
uint8_t resetFlags __attribute__ ((section(".noinit")));

/*
 * Next, we need to put some code to save reset cause from the bootload (in r2)
 * to the variable.  Again, avr-gcc provides special code sections for this.
 */
void resetFlagsInit(void) __attribute__ ((naked))
                          __attribute__ ((section (".init0")));
void resetFlagsInit(void)
{
  /*
   * save the reset flags passed from the bootloader
   * This is a "simple" matter of storing (STS) r2 in the special variable
   * that we have created.  We use assembler to access the right variable.
   */
  __asm__ __volatile__ ("sts %0, r2\n" : "=m" (resetFlags) :);
}

void setup() {
  MCUSR = 0;
  Serial.begin(9600);  // Initialize serial port
  wdt_enable(WDTO_8S);
}

void loop() {
  Serial.println("Reset flag test");
  while (Serial.read() < 0)
    ;  // wait for some type-in

  Serial.print("Have reset flag value 0x");
  Serial.print(resetFlags, HEX);
  /*
   * check for the usual bits.  Note that the symnbols defined in wdt.h are
   * bit numbers, so they have to be shifted before comparison.
   */
  switch (resetFlags) {
    case 1<<WDRF:
      Serial.println(" (Watchdog)\n");
      break;
    case 1<<BORF:
      Serial.println(" (Brownout)\n");
      break;
    case 1<<EXTRF:
      Serial.println(" (External Reset)\n");
      break;
    case  1<<PORF:
    case ((1<<PORF) | (1<<BORF)):
      // A poweron can frequently result in both PORF and BORF being set, as the
      //  power switch bounces or the voltage rises slowly.
      Serial.println(" (PowerOn)\n");
      break;
    default:
      // Multiple bits can be set under various circumstances.  For example, the
      //  "hold down reset while powering up" trick used to recover from certain
      //  problems can leave both PORF and EXTRF set.
      Serial.println(" (Unknown)\n");
      break;
  }
  /*
   * Now we'll let the Watchdog reset the chip, and see if that cause is reported
   * correctly.  Older versions of optiboot could not easily distinguish between
   * WDRF and EXTRF resets, since the WDT was used inside the bootloader.
   */
  //wdt_enable(WDTO_8S);
}

la cosa strana è che come motivo del reset ho sempre watchdog

Reset flag test
Have reset flag value 0x8 (Watchdog)

anche quando lo resetto con il tasto reset o lo riaccendo.
Ho provato anche a cancellare il registro
MCUSR = 0;
ma non cambia nulla...
Era una prova per capire se si riesce a gestire il motivo del reset.
Qualcuno ha qualche idea?

Alberto

Allora vorresti dopo il reset capire la causa del reset (watchdog, accensione, Sottotensione, impulso sul prin Reset ecc)?
Ciao Uwe

Si,
con le ultime versioni dell'optiboot lo stato del registro MCUSR viene salvato dal bootloader nella variabile resetFlags che rimane in memoria anche dopo l'uscita dal bootloader, in quella variabile ci dovrebbe essere il vero motivo del reset, e non il wdt del bootloader...

Come da "Application note" di Atmel (quindi indipendentemente dal bootloader), prova così ...

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
...
...
void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));
void get_mcusr(void)
{
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}
...
...

... ovviamente NON devi chiamare la get_mcusr() dato che è messa nella section .init3 :wink:

Ti dovresti trovare, ad inizio programma, il valore del MCUSR nella variabile mcusr_mirror ...
... dico "ti dovresti" perché, purtroppo, c'è di mezzo l'IDE e le sue "manipolazioni" sul codice (... inclusa la definizione del prototipo della get_mcusr() in conflitto con quella corretta) ::slight_smile:

Guglielmo

Purtroppo tutto sto codice girerà inesorabilmente dopo il bootloader, e il bootloader usa il watchdog per uscire da se stesso e avviare il vero sketch, per cui leggeremo sempre 8 (wdt reset).
Il bootloader prima di avviare il watchdog dovrebbe copiare il vero stato del registro MCUSR nella variabile resetFlags che può essere letta dall'applicazione.
Almeno così si capisce dall'esempio.
Però non funziona, anche quella da sempre 8, resettando in qualsiasi maniera.
Magari scrivo sul github dell'optiboot...

Ma .... ti serve veramente un bootloader ? :smiling_imp:

Non puoi caricare il codice via connettore ICSP con un normale programmatore e ... toglierti dalle scatole il bootloader e la memoria che usa ? :wink:

Guglielmo

Si,
non mi serve il bootloader, infatti ho sul tavlolo l'usbasp che ho usato per aggiornare il booloader.
E' che volevo vedere se avevano risolto il problema del bootloader con il watchdog.
E l'hanno risolto, adesso se si usa il watchdog non entra in loop reboot.
Hanno anche messo la funzione per passare lo stato del MCUSR tramite il registro r2 che pare andare e dice che il reset è sempre wdt.
Molto bene!