Go Down

Topic: Turn the EEPROM[x] write into an update? (Read 562 times) previous topic - next topic

a2e5

EEPROM's subscript/ref write (operator=) feature as currently implemented always writes the EEPROM without checking like "update" does. This can feel a bit inconsistent compared to the similarly simplified "put" method. Perhaps an explicit "write" function can be updated to the ref, and #define switch can be introduced to choose between the two behaviors?

(FYI, I am talking about https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/libraries/EEPROM/src/EEPROM.h.)

pert

Since it's a header-only library it's actually possible to use a #define in the sketch before the #include directive to configure the library. I would suggest this #define also control whether put() does a blind write or an update.

I think that generally Arduino is officially not in favor of using this sort of user interface to a library so you might have some difficulty with that. To be honest, I don't fully understand the workings of the EEPROM library. Would it be possible to configure this behavior via an argument passed to a function instead of using the preprocessor?

I see you've now submitted a pull request for this proposal:
https://github.com/arduino/Arduino/pull/7486
Thanks for your contribution!

a2e5

#2
Apr 19, 2018, 12:45 am Last Edit: Apr 19, 2018, 12:47 am by a2e5
Since it's a header-only library it's actually possible to use a #define in the sketch before the #include directive to configure the library. I would suggest this #define also control whether put() does a blind write or an update.
My PR is basically based on a "#define" switch. Modifying "put" can be interesting (and pretty easy -- just make it do a "="), although I don't see much point in allowing users to throw multiple unconditional writes easily *and* globally yet...

Would it be possible to configure this behavior via an argument passed to a function instead of using the preprocessor?
The "=" operator cannot accept additional arguments, so I am afraid this can't be done straightforwardly. (A non-strightforward way can be accepting an int16_t, where the first byte is for options and the second is for the actual data.) The "put" function can definitely do it with a caller-decided switch though.

pert

I don't see much point in allowing users to throw multiple unconditional writes easily *and* globally yet...
I sometimes like to use blind writes to EEPROM when I already know the value is changed because then you avoid the overhead of the unnecessary check. In the Arduino world it's definitely best to default to the safe update behavior. This is a difficulty for controlling both via the same #define since currently one does a blind write and the other an update. So this would mean changing the default behavior of the subscript functionality of the library but I think a case could definitely be made for that being a reasonable change. I actually haven't ever seen anyone use that feature and of the small number of people using it probably very few would be significantly inconvenienced by the changed behavior (and those few would probably be balanced out by the benefit to the others), so it shouldn't cause too much trouble.

The "=" operator cannot accept additional arguments, so I am afraid this can't be done straightforwardly.
I wasn't talking about adding an additional argument. I was talking about adding an additional function that is called to configure the behavior. For example:
Code: [Select]
#include <EEPROM.h>

void setup() {
  EEPROM.doUpdates(true);
  EEPROM[0] = 42;  // only writes to EEPROM if the value has changed
  EEPROM.doUpdates(false);
  EEPROM[0] = 42;  // always writes to EEPROM
}

void loop() {}

a2e5

#4
Apr 19, 2018, 02:34 am Last Edit: Apr 19, 2018, 03:10 am by a2e5
Code: [Select]
#include <EEPROM.h>

void setup() {
  EEPROM.doUpdates(true);
  EEPROM[0] = 42;  // only writes to EEPROM if the value has changed
  EEPROM.doUpdates(false);
  EEPROM[0] = 42;  // always writes to EEPROM
}

void loop() {}


Oh I see. Yes, this is possible by adding a class-static boolean value in EERef and checking on each "=" operation. (GCC appears pretty good at handling these things: for example, with the flag in "begin" clearly deterministic, it elliminated a call to "bar" in https://godbolt.org/g/Dh1wra.)

P.S. I just found out that avr-libc in fact has some "block" functions that can be used to implement get/put probably more efficiently: https://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html. To keep the compiled code size small, I am planning to take the byte/block one but keep all others. I guess I will make a separate pull request for using these replacements?

Go Up