earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
GNU Lesser General Public License v2.1
2.03k stars 423 forks source link

OTA and watchdog #2285

Closed djaus2 closed 3 months ago

djaus2 commented 3 months ago

Been testing an OTA upload with watchdog enabled..

Given the max watchdog update period of 8.3 seconds am I correct in assuming that limits the size of the upload? I've got an upload that takes 14.3 and seems to fail around 8 seconds.

Uploading.................................................................................................................................................................................................................................................................
13:44:24 [ERROR]: Error Uploading
Failed uploading: uploading error: exit status 1

With watchdog disabled it uploads OK.

Sketch uses 647512 bytes (61%) of program storage space. Maximum is 1044480 bytes.
Global variables use 98688 bytes (37%) of dynamic memory, leaving 163456 bytes for local variables. Maximum is 262144 bytes.
Uploading..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Complete

Any workaround for this?

Nb Flash is partioned as 1M: 1M

Relevant setup code is:

  #ifdef USE_WATCHDOG
  watchdog_enable(WATCHDOG_SECS * 1000, false);
  #endif

And loop code is

  ArduinoOTA.handle()
  #ifdef USE_WATCHDOG
  watchdog_update();
  #endif
  if(OTAing)
      return;

And in ArduinoOTA.onStart OTAing is set. (It is initialised as false);

  ArduinoOTA.onStart([]() {  // switch off all hardware
    OTAing=true;

I'm guessing though during an upload, the loop() never runs, so OTAing is not necessary???

earlephilhower commented 3 months ago

What exactly is WATCHDOG_SECS defined as? If it's > 4 seconds then the HW can't actually do it (check the Pico forums @ RPI, there's an off-by-2 somewhere in the design) and you'll be running at some smaller value than you think. Try setting it to 1 sec if it's >4.

djaus2 commented 3 months ago

define WATCHDOG_SECS 8 in another Header file.

In your docsl you state:

void rp2040.wdt_begin(uint32_t delay_ms)
Enables the hardware watchdog timer with a delay value of delay_ms milliseconds. Note that on the RP2040, once this function has called, the hardware watchdog can _not_ be disabled.

The maximum delay_ms allowed in this call is 8300, corresponding to 8.3 seconds. 
Any higher values will be truncated by the hardware.

So is it 8s or 4s, the max period? I did see a suggestion in Pico discussion its 14s???

I did try a simple app as follows and the count always just gets to 8, cpu resets and count restarts.

#include "rpiwatchdog.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while(!Serial);
  watchdog_enable(15 * 1000, false);
}

void loop() {
  // put your main code here, to run repeatedly:
  watchdog_update();
  for (int i=0;i<20;i++)
  {
    Serial.println(i);
    delay (1000);
  }
}

So my question remains, can the WatchDog timer be disabled whilst an OTA upload is occuring?`

rpiwatchdog.h and rpiwatchdog.c can be veiwed here on GitHub at SoftataOTA

djaus2 commented 3 months ago

Ps I got my complete Softata code running OK with OTA updates, without WatchDog enabled. See the SoftataOTA link above.

earlephilhower commented 3 months ago

You haven't provided your actual source code so there's no saying exactly what is going on, unfortunately.

You should be calling a WDT kick in onProgress. Add that to your code and each packet in should kick the WDT.

earlephilhower commented 3 months ago

This is what I was thinking of. It was originally intended to run up to 16 seconds (not 8, mybad), but there's a double decrement so only up to 8 secs is supported. From the datasheet: image

djaus2 commented 3 months ago

So my question still is, can WatchDog be disabled during an OTA deployment?

earlephilhower commented 3 months ago

Err, I've never seen a real watchdog that can be stopped after it's started. AFAIK, neither can the Pico's WDT. You can double-check with the RPi forums to get the 100% answer, but looking at the datasheet it seems like it's not doable.

You may want to look at the other update methods. The HTTPUpdate/etc. examples are more modern and can include things like authentication and encryption over the air (TLS). They (and ArduinoOTA) simply write a file and reboot to let the real OTA block, which runs before any user app, update flash atomically.

djaus2 commented 3 months ago

Ok thanks, as I thought. Considering inserting a periodic interrupt, say once per second, enabled at OTA start that touches the Watchdog such that if, say, it gets to a large count, say 20(sec) the device will reboot by not "touching" the Watchdog.

earlephilhower commented 3 months ago

Why not add an onProgress callback instead? Every packet should get a callback and no need to mess with IRQs...

djaus2 commented 3 months ago

OK That sounds good, and clean! Will try that.

djaus2 commented 3 months ago

OK Have added the following code in setup() and it appears to work. Need to further test. Thx

  ArduinoOTA.onProgress([](size_t progresso, size_t total){
    //THandlerFunction_Progress fn
    #ifdef ENABLE_WATCHDOG
      watchdog_update();
    #endif
  });
djaus2 commented 3 months ago

I have blogged about this here.

Isssue IS now cl;osed/resolved! Thx.