If you build a monolitic firmware (like on the Core) then not, but when building modules then you should just build and flash the seperate binaries manually using CLI or dfu-util and not the make āparameterā program-dfu.
Or you download the prebuilt system parts, flash them and then do as you normally do, but with the correct tag selected.
This issue turned out to be very troublesome for me and some customers already using some devices, so I have put some time into reproducing and dumping the contents like you asked.
I can reproduce when using a 2x AA battery power pack. It has an on-off switch, but in the off position it leaks. In the on position it delivers 5.05V and enough current, in the off position, it delivers 2.6V and very little current. The problem almost instantly occurs when powering it in the on position, wait for the application to start running and connect to wifi. After that I switch to the off position. The led slowly fades, and blinks red a few times and then dies. If that doesnāt work the first time, it will happen by playing around with the switch, connecting and disconnectingā¦ it will break eventually.
After that it still boots and runs ānormallyā, but the eeprom is empty (I can tell by the behaviour of the device).
Also, when this happens, the device will not be recognised by the computer anymore, it does not show in OSX āSystem Informationā. Neither in application mode or dfu mode. Leaving it sit without power for a minute or so fixes the USB in DFU mode, but it will not always be recognised in application mode. Only after re-flashing everything is back to normal.
It seems like it was very easy to reproduce with 0.4.6, and slightly harder with 0.4.7, but that could be coincidence.
@mdma: I have made a few memory dumps, how do I get them to you?
Addition 1: When trying to view what was the remainder of the EEPROM memory, it looks the EEPROM does not get wiped, but rather corrupted. Some values clearly had parts of the original value. e.g an ip address that that should be ā192.168.0.254ā turned into|ā0.68.0.254ā.
Addition 2: searching the community for brown-out seems to get some related results. Especially the ones were keys got lost or corruptedā¦ (I donāt use the cloud and/or keys, so cannot tell wether it is related in my case).
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.
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.
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?
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.
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() {
}