CS 341 – Lab 3
Computer Architecture and Organization
Non-volatile Storage for Configuration Data (EEPROM)
Equipment: Arduino UNO microcomputer, PC with Arduino IDE installed, and a USB cable.
Configuration data may be information about the product such as manufacturer’s ID, part number, and even the customer service phone number or web/email address. The device may be programmed to display this information upon user request. Configuration data may also be calibration information used to properly calculate the values read from or written to analog ports or other data needed for the product to operate that may differ from device to device. Configuration data must be preserved through power outages and/or processor resets, but it usually not part of the compiled program code because it may need to have different values for different individual devices. It may be stored in Electrically Erasable PROM (EEPROM).
The contents of an EEPROM are preserved across power outages so your code can save data while your device is running. After it is powered off and back on again and/or reset, your code can retrieve it during your initialization sequence. However, you can never tell if your code is executing on an embedded system where your code has previously run and left valid configuration data in the EEPROM or not. So the format of your configuration data in the EEPROM must have some unique characteristics that your initialization code can use to verify its validity. If it appears to be valid, your code can go ahead and use it for configuring this new run. If it appears to be invalid, your initialization code should not rely on the contents of the EEPROM. It should either initialize it to default values or go through an interaction with the operator or another system (e.g. a network server) to obtain and store new configuration data in EEPROM.
Two validation mechanisms commonly used to indicate and verify the validity of the contents of EEPROM are magic numbers and checksums (or both).
A magic number is a specific location in the EEPROM as part of the configuration data that is of a specific size and contains a specific value. A magic number should contain enough bits to make it unlikely that it will be found accidently in an uninitialized memory. With the Arduino compiler, an int data type is 16 bits and an int magic number provides a 1 in 65536 chance of an accidental match. A long data type is 32 bits and a long magic number is better with only a 1 in 655362 chance of an accidental match. The magic number must be a value that is unlikely to appear in an uninitialized EEPROM. A value of all ones or all zeros is usually a bad choice because the memory might be shipped after manufacturing test with all locations set to one of those values. (I have observed that our Arduino boards start out with an all ones value in all EEPROM locations.) How can you choose a suitable value for your magic number? You pick one at random. See – it’s magic! In embedded systems, commonly used magic number values consist of alternation of bit states, e.g. 0xA5A5 or 0xA5A5A5A5.
A checksum is generated by operating on the contents of the configuration data with an algorithm that produces a checksum value that includes all values in the range of memory being protected. That value is then stored in a specific location in the EEPROM along with the configuration data. Again, the number of bits in the checksum should be large enough to avoid accidental matches and the algorithm should not typically produce a checksum value that will match when run on an uninitialized EEPROM containing all zeros or all ones.
However, recognize that although it may be unlikely that the chosen magic number and/or checksum is accidently determined to be valid, it is not impossible. Your code should also include some sanity checks on the values or combinations of values for parameters in the configuration data and escape to error handling code in case an accidental match has occurred.
NOTE: EEPROM memories have a limited lifetime in terms of the number of times that they can be written/read. In the Arduino UNO, this limit is specified as 100,000 read/write cycles. That value is specified conservatively. In practice, the memory will be good for more cycles than that, but keep this limitation in mind when you are planning use of an EEPROM memory. You don’t want your design to excessively read/write an EEPROM memory, e.g. by frequently storing/retrieving transient data in it.
In the Arduino UNO, the EEPROM is mapped to a memory space that is separate from program memory and RAM memory. The EEPROM memory is organized by bytes and its map has addresses ranging from 0 to the constant E2END. You should have learned the value of E2END in Lab 2. For reference, copy that value here: 0x______________.
In the Arduino IDE window, use the Help >> Reference menu, select the Libraries, and look at the EEPROM library. To access EEPROM, you need to include the header file <EEPROM.h>. The function EEPROM.read(int address) returns a char value from the indicated EEPROM address. The function EEPROM.write(int address, char value) stores the char value at the indicated EEPROM address.
In the setup function in your initial sketch, write a loop to display the existing values in the EEPROM from the beginning to the end of its memory space. What values do you find? Describe them in your report.
Now, change your setup function code to simulate storing, validating, and using configuration data in the EEPROM. Make it read and display a small number of bytes in the EEPROM. Then, run a bitwise exclusive-or on all bytes except the last one and ones-complement the result. Compare that value with the value stored in the last location in the EEPROM area that you are using.
If it is incorrect (which it should be the first time you run this sketch on your board), write some specific values into those locations except for the last one. You can use the letters of one of your team member’s name. These values represent your default configuration data. Then, run a char bitwise exclusive-or on all locations except the last one, ones compliment the result, and store it as a checksum in the last location. Print a message that "EEPROM has been reinitialized".
If it is correct, just print a message that "EEPROM checksum is OK".
Unplug the Arduino board from the PC to cause a power off. Plug it back in and run your code again to check the values in those EEPROM locations. Push the reset button on the Arduino board and check the values in those EEPROM locations again. Describe the results in your report.
Lastly, swap Arduino boards with another team that has also gotten this far in the assignment and run your code on that board. Check the values in the EEPROM initially and again after a power up/reset cycle. Explain what has happened.
Submit your report to the TA in your next lab session with a copy of the code for your final sketch.
___ / 10