'EEPROM' persistence issue

@nicodegunst nice catch! Section 3.3 is of specific interest IMO. I’ll flag the folks at Particle. :grinning:

1 Like

Thanks! And that section in particular drew my attention to. I can not find the mentioned routine “EE_Init()” anywhere in the firmware, so maybe this can be of any use somewhere somehow.

I hope it will get a higher priority soon. I receiving more and more reports from users now, so it is getting very troublesome.

This article also explains a little: https://www.digikey.com/Web%20Export/Supplier%20Content/lattice-semiconductor-220/pdf/lattice-wp-flash-corruption.pdf?redirected=1

This phenomenon potentially affects all flash memory, but I assume firmware space is set to be protected?

1 Like

@nicodegunst, that is a really good article and quite sobering. The STM32 has brownout voltage detection and I’m not sure it is being used. :smile:

I have tried to turn it on/change its settings, I have added:

FLASH_OB_BORConfig(OB_BOR_LEVEL3);

to setup().

But could not really notice any difference between one or the other. I could still reproduce the problem, regardless of this setting.

I also tried enabling/disabling write protect

FLASH_OB_WRPConfig(OB_WRP_Sector_All, ENABLE);

But also this does not seem to make any difference…

I am not entirely sure my attempts are valid, but it did not produce any compilation errors, so I assume there is nothing wrong with it…

That app note talks about recovering from power loss/brown-out during the update window.

Whether or not the particle code is susceptable to these errors, I have no idea, but this can be fixed so that at worst you lose the last update and have to roll back to the previous version.

I believe the particle problem is deeper than this, and can result in loss of emulated eeprom, even without any write accesses active when the power fails.

2 Likes

I can confirm it happens when no (user code) write actions are being performed. I do not write to “EEPROM” on boot, and it always happens when (un)plugging a device from a (charged) battery power source.
Are there any write actions in the photon firmware at boot time?

2 Likes

As I suspected, thank you for the confirmation.

2 Likes

A detailed description of how to reproduce this, including test firmware, would be a great first step in our journey towards a fix.

Seems like we have plenty of reproduction listings in this thread. I can ship you a USB wallwart that causes this issue it if you want?

I was able to reproduce pretty easy using a USB cable with a broken micro-usb connector. It has a bad connector, so I just have to tap it to cut power.

It hardly ever happens when cutting power when the photon has reached user code. But when cutting power while the LED is white, the eeprom would be cleared after maybe 2-3 attempts.

I think if you make a breadboard and wire it so you can use a momentary switch to cut power. A write some lines of code that read EEPROM, you will have this reproduced in no time. Power it up, cut power few ms after that for a few ms, and then let it boot.

I guess a cheap wall wart could have a bad connector, or have bad circuitry that doesn’t power up nicely. Or in my case, 2xAA battery with step up converter could also give short bursts of power when the batteries are almost flat.

1 Like

Guys,
Just thought I would throw this in - it might just help someone…

I had this issue way back and decided that the EEPROM storage for long-term use was too ‘iffy’ ;-)).

So - I designed my PCB to include a low-cost I2C FRAM (FerroElectric RAM) chip - works like a charm ;-)).

These chips are WAY longer-life than FLASH or anything else - being measured in the trillions of write cycles :open_mouth: and come in many sizes…

Hope this is helpful to someone else ;-)).

BR
Graham

1 Like

The brown-out reset (BOR) functionality is off by default on the STM32. You can see that the first time you run the code below.

Those that have the EEPROM persistence issue can try this code to set the brown-out level to a higher value to see if it makes the issue go away. The BOR feature will keep the microcontroller in reset when the voltage is too low.

@nicodegunst your code above didn’t actually change the BOR level because it was missing the unlock and launch steps. Can you try this?

#include "application.h"

void printBrownOutResetLevel() {
  Serial.println("Reading BOR");

  uint8_t bor = FLASH_OB_GetBOR();

  switch(bor) {
    case OB_BOR_OFF:
      Serial.println("OB_BOR_OFF: Supply voltage ranges from 1.62 to 2.10 V");
      break;
    case OB_BOR_LEVEL1:
      Serial.println("OB_BOR_LEVEL1: Supply voltage ranges from 2.10 to 2.40 V");
      break;
    case OB_BOR_LEVEL2:
      Serial.println("OB_BOR_LEVEL2: Supply voltage ranges from 2.40 to 2.70 V");
      break;
    case OB_BOR_LEVEL3:
      Serial.println("OB_BOR_LEVEL3: Supply voltage ranges from 2.70 to 3.60 V");
      break;
  }
  Serial.println("");
}

void setBrowoutResetLevel() {
  const uint8_t desiredBOR = OB_BOR_LEVEL3;
  if(FLASH_OB_GetBOR() != desiredBOR) {
    Serial.println("Writing BOR");

    /* Steps from http://www.st.com/web/en/resource/technical/document/programming_manual/CD00233952.pdf */
    /* See also https://github.com/spark/firmware/blob/aefb3342ed50314e502fc792f673af7a74f536f9/platform/MCU/STM32F2xx/STM32_StdPeriph_Driver/src/stm32f2xx_flash.c#L615 */

    /* To run any operation on this sector, the option lock bit (OPTLOCK) in the Flash option control register (FLASH_OPTCR) must be cleared. */
    FLASH_OB_Unlock();

    /* Modifying user option bytes */
    /* 1. Check that no Flash memory operation is ongoing by checking the BSY bit in the FLASH_SR register */
    FLASH_WaitForLastOperation();
    /* 2. Write the desired option value in the FLASH_OPTCR register */
    FLASH_OB_BORConfig(desiredBOR);

    /* 3. Set the option start bit (OPTSTRT) in the FLASH_OPTCR register */
    FLASH_OB_Launch();

    /* disable the FLASH option control register access (recommended to protect the Option Bytes against possible unwanted operations) */
    FLASH_OB_Lock();

    Serial.println("Done writing BOR");
  } else {
    Serial.println("BOR value already set");
  }
  Serial.println("");
}

void setup() {
  Serial.begin(9600);
  delay(2000);
  printBrownOutResetLevel();
  setBrowoutResetLevel();
  printBrownOutResetLevel();
}

void loop() {

}

I got the steps from the STM32 flash programming reference manual.

8 Likes

This seems very interesting. I will work on it tomorrow:

Quick question:
I understand this is off by default? Is that correct for the photon?

If not… What are the default levels?

So I’ve implemented this today, some cloudy days ahead should put the implementation to the test… Let’s see how it works. I will report back with results…

3 Likes

@jvanier, I have tested with the “setBrowoutResetLevel” function you suggested. This did not make a difference for me. Flash was still getting corrupted by switching usb on and off during the white led.

I also tried to pull request you posted: https://github.com/spark/firmware/pull/762

That did the trick!! It is now impossible to corrupt the flash by fiddling with the power supply. Thank you so much for this contribution! I hope (read: assume) this will be added to the firmware asap… @mdma, @zachary? don’t know who to ping about it, but I am sure you guys do… :smile:

5 Likes

Awesome! Thanks for letting us know it works for you @nicodegunst.

1 Like

Thanks for your work on this @jvanier

wow that is really cool! @nicodegunst. I really hope that @mdma or @zachary will integrate that change.
Thanks a lot.

I just realized that we have a serious problem all our units in the field loosing the EEPROM information on power down. We have big caps installs, powering the units (after unplugging the power supply) for almost 5sec and I’d guess that the Vcc is really slow going down. We tried to push down the reset, before unplugging the power supply and sure enough, that worked flawless.

Will this fix be part of the next firmware release (0.48?), or is there anything that I could add right now to my code to fix the issue? How soon will the 0.48 be available? Questions, questions questions :smile:

JKW

9 posts were split to a new topic: Unexpected lockup of Photon with SparkFun PowerShield

A post was split to a new topic: Photon not turning on, can’t DFU