[ Electron ] : How can i use the hardware watchdog of the STM32F205?


#1

Hi,

I’ve spent some time looking at the documentation and the Particle community, but i couldn’t find any reference on how to use the hardware watchdog of the Electron module.
I’ve found something on Photon and Core ( SparkIntervalTimer library) but nothing on electron.

I’m aware of the apllication watchdog but Im interested in a hardware level security, as example, something that can reset the uC if the code locks in a dead state because of bits flipped in RAM or because of erroneous jump of the program counter or in general because of a software or hardware fault.

Any clue on that?

thank you.


#2

SparkIntervalTimer also works on the Electron (it uses the same µC as the Photon).


#3

oh, is it?
I’ve not try to implement the library in my code, because i had a quick look to the Source and the Electron seems not supported.

Have you tested it before on Electron?

109 #else
110 #error "*** PARTICLE device not supported by this library. PLATFORM should be Core or Photon ***"
111 #endif


#4

@LucaM, I just test compiled the SparkIntervalTimer on the web IDE with 0.6.0 and 0.7.0 firmware with an Electron as the target without any problems.

Using a hardware timer as a watchdog will ensure that it will fire if something stalls (vs the Application Watchdog) but doing a software reset is NOT the same as a hardware reset. This is where an external (hardware) watchdog may be a better choice.


#5

The important bit in that code is not the #else part but what it actually should contrast :wink:

#if defined(STM32F10X_MD) || !defined(PLATFORM_ID)		//Core
...
#elif defined(STM32F2XX) && defined(PLATFORM_ID)	//Photon (ScruffR: and we also now know Electron too)
...
#else
  #error "*** PARTICLE device not supported by this library. PLATFORM should be Core or Photon ***"
#endif

And since the Electron also runs a STM32F2XX it’s fine - the Electron was just not there at time of first contribution of the library.
@peekay123, maybe the error message could be altered and the || !defined(PLATFORM_ID) for Core may probably want changing as the Core does now have it declared too hence it may be confusing :wink:
However trying it despite the text would have revealed that it isn’t thrown anyway.


#6

Cool! I’m going to try it.

@peekay123
Thankyou, however, I’m looking for a proper use of the watchdog timer, a piece of hardware that perform an hardware reset on the uC if the code stocks,(not a software routine that trigger a software reset).

Is SparkIntervalTimer the right library to use the built-in watchdog timer of the STM32F205?

(why should i use an external hardware when the STM32F205 has is built-in hardware watchdog?)


#7

@LucaM, SparkIntervalTimer does not support the internal watchdog timer. The STM32F205 WDT or IDT is not currently supported and there are several firmware issues addressing this:


#8

Is it possible to use the internal watchdog timer with the Electron?


#9

Support for using the hardware watchdog is supposed to be coming in the 8.0 firmware version from what I have heard :slight_smile:


#10

Hello everybody,

I’m also trying to use the IWDG. Looking into the firmware I found this file “stm32f2xx_iwdg.h”

Using it in a simple example:

  • after 30 sec config and enable WD
  • with while(1){IWDG_ReloadCounter();} no reset
  • without while(1){IWDG_ReloadCounter();} reset after ~1040ms
  • using IWDG_Prescaler_256 or IWDG_Prescaler_4 does not change the reset period so I’m probably doing something wrong. I wanted to go for the maximum period between resets (~=32 sec) I also added the delays but do not know if it is needed?
#include "stm32f2xx_iwdg.h"

SYSTEM_THREAD(ENABLED);

void setup()
{
    Serial.begin(115200);
}

static unsigned long lastMillis = 0;
static unsigned long milPrev = 0;
static uint8_t t = 0;
static uint8_t once = 1;

void loop()
{
    if(!once)
    {
        unsigned long mil = millis() - lastMillis;
        if((mil-milPrev) > 1 ) // count 2ms untill WD reset
        {
            Serial.printlnf(" %lu",millis() - lastMillis);
            milPrev = mil;
        }
    }
    
    
    if(((millis() - lastMillis) > 1000) && once) 
    {
        t++;
        Serial.printlnf("t=%u",t);
        if(once && t==30)
        {
            once = 0;
            
            Serial.println("WD config");
            // 1. Enable write access to IWDG_PR and IWDG_RLR registers using
            //    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable) function*/
            IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
            
            // 2. Configure the IWDG prescaler using IWDG_SetPrescaler() function
            delay(500);
            IWDG_SetPrescaler(IWDG_Prescaler_256);
            delay(500);
            
            // 3. Configure the IWDG counter value using IWDG_SetReload() function.
            //    This value will be loaded in the IWDG counter each time the counter
            //    is reloaded, then the IWDG will start counting down from this value.
            delay(500);
            IWDG_SetReload(0xFFF);
            
            // 4. Start the IWDG using IWDG_Enable() function, when the IWDG is used
            //    in software mode (no need to enable the LSI, it will be enabled by hardware)
            delay(500);
            
            uint8_t pvu = IWDG_GetFlagStatus(IWDG_FLAG_PVU) == SET;
            Serial.printlnf("pvu %u", pvu);
            uint8_t rvu = IWDG_GetFlagStatus(IWDG_FLAG_RVU) == SET;
            Serial.printlnf("rvu %u", rvu);
            delay(500);
            Serial.println("Reload");
            IWDG_ReloadCounter();
            
            delay(500);
            Serial.println("WD enable");
            IWDG_Enable();
            
            // 5. Then the application program must reload the IWDG counter at regular
            //    intervals during normal operation to prevent an MCU reset, using
            //    IWDG_ReloadCounter() function.

            //while(1){IWDG_ReloadCounter();}
        }
        
        lastMillis = millis();
    }
    
}

So it seems that the IWDG is working?
Why is it officially not working? What am I missing?
I do not plan to use Sleep in my application. Should I be careful with other things (OTA?)


Woes remote managing a boron
#11

Thank you for listing this.

I am thinking that if it can be set to 32 seconds, and any blocking thing the system does can be over in less than 32 seconds, then it is usable. I am not sure the latter is always true when OTA software updating maybe with a 3-part OS upgrade for Electron.

Maybe possible to use System.disableUpdates(), and on a cloud signal restart without the watchdog, to allow an update within the next 15 minutes, then reverse when finished.

So I wonder what stops the watchdog (a reset is OK for this). And does anyone know how to get the pre-scaler setting to work? I could not find a working example online with the pre-scaler.


#12

It is working - but it’s working too good :wink:
Once started it can’t be stopped any other way than with a reset but keeps running even in stop or standby mode and hence would reset your device while it’s asleep, which is probably not desired.
Additionally, as you already asserted, OTA updates would be interrupted by the IWDG since the update process wouldn’t tickle the WDG.

However, there are ideas tossed around that may help out of these traps.
e.g. for deep sleep (which would normally wake with a reset anyway) first reset the device with a retained deep sleep period. When this value is non-zero a STARTUP() macro should not start the IWDG again but copy that period, clear the retained version and engage the actual deep sleep phase with desired period. This way the IWDG won’t interrupt deep sleep but on next sheduled wake the IWDG would again be enabled and the normal code can run.
Rinse. Repeat.

Stop sleep (for more than the IWDG period) would be more tricky as the reset is inevitable to stop the IWDG.


#13

Thanks, well a reset to stop is fine with me. Using retained sounds like a way to go.

OTA updates may be handled by announcing this to the device beforehand, to reset wo. restarting the dog for a period. A bit cumbersome to do manually when updating a large number of devices but should be well worth it.

Does anybody know how to get the pre-scaler to work?


#14

No it is not. I’ve been using STM32 for a long time without Particle firmware and I haven’t had any problems of this kind with the watchdog (enable, prescalers, reload,…).

It looks like the Hardware Watchdog timer is already used in the electron for another purpose hence the problem to modify prescaler. My guess is RTOS? Did not have the time or the motivation to dig further in the firmware code. Documentation is really lacking on this point. If someone could clarify this it would be great.

I ended up with an external Watchdog ~30 sec intervals, it’s working perfectly (I’m not using any kind of sleep) even with OTA (In the unlikely case that the WD resets while flashing OTA, just retry).
It was just a waste of time and money to get a feature that was already on the MCU…


#15

@tdasnoy, the bootloader/OTA seems to use the IDWG:

// Get the Bootloader Mode that will be used when IWDG reset occurs due to invalid firmware


#16

Too bad. Got my hopes up there for a while. The existing ~1004ms is too tight.

For me an internal watchdog should be refreshed by the App, so an external watchdog it is then. Thank you for advising on the 30 seconds without sleeping. I will experiment with that together with sleeping.