Hello,
I would like to run a code (EEprom initialization) only at the first boot after uploading a new firmware. How can this be done?
Putting it in setup() is not achieving my goal, because it would run at every boot (not only the first boot of a new firmware).
How are you uploading the firmware?
You could use a variable in EEPROM that holds the current release number.
In setup you look for the expected value, if not found initialize and set the field to the new value.
A new firmware that needs a new init just gets a new release number.
The board has Atmega 238 (Arduino Nano with original bootloader).
I upload the firmware from the Arduino IDE, or upload the .hex file using Xloader.
@Whandall Do you mean that I should have a "firmware version" variable declared to a value, that I have to manually increment before uploading?
Are you uploading over USB (Sketch > Upload or Ctrl + U in the Arduino IDE) or via an ISP programmer (Sketch > Upload Using Programmer or Ctrl + Shift + U in the Arduino IDE).
ingdemurtas:
@Whandall Do you mean that I should have a "firmware version" variable declared to a value, that I have to manually increment before uploading?
You would have to add the definition of the value and the handling code in the editor.
I think changing that number manually for each release by hand is not too much trouble.
I upload over USB, using Sketch > Upload in the Arduino IDE.
OK. If you did Upload Using Programmer then it clears the EEPROM (with the default fuses in the standard Arduino boards definitions) so that would make things easy but no such luck.
If you didn't want to manually set the version number each time you could use the TIME macro instead. That's set to your system time at compilation. It's very unlikely that any two compilations would happen at exactly the same time. If you were concerned about that you could always use DATE also. Going the other direction, you could use SECOND if a 1/60 chance of collision was acceptable.
Reference:
http://www.microchip.com/webdoc/avrassembler/avrassembler.wb_preprocessor.Pre-defined_macros.html
Something like this?
What format should I use for the variable that receive the TIME? a String?
#define EPROM_Address 0
struct settings_type {
String BuildTime =0;
String BuildDate=0;
};
settings_type s{}; //create object of type settings_type
setup(){
if(s.BuildTime != __TIME__){
//run this at the first boot after compile
s.BuildTime= __TIME__;
EEPROM.put(EPROM_Address, s); //initialize eeprom
}
}
main(){
//
}
(deleted)
That would only work the first time a uC is ever programmed.
ingdemurtas:
What format should I use for the variable that receive the TIME? a String?
Noooo! Never use String. Use string instead (null terminated char array). Here's a demo:
#include <EEPROM.h>
void setup() {
Serial.begin(9600);
const unsigned int buildTimeEEPROMaddress = 100;
const char storedBuildTime[9];
EEPROM.get(buildTimeEEPROMaddress, storedBuildTime);
if (strcmp(__TIME__, storedBuildTime) == 0) {
Serial.println("this is not the first run after upload");
}
else {
Serial.println("this is the first run after upload");
EEPROM.put(buildTimeEEPROMaddress, __TIME__);
}
}
void loop() {}
Thanks for all the advices!
At the end I used a variable to store the "version" of the program, and I manually change it when I want to reload the eeprom with default values.
I did like that because several times I wanted to update the firmware but keeping the modified settings (modified trough the LCD menu system, stored in eeprom).