8
\$\begingroup\$

How can I make a code snippet run only once in the lifetime of a program? It can be turned off and turned on many times. The only option to run the code snippet again must be flashing the board again.

The code is a Calibration Section which I don't want to run again. If I use EEPROM or Flash we will be setting a Flag to true or False. So When we first read that memory location what would be the random value in that memory area?

What is the best method to implement this in embedded C?

\$\endgroup\$
10
  • 5
    \$\begingroup\$ Use a flag and save this flag to eeprom(or the flash). In every instant read the flag from eeprom. The very first time of the instant, the value of the flag will force the function to execute. After that you can change the value of the flag and save it to eeprom again. All the other times the flag value will not force the function excecution. \$\endgroup\$
    – hoo2
    Commented Apr 11, 2016 at 6:50
  • 2
    \$\begingroup\$ unclear what you are asking. \$\endgroup\$
    – old_timer
    Commented Apr 11, 2016 at 11:09
  • 2
    \$\begingroup\$ What is your motivation behind preventing the code from running a second time? Is it important that the code cannot be reverse-engineered, in which case setting a flag to bypass it may not be secure enough? Would running the code a second time damage the hardware? Is it a UX thing, like to display a tutorial message the first time the system is used, in which case it might be desirable for the "factory reset" function (if present) to trigger the code to run again? \$\endgroup\$ Commented Apr 11, 2016 at 15:10
  • 5
    \$\begingroup\$ Generally it's a good idea to allow for recalibration in case something gets messed up the first time round, or the system needs to be recalibrated for a different setup or to compensate for hardware ageing etc. I, for example, tend to mess calibration up the first time because I don't know what I'm supposed to be doing. \$\endgroup\$ Commented Apr 11, 2016 at 20:38
  • 3
    \$\begingroup\$ How about you set up the code so that there is a way to command it to run (I.e. send something in via a serial port). This way, there is no need to bother with nonvolatile memory and you can trigger the calibration during production in a controlled manner. \$\endgroup\$ Commented Apr 12, 2016 at 10:16

4 Answers 4

18
\$\begingroup\$

Your microcontroller might have some EEPROM, OTP memory, user fuse bits, where you can set a flag.

There is no "best method in embedded C", writing nonvolatile memory is different in every microcontroller.

edit:

FLASH

Flash memory contents are erased while programming the device. After programming, all bytes that weren't written contain 0xFF. Consult the datasheet to find an area that can be safely programmed from within the running firmware.

EEPROM

Although it's not guaranteed in the datasheets, all EEPROMs I've seen so far contained 0xFF:s when shipped from the factory (except ones preprogrammed with an unique MAC address, but that's explicitly documented). Some programming devices/software are able to erase or program EEPROM contents too. Some can be write protected, permanently or reversibly.

OTP

One Time Programmable memory always contains well defined initial values, documented in the datasheet.

It's always a good idea to include a good checksum like CRC32 with the data written, to protect against data corruption caused by defective parts, transmission errors, cosmic rays, whatever.

\$\endgroup\$
2
  • \$\begingroup\$ If i use EEPROM or Flash we will be setting a Flag to true or False.So When we first read that memory location what would be the random value in that memory area. \$\endgroup\$ Commented Apr 11, 2016 at 18:43
  • 2
    \$\begingroup\$ During manufacturing reset the EEPROM (either with a programmer, if possible, or by making a dumb little wiper program, flash that, power it up normally for a few seconds, then load in your production program). \$\endgroup\$
    – Nick T
    Commented Apr 11, 2016 at 23:35
13
\$\begingroup\$

You said:

The only option to run that code must flashing the board again.

Others have said to use EEPROM to store a flag to indicate when the run_once() function has been run. However, this has a draw back which is that if you reflash the microcontroller the ran_it_once flag in EEPROM has already been set and the run_once() function will not be executed. If your microcontroller has embedded EEPROM then it may be possible to clear the ran_it_once flag when you reflash the microcontroler, if the programmer supports this.

A better way is to have version numbers in both EEPROM and the code. When the code runs from power-up it should read the version number from EEPROM and compare it to the version number stored in the code. If they don't match then the run_once() function is called, and the final act of the run_once() code is to write the firmware version number into EEPROM. Each time that you modify the source code of the firmware you must increment the version number embedded in it.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ This would actually have the same problem as a boolean flag if all the user did was reflash the microcontroller and it needed to be re-run again (in that scenario). It would definitely resolve the issue if the firmware was updated and it needed to be re-run. \$\endgroup\$
    – Taegost
    Commented Apr 11, 2016 at 18:35
8
\$\begingroup\$

Choose a microcontroller that can write/erase its own program memory. After executing the code in question, have the last part of said code replace the first instruction with a jump that bypasses it. Optionally, you can also erase the rest (maybe replace with nop), so that there is absolutely zero chance of it ever executing again.

This message will self-destruct in 5..4...

\$\endgroup\$
4
  • 1
    \$\begingroup\$ As clever as this answer may be, I think it's needlessly complex. Perhaps it could use a note specifying that it should probably only be used if persistent memory outside of the code memory is unavailable? \$\endgroup\$
    – skrrgwasme
    Commented Apr 11, 2016 at 16:41
  • \$\begingroup\$ Even if other solutions are possible, I think this is easier to understand than others. \$\endgroup\$
    – Joshua
    Commented Apr 11, 2016 at 20:41
  • 1
    \$\begingroup\$ Even if other solutions were possible, I think this would be very difficult to understand at a source code level. \$\endgroup\$
    – user
    Commented Apr 12, 2016 at 7:52
  • \$\begingroup\$ Most PICs only have 35 instructions... what could go wrong? ;) \$\endgroup\$
    – rdtsc
    Commented Apr 12, 2016 at 13:51
5
\$\begingroup\$

As you are using this code for calibration, my suggestion would be to create a blast process which runs the calibration code as a first stage and not even have it on the finished production version of the board. This is similar to the answer by apalopohapa, except different in the sense that you would have two separate program loads: have a blast process that flashes the first program load which runs all the calibrations and spits out the data from that. Then take that data and incorporate it into the data of the second program load.

One benefit of this approach is that you absolutely minimize the amount of storage space you need - you don't need to store your once only code, only the data that it generates. By having a blast process which loads two separate programs, you also insulate yourself a bit from bugs in the initialization code which could linger around otherwise. You also have some additional flexibility if you want to re-run your calibration code: instead of having to write extra code to clear out whatever bit denotes that your code has been run (which could accidentally get cleared already) you simply re-run your blast process.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.