[Tonight's post is by Ed Smith, participant in the Humboldt Microcontrollers Group]
I'm writing this blog post largely because it took me quite a while to figure out how to use the Tiva-C's EEPROM in an effective way. My hope is that this page will make life easier for future people who use the Tiva-C.
First up, these are the Microcontroller boards we're going to be talking about today.
The Stellaris LM4F120 / Tiva-C TM4C123 Launchpad and the very snazzy TM4C129 Connected IoT Launchpad.
There are plenty of other Launchpads worth talking about, but all of them fall into one or more of two categories: Launchpads I do not have, and: Launchpads containing no EEPROM.
Not having EEPROM makes this article about using the built in EEPROM a bit irrelevant, and if I haven't used it I don't like writing about it.
Many programs and projects don't need to use EEPROM. All the variables are either burnt into the flash and never change, or are kept in RAM and updated as needed for that boot. When power is cycled the program starts fresh and off it goes. You don't need your calculator to remember what you did last week for instance.
There are other times when having some storage is extremely useful, calibrating sensors is a wonderful example. The Humboldt Laser Harp for instance uses EEPROM to store the calibration data for the laser sensors, as well as to store the MIDI "Velocity" of the notes. Without EEPROM you would have to either redo the mechanical/physical calibration every time you turned the harp on in slightly different circumstances (which takes 10-15 minutes), or recompile and reupload the firmware every time.
Almost any sort of sensor that requires calibration once in a while is a good use for EEPROM. Things like odometers or hour meters as well.
That brings us to the question of how.
How do I get access to the EEPROM of my microcontroller?
I'm glad you asked!
If you're using an Arduino, or a TI Launchpad and the Energia IDE, the process is very simple.
First you include the EEPROM library (At the top of your program, add "#include <EEPROM.h>" without the quotes), then in your program you call EEPROM.read(address) and EEPROM.write(address, value) to read and store values respectively. For example:
This would read the value at address 10 into the someVariable variable, update it, and then stuff it back into EEPROM address 10.
The process is very simple, if your value fits into a single byte. That is to say, 0-255. If your value is 256 it will be stored as 0. If it's 260 it will be stored as 4, and so on.
You have to do some bitshifting to split larger variables up into bytes and store the bytes individually, then bitshift it back together when you want to use it. It's very doable, but something of a pain.
There are add-on Arduino libraries that can be used to automate the bitshifting, though I have not used them.
What I have used is a slightly lower level method of EEPROM access on the TI Stellaris and Tiva-C chips.
This method and example still uses the Energia IDE, though I believe the code is more or less the same for TivaWare and the TI Code Composer Studio.
Instead of EEPROM.whatever, you use "ROM_EEPROMRead(variable, start address, length)" and "ROM_EEPROMProgram(variable, start address, length)".
The trick is, the variables you use are long integers (32 bits, 4 bytes) in an array, rather than single bytes.
The same operation as above, but with the ability to count from zero to a bit over four billion. Quite the improvement over 0-255.
You can also use sizeof(someVariable) rather than listing the number of bytes (so ROM_EEPROMRead(someVariable,10,sizeof(someVariable)); instead of 4) this is useful if you're using an array with more than one variable in it.
What I really like about this method is you can stick an entire array in just as easily, rather than the single member array we declared above you can declare an arbitrarily long array. Say 30 members. Then the exact same ROM_EEPROM calls store that entire array.
It does start to get tricky if you're using a number of addresses, the above example code uses address 10 as its starting point, it also uses address 11, 12 and 13, as the address is done by the number of bytes used. That 30 memory long array would use 120 bytes / address slots.
If you aren't paying attention and write something else to the middle of that range you're going to be unhappy with the results!
You get 32kB worth on the basic Tiva-C, and 256kB on the Connected Tiva-C, so you can afford to be lavish.
The really entertaining part to me is that if you use the Arduino style EEPROM calls on the TI chips, the EEPROM library is converting them into the unsigned long flavor of call to interface with the TI MCU itself. That means that if you're storing an unsigned long using the Arduino method on TI chips, you're bitshifting it manually into bytes, then the library is bitshifting it back into unsigned longs and storing it. Bit of a crackup if you ask me.
When you do use EEPROM it is a good idea to think about how often it will be written to, if you write to it once per second you only get 27 hours of operation before you hit the rated lifespan. Real world testing of Arduino (Atmega328 MCU) EEPROM has shown it to typically get to well over 1,000,000 writes before it starts throwing errors. Atmel and TI are not willing to guarantee that you'll get a million writes though.
Reads are free, read the EEPROM as often as you want, but try to keep the writes within reason. If you write once per minute you'll get ~69 days of operation per the spec, or 694 days if your EEPROM does the >1 million writes many seem to. Once an hour on average gives you a very long lifespan indeed, a bit over 4,000 days per spec or 40,000 if you're lucky. That's 11 to 110 years, which should be enough.
If you made it this far through this wall of text, congratulations! My next post will have more pictures.
I hope this was an interesting read and/or helped, look for a blog post about the Humboldt Laser Harp coming in the near future. This coming blog post will include some (most? all?) of the code for the laser harp, including the EEPROM bits.