Compile-Time vs. Run-Time Flag

stecoop is using an Arduino Uno.

I know there's a bootloader that not only lets flash be written to at runtime but provides functions to do it with, but it's for "The Mighty" 1284P. There might be a version for the 328P that I haven't seen yet.

When I was researching hex files to see if I could add lines, I thought I saw a reference to loading hex to EEPROM but don't need so didn't follow it up.

Almost all of the RTC 1307 and DS3231 modules have flash storage on them.
You could use that for your storage. There are libraries available for them.

IMO, it doesn't make sense to use a 1307 anymore. 6-8 years ago the 3231 was quite a bit more expensive than the 1307 but these days that isn't the case.

These days I don't even use an RTC anymore on many of my projects. I use ESP8266 parts and use the core supplied time library which can fetch the time from an NTP server over wifi and will do daylight savings adjustments once configured with a TZ string.

--- bill

bperrybap:
These days I don't even use an RTC anymore on many of my projects. I use ESP8266 parts and use the core supplied time library which can fetch the time from an NTP server over wifi and will do daylight savings adjustments once configured with a TZ string.

For one of my ESP8266 projects I just added an RTC in a redesign... for the simple reason that WiFi is not reliably available where it's being installed.

It will use NTP to grab the time when available - e.g. when it can connect to my phone's hotspot. Makes setting the time a lot easier, and makes sure time is available upon startup.

A duino with crystal instead of resonator will keep time as well as a cheap watch won't it?

GoForSmoke:
A duino with crystal instead of resonator will keep time as well as a cheap watch won't it?

It should do so indeed - until the power goes out. Then the time is completely forgotten.

stecoop:
Okay, I see what you're suggesting...it's the reverse logic of what I'm looking for. I think it could work; I'll give it a try as soon as I can and post here the results.

Thank you, everyone, for your suggestions.

As I previously said, I would post the results of my EEPROM tests; it works very well. Below is the setup() code I used for this:

void setup()
{
pinMode(LED_BUILTIN,OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
lcd.begin(16,2);
EEPROM.get(eeAddress,FirstLastRunFlag);
getTime(TIME);
TestFlag = tm.Second + (tm.Minute * 60) + (tm.Hour * 3600);
if (TestFlag != FirstLastRunFlag)
{
getDate(DATE);
RTC.write(tm);
EEPROM.put(eeAddress,TestFlag);
}
lcd.clear();
}

eeAddress, FirstLastRunFlag, and TestFlag are all defined as int's.
tm is a tmElements_t structure from the DS1307RTC library.

I decided to convert the time of day to seconds as the flag value because it's easier and quicker to compare one value then to compare several values; and I'm not likely to do an uploaad at exactly the same time on two different days.

Thanks to all for your help and suggestions.

It would still be nice if the Arduino compiler included an easily run-time resettable compile-time flag; I can imagine this would be useful in other applications.

stecoop:
I decided to convert the time of day to seconds as the flag value because it's easier and quicker to compare one value

That's indeed the common way to do it - no doubt your library can give you the "unixtime" (seconds since 1 Jan 1970) directly. The TimeLib function now() also gives this value. Some RTCs use 1/1/2000 as epoch, then you have to correct for the 30 years.

stecoop:
It would still be nice if the Arduino compiler included an easily run-time resettable compile-time flag; I can imagine this would be useful in other applications.

The write-to-flash bootloader is the Mini_MCU that can be found at Github.

I'd put up the link that was PM'd to me but ARDUINO.CC DOESN'T LET ME ACCESS PM'S UNLESS ONE IS SENT, A "NEW FEATURE" FROM SOME DINK WITH A STUPID IDEA. NO, I DON'T WANT TO SEE WHAT I PLAN TO BUY AT THE STORE, I'M TRYING TO LEAVE HELP BEFORE MY LINK TIMES OUT!

stecoop:
It would still be nice if the Arduino compiler included an easily run-time resettable compile-time flag; I can imagine this would be useful in other applications.

From what you are wanting to do, I really don't see how that would be useful.
You can already do that by initializing a variable.
i.e.

int flag = 1;

The compiler sets things up so that the variable will be 1 when the code starts up and the code is free to change it to anything it wants runtime.
The issue is that once it is altered it is not "remembered" across powerup or reset cycles.

i.e. every time the code starts the value of flag will be 1

From your application you are wanting the "override" to be nonvolatile.
That is not something that a compiler provides nor should it.

You have a few options,

  • you could use a time flag like you have done either stored in the AVR EEPROM or in the EEPROM on the RTC module.
  • you could read the time from the RTC and if it is older than the compiled time, set the RTC.
    The best way to do the comparison is to use epoch time, which is simply an integer so the comparison is trivial.
    Many of the time/RTC libraries provide the capability to create the epoch value for you.

--- bill

For a sketch to know if this is the 1st run or not, possibly for some kind of initialization?

Reasons to use EEPROM instead of flash are:

  1. flash writes to a 128 byte page while EEPROM writes to single bytes.
  2. flash has 10K guaranteed writes while EEPROM has 100K guaranteed writes.

If the first run is supposed to fill EEPROM then run a sketch to erase it before the product sketch. Detect the erased values.

GoForSmoke:
For a sketch to know if this is the 1st run or not, possibly for some kind of initialization?

Reasons to use EEPROM instead of flash are:

  1. flash writes to a 128 byte page while EEPROM writes to single bytes.
  2. flash has 10K guaranteed writes while EEPROM has 100K guaranteed writes.

If the first run is supposed to fill EEPROM then run a sketch to erase it before the product sketch. Detect the erased values.

For initialization, pre-start diagnostics, safe shutdown, etc. There are many situations where it is desirable to know what happened BEFORE the sketch started up, including whether or not this is the very first run.

Using the EEPROM does seem to be the best way to do this. I've worked with a few PLC's (Programmable Logic Controller) and they all had some non-volatile memory that would be erased when a program was uploaded to the device, but not erased when powered off. This allows a program to make certain tests that may be neccesary after an upload, but not really needed, or desirable, after a restart.

GoForSmoke:

  1. flash writes to a 128 byte page while EEPROM writes to single bytes.

I thought EEPROM uses 4-byte pages?

wvmarle:
I thought EEPROM uses 4-byte pages?

When accessed via in-system programming. For the running program access is bytewise.

You can load hex to EEPROM with ICSP?

stecoop:
For initialization, pre-start diagnostics, safe shutdown, etc. There are many situations where it is desirable to know what happened BEFORE the sketch started up, including whether or not this is the very first run.

Just chewing on this bite right now.

Using the EEPROM does seem to be the best way to do this. I've worked with a few PLC's (Programmable Logic Controller) and they all had some non-volatile memory that would be erased when a program was uploaded to the device, but not erased when powered off. This allows a program to make certain tests that may be neccesary after an upload, but not really needed, or desirable, after a restart.

AVRs have 2 kinds of non-volatile memory, and one gets 10x as many writes.

GoForSmoke:
You can load hex to EEPROM with ICSP?

Yes. There is even an eyecatcher (EEMEM?) to mark data meant to be uploaded to EEPROM.

https://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

#define EEMEM attribute((section(".eeprom")))
Attribute expression causing a variable to be allocated within the .eeprom section.

I have have no use for EEPROM yet. It's slow too.

So like PROGMEM for flash we have EEMEM for EEPROM with special read and write functions. But not examples except posts in the forum.

And there's this:

// eeprom storage
uint16_t reboot_counter_ee EEMEM = 0;
uint8_t config_ee[15] EEMEM = "testing ...";

The name reboot_counter tells me that value is only set to 0 on the sketch download.

There. All nice and clean and wrapped up with example code.

GoForSmoke:
So like PROGMEM for flash we have EEMEM for EEPROM with special read and write functions.

Almost every day I can learn something new here, like this EEMEM. Never heard about that before! Speed is not really an issue. It's slower than RAM of Flash, but for most uses definitely fast enough.

EEPROM: 5 clock cycles per byte.
Flash (PROGMEM): 3 clock cycles per byte.
RAM: 2 clock cycles per byte.

Writing to EEPROM is of course MUCH slower - taking about 10 ms to complete. But that's irrelevant when talking about read-only data.

Quite likely the use cases will be pretty limited. Not often that you just need that handful of bytes extra to squeeze your program onto a controller.

It's great for holding temp values through power offs.

I put my const data in flash since I learned PROGMEM and F() but I still forget the print from flash trick since I didn't use the heck out of it before short term wetware lost my copy, and where's my keys?.

I don't remember seeing EEMEM before. Like to all but forget by tomorrow, just know there is something to look for at AVR-LibC.

Oh.... wait... what does "If you want to write values to EEPROM with your programmer, be sure to generate an eeprom file." mean? Is this another option or is it necessary as well as the above code? Ayayay!

Notes

If you want to write values to EEPROM with your programmer, be sure to generate an eeprom file. This can be achieved with:
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex .exe .eep
If you generated your eep file, be sure to upload it. I did it with avrdude.
c:winavrbinavrdude -v -F -p ATmega8 -c avr910 -P com4 -U eeprom:w:.eep:i
Be sure to write the eep after you have written your program, as avrdude automatically does an erase cylce which clears the eeprom as well. Otherwise you will see unprogrammed eeprom storage. You can try to suppress the erase with option -D but that does not work for me (errors in verification). If you want to preserve your eeprom while programming, you have to protect it by setting the “preserve EEPROM” fuse. That should be used if development and testing is over.

Confirmed here:
https://www.avrfreaks.net/forum/tut-c-using-eeprom-memory-avr-gcc?name=PNphpBB2&file=viewtopic&t=38417

The hex file goes to flash and the eep file goes to EEPROM, I have no idea what Arduino IDE does or doesn't do about eep files but I don't see why it couldn't do the extra step. He is loading ICSP, not through bootloader.