This simple tutorial will guide users through the process of interfacing an EEPROM chip to a Raspberry Pi using the GPIO pins and performing operations with Python scripts.
Let's start with some basics on EEPROM:
1) CE, OE, WE - What does it all mean?
In order to read, write and erase data from an EEPROM chip, we must first bring the chip at the correct state. This is done using 3 control pins typically named Chip Enable, Output Enable and Write Enable.
Chip Enable controls whether or not the chip is powered up. Depending on the type of chip, connecting this pin to the ground or to voltage will turn the chip on or off. Needless to say, that if we want to perform any operation we need to enable the chip. Disabling the chip allows us to power down the chip while leaving it electrically connected to our circuit. This way the chip consumes less power.
Output Enable is a pin used to tell the chip that you want to read from it. Once again, depending on the chip, connecting this pin to the ground or to voltage will tell the chip to present you with the contents of given memory address (more on that later). Disabling the Output completes the read operation.
Write Enable is similar to Output Enable but used for writing data to the chip. Depending on the type of chip, connecting it to ground or to voltage will make the chip write data to a selected memory address (more on that later).
2) So how do I control the pins?
It is easy! Depending on your EEPROM chip, you enable or disable these pins by connecting them to a voltage source or to the ground. The jargon used for the operation is "pull up" for connecting to voltage and "pull down" for connecting to the ground. In some cases (and in our case in particular), pulling up a pin causes the corresponding state to be Disabled instead of Enabled. This may sound counter intuitive since you expect to pull up to turn on something but such is life sometimes.
Warning!!!: Leaving one of these pins disconnected from the circuit does not equal to it being pulled down! If any of the pins are left disconnected from the circuit we call them "floating" and essentially their state is random and undetermined. For example, RF interference may cause a high or low signal and therefore make the pin act as if it is enabled or disabled. Always connect all the pins to your circuit!
3) It is all about sequencing!
Suppose I want to read some data from my EEPROM, what do I need to do with these pins to make it all work? Performing operations on EEPROM is all about doing things in the right order. So if we wish to read from the chip, our sequence would be as follows:
Set the memory address (pull up/down Address bus pins to form an address in binary format)
Enable chip (power up)
Enable output (read that address)
Read the memory address (the Data bus pins will now be set high/low according to the data in the address)
Disable output (the Data bus output is still enabled at this point so I can read the data)
Disable chip (power down, no output on the Data bus at this point)
Repeat the above for the next address you wish to read.
4) What was that bus you talked about?
Data Bus and Address Bus. The EEPROM chip, along with the CE, OE and WE pins, will also have a set of pins for setting an address and a set of pins for reading/writing data to the selected address. The number of pins for the Address Bus depends on the capacity of the chip. The higher the capacity, the more addresses are needed and therefore the more pins the bus will have. To set an address we pull up/down the pins to represent 1/0. Each address represented by any combination of bits contains 1 byte. So a chip with 2048 addresses will have 2048 byte capacity. The pins on the Address Bus are typically numbered like so: A0, A1, A2, A3,... A(n)
The Data Bus, in contrast with the Address Bus, can be either input or output, depending on the operation selected. If we choose to write to the chip, we set the address we wish to write to via the Address Bus and then we set the Data Bus by pulling its pins up/down to represent one byte. If we choose to read from the chip, then the Data Bus pins will be set high/low to represent the 1/0 of the byte contained in the address we selected. The pins on the Data Bus as numbered: D0, D1, D2,... D7
5) One last thing: Most Significant Bit
Most Significant Bit is essentially the bit that represents the highest value in a byte. Different chips may use a different ordering scheme when storing bytes. The documentation of your chip will define if the Most Significant Bit is at the highest or lowest pin number on the Data Bus. Once you know which pin has the MSB, the rest of the pins represent the rest of the bits in ascending or descending order. For example, if the MSB is on pin D7 of the Data Bus, then the Least Significant Bit is going the be on pin D0.
Step 1: Let's Put Things Together
I am attaching the GPIO layout of Raspberry Pi B+ along with the pin connections to the chip. Be very careful with the 5v pin on the Pi because although your EEPROM chip may function at 5v, it will also output 5v on the Data Bus when you read from it. And this means that it will feed 5v into the GPIO of the Pi which is really bad news because Pi uses 3.3v logic and you will fry your Pi.
So DO NOT use the 5v pins on the Pi!!!! Power your chip from the 3.3v pins!
1) OK, show me your gear
The rest of the guide is based on connecting the Pi to the EEPROM chip that I have. It is an SST 39SF020A which I scavenged from an old digital amp. You can search online for the documentation for the chip. It is freely available from many sources. I am not attaching it here in case of Copyright issues. There are three different version of this chip, each one with different capacity and therefore a different number of Address Pins. If you can get one of the three models of my chip, you can follow this guide closely. If you have a different chip, you need to find the documentation of your chip from the manufacturer and create a table that maps your chip's pins to mine. The notation for Address, Data and Enable pins is standard in the industry, so it should not be difficult. It is also worth noting that my chip considers the CE, OE and WE pins to be enabled when they are pulled down. Therefore, to activate the chip, I need to pull CE down. If I want to deactivate the chip, I need to pull CE up. This is done by setting the GPIO pins on/off. This does not apply to Data and Address pins. So for Data and Address pins, a "1" is an "on" signal on the connected GPIO pin. You see where this is going, right?
2) JEDEC write-protection: Keeping our data safe and making our life tougher!
Remember when I said that it is all about sequencing when you want to perform operations on the chip? Well sometimes it just happens that due to interference or voltage spikes (or any other undesirable occurrences in the circuit), a chip may be put in "write mode" and accidentally lose some of your data. To avoid this, JEDEC has come up with a standard for protecting the data. All it means, is that the chip will not enter "write mode" by simply enabling the WE pin. It expects a sequence of Addresses and Bytes before the chip "unlocks" its "write mode" and allows you to write data to an address. Your chip's documentation will define what this sequence is and it will all make more sense once you have a look at the code. For now, just keep in your mind that this mechanism complicates things a bit when we want to write data because it adds an overhead to the operation.
3) We got everything we need, let's do this!
I will assume you know how to use a breadboard and wires to connect your chip to the GPIO pins as shown in the attached diagram. Because my chip happens to have more pins than my Pi's GPIO, I have chosen to permanently attach the three highest pins on the Address Bus permanently to the ground. Therefore, those pins always read 0 and I cannot access the entire memory of my chip. Feel free to do the same if your chip also has too many Address pins. You may also choose to permanently pull down the CE pin so the chip is always on. It is entirely up to you. So, to clarify, I am permanently attaching A17, A16 and A15 on my chip to the ground and through the Pi's GPIO pins, I control pins A15 to A0. So I have a 16bit Address Bus and 8 bit Data Bus. I also control CE, OE and WE. And one last thing, on my chip, the Most Significant Bit is always the highest numbered pin.
Step 2: Reading From the Chip
In this step, I am attaching the Python script for reading from the chip. To execute it on your Pi, simply download the file and in your terminal navigate to the folder where you saved the file and type: sudo python EEPROMr.py
I have placed lots of comments in the code, so I will not analyse here what I did. It is pretty self-explanatory once you read the comments. I have tried to use try and catch loops to handle exceptions when things go wrong or when the user interrupts the program before it completes.
One thing to note is that the first comment in the script: "#Use chip numbering scheme" refers to the Pi's BroadCom chip and not to the EEPROM chip. Don't confuse the two.
Step 3: Erasing the Chip - This Wipes Out EVERYTHING!
So in this step I am attaching the script that deletes the entire EEPROM chip. This will set all the bits in every address of the chip with "1".
In this case the JEDEC write-protection kicks in, so if you follow the code closely, you will see the steps that correspond to the sequence of Addresses and Data that unlock the "write mode" of the chip. As you are going through the code, keep in mind how the CE and WE pins are being enabled/disabled to "latch" addresses and data.
To execute the script, navigate to the folder where you saved it and type: sudo python EEPROMd.py
You will get a prompt asking you to confirm the operation before it wipes all the data.
Step 4: Storing Data to the Chip
OK, so this script is a bit more interesting than the others. You execute it by typing: sudo python EEPROMw.py
It will first ask you to define an address of 15 bits. Enter the address starting with the Most Significant Bit in binary format. The script checks to validate that you used only 1/0 and that there is 15 of them. Once it is happy, it will ask you to define the data you want to store in the selected address. Once again, type a full Byte (8 bits) in binary format. Once it is happy, it will perform the write operation for you and inform you when it is complete. JEDEC write-protection is in effect in this script also, so watch out in the code for the sequence that "unlocks" the chip.
This script has a little oversight in that it does not catch Keyboard Interrupts when it prompts the user for addresses in data. This means that if you Ctrl+C during those steps, the script will terminate without cleaning up the GPIO pins. Feel free to add this functionality to the code for practice.
This concludes the EEPROM programming guide using Python on the Pi. You are free to use these scripts, modify them and distribute them for individual use and educational purposes.
Please give credit to Headamage and a link back to this page. The software is available under the GNU General Public Licence v2.