Introduction: Bus Pirate 3EEPROM Explorer Board

If you've got one of Hack a Day's Bus Pirates, what do you do with it? Learn about 1-wire, I2C, and SPI EEPROMs with the 3EEPROM explorer board (we call it the THR-EE-PROM).

EEPROM is a type of memory chip that stores data without a continuous power supply. It's useful for permanent data storage in small logger circuits, or holding custom pages in a mini web server. EEPROMs come in lots of sizes and protocols.

The 3EEPROM has three common EEPROM chips: the DS2431 (1-Wire), 24AA- (I2C), and 25AA- (SPI). All three were previously demonstrated on Hack a Day, but each demo uses a different version of the Bus Pirate hardware and firmware, its difficult for a beginner to follow using a Bus Pirate v2go.

Continue reading for an updated, step by step guide to using the DS2431, 24AA-, and 25AA- EEPROMs with the Bus Pirate v2go. We've also got the full session logs as text files so you won't miss a single detail.

We can have 3EEPROM explorer board PCBs or kits produced at Seeed Studio. PCBs are about $10, kits are about $15, shipped worldwide. We need to organize a group purchase of 10 PCBs or 20 kits to get started. If you're interested in a Bus Pirate, version 3 is coming.

I couldn't include some formatting elements and HTML tables in an Instructable, you can see the original post at the Dangerous Prototypes blog.

Step 1: 3EEPROM Hardware Overview

The goal of this prototype is to learn about EEPROM and three common bus protocols. First, we look at the 3EEPROM PCB, then we demonstrate each EEPROM using a Bus Pirate universal serial interface tool. If you don't have a Bus Pirate, you can still follow along because the basic order of interface operations remains the same no matter how you implement them.

Circuit

Full size schematic [PNG]. We made the circuit and PCB using the freeware version of Cadsoft Eagle. You can download the schematic and PCB from the Bus Pirate SVN archive.

The 3EEPROM PCB holds a DS2431 1-Wire EEPROM (IC1), a 24AA- I2C EEPROM (IC4), and a 25AA- SPI EEPROM (IC5).

The DS2431 (IC1) draws power parasitically from the 1-Wire bus, it doesn't have an external power supply pin and doesn't require a decoupling capacitor. IC2 and IC3 are empty spots for additional 1-Wire devices, like another DS2431 or a DS1822 temperature sensor. C1 (0.01uF) is optional and only needed if IC2 or IC3 are populated with a powered 1-Wire device.

1-Wire requires a strong pull-up resistor, a maximum of 2.2K ohms. The Bus Pirate's on-board pull-up resistors are 10K, too weak to properly power the DS2431 during writes. The 3EEPROM explorer board includes a 1.8k ohm, 1/8th watt pull-up resistor (R1) on the 1-Wire bus so that no additional pull-up resistor is needed.

The 24AA-(IC4) and 25AA- (IC5) each get a 0.1uF capacitor to decouple them from the power supply (C2, C3). You probably don't need the capacitors in such a simple circuit, we omitted them from the prototype board in the demonstration. The I2C bus used by the 24AA- also requires pull-up resistors, but the Bus Pirate's on-board 10K ohm pull-up resistors are sufficient.

All the components will operate from 2.8volts to 5volts DC. The circuit is powered through the VCC and GND pins of jumper 3. There's two VCC pins, one is for power, the other is for the Bus Pirate's pull-up resistor voltage input pin (Vpullup).

PCB

We made the circuit and PCB using the freeware version of Cadsoft Eagle. You can download the schematic and PCB from the Bus Pirate SVN archive. If you'd like a professionally prepared PCB or 3EEPROM kit, we might be able to arrange a group purchase if 10 or 20 people are interested.

Parts list
R1 1800 ohm resistor (1/8th watt)
C2,3 0.1uF capacitor/10volts+
JP1-4 0.1" male pin header
IC1 DS2431 1K 1-wire EEPROM TO-92
IC4** 24AA014-I/P I2C EEPROM DIP8
IC5** 25AA010A-I/P SPI EEPROM DIP8
ICS4,5 8 pin DIP socket for IC5, 6

**IC4, IC5 could be any size, we linked to small chips, we used 128bytes and 128Kbytes.

I couldn't include some formatting and HTML tables in an Instructable, you can see the original post at the Dangerous Prototypes blog.

Step 2: 25AA- / 25LC- SPI EEPROM

Demonstrations

All EEPROM demos look pretty much the same. We'll write a few numbers to the chip, and then read them. Each device has conditions that apply once you want to write more than a few values, such as page size and boundary limitations. Read more about these in the datasheet for your specific device.

If you can't get a demonstration to work, download the complete terminal log so you don't miss a single thing we did. Pull-up resistors are the most common problem, check the pull-up pin voltage using menu 'v' in the Bus Pirate terminal.

Chip: 25AA, SPI EEPROM (1Kbyte).
Bus:SPI. Pull-up resistors only required for mixed-voltage interfacing.
Power requirements: 1.8volts to 5.5volts (AA), 2.5volts to 5.5volt (LC).
References:datasheet, Hack a Day demonstration.
Complete Bus Pirate session log for this demonstration.

I couldn't include some formatting and HTML tables in an Instructable, you can see the original at the Dangerous Prototypes blog.

IC5 is a 25AA- series I2C EEPROM from Microchip, these EEPROMs come in a ton of sizes. AA parts run from 1.8volts to 5.5volts, while the 25LC- parts have 2.5volt minimum requirement.

C3 (0.1uF) decouples the SPI EEPROM from the power supply. The write protect (WP) and hold pins could be controlled by a microcontroller, but we disabled them by holding these pins high. The SPI bus pins, CS, DO, CLK, and DI, are brought to header JP4.

Setup

If you're using a Bus Pirate, connect it to the 3EEPROM or 25AA- IC as shown in the chart image below. SPI doesn't normally require pull-up resistors.

Interfacing

In the Bus Pirate terminal press 'm' for the mode menu and select SPI. Configure the SPI library for normal pin output, use the defaults for all other SPI mode settings. Enable the power supplies (big 'W') at the SPI mode prompt. Finally, get a voltage report to make sure the power supplies are working ('v').

We're going to demonstrate how to interface the EEPROM directly at 3.3volts using the SPI library in normal pin mode. Pull-up resistors aren't required for this demo. If you want to interface an EEPROM powered by 5volts, use the SPI library in open collector (HiZ) pin mode and enable the pull-up resistors with the Vpullup pin (Vpu) connected to the EEPROM's power supply.

Step 1, turn off write-protect'

SPI>[0b110]
CS ENABLED <<<chip select enabled
WRITE: 0x06 <<<disable write protect command
CS DISABLED <<<chip select disabled
SPI>

The 25AA- is write protected at power-on. Lower chip select (CS) ([), send the disable write protect command (0x06), and then raise CS (]) to enable writes to the EEPROM.

The disable write protect command is 0b00000110 in binary, but we can shorten it to 0b110 and the Bus Pirate still understands.

Step 2, write some values'

SPI>[0b10 0 3 2 1]
CS ENABLED <<<chip select enabled
WRITE: 0x02 <<<write command
WRITE: 0x00 <<<write start address
WRITE: 0x03 <<<3 values to write (3,2,1)
WRITE: 0x02
WRITE: 0x01
CS DISABLED <<<chip select disabled
SPI>

Now the EEPROM is writable. First, lower CS to activate the 25AA- ([). Next, send the write command (0x02) and the location to begin writing (0). Send the data to store (3 2 1), then raise CS (]) to save the values.

Note: we used a tiny 128byte EEPROM, bigger chips will use a 16bit (2 byte) address. This command would be [0b10 0 '''0''' 3 2 1] for EEPROMs bigger than 256bytes, note the second 0. Check the datasheet for your EEPROM to be sure.

Step 3, read values back
SPI>[0b11 0 r:3]
CS ENABLED <<<chip select enabled
WRITE: 0x03 <<<read command
WRITE: 0x00 <<<read start address
BULK READ 0x03 BYTES: <<<read 3 values
0x03 0x02 0x01
CS DISABLED <<<chip select disabled
SPI>

Finally, read the data back to verify that the write was successful. Select the 25AA- ([), send the read command (0x03) and start address (0), and then read three values (r:3). Raise CS to complete the transaction (]). The values match, the write was successful.

Note: we used a tiny 128byte EEPROM, bigger chips will use a 16bit (2 byte) address. This command would be [0b11 0 '''0''' r:3] for EEPROMs bigger than 256bytes, note the second 0. Check the datasheet for your EEPROM to be sure.

Step 3: 24AA- / 24LC I2C EEPROM

Chip: 24AA, I2C EEPROM (1Kbyte).
Bus:I2C, pull-up resistors required.
Power requirements: 1.8volts to 5.5volts (24AA), 2.5volts to 5.5volt (24LC).
References:datasheet, Hack a Day demonstration.
Complete Bus Pirate session log for this demonstration.

I couldn't include some formatting and HTML tables in an Instructable, you can see the original at the Dangerous Prototypes blog.

IC4 is a 24AA- series I2C EEPROM from Microchip, these EEPROMs come in a ton of sizes. AA parts work from 1.8volts to 5.5volts, while the 24LC- parts have a 2.5volt minimum requirement.

A 0.1uF capacitor (C2) decouples IC4 from the power supply. The write protect pin (WP) could be controlled from a microcontroller, but for this simple demonstration we disable it with a connection to ground. The I2C bus pins, SDA and SCL, are brought out to header JP2.

The address of most 24AA EEPROMs is 1010AAAS, with the final four bits determined by the address pins (A0, A1, A2) and the read/write mode select bit (S). All the address bits are grounded in this example, so the write address of the EEPROM is 10100000 (datasheet page 6).

Setup

If you're using a Bus Pirate, connect it to the 3EEPROM or 24AA- IC as shown in the chart image below. I2C is a bidirectional bus that requires pull-up resistors on both pins. You can use the Bus Pirate's on-board pull-up resistors by connecting the Vpullup (Vpu) pin to the 3.3volt power supply and enabling them in the terminal.

Interfacing

Note: Not all I2C EEPROMs work the same. The tiny 24AA01, for example, has a completely different addressing and command system. Be sure to check the datasheet for your chip.


Press 'm' in the Bus Pirate terminal and select I2C from the mode menu. Enable the power supplies (big 'W') and the pull-up resistors ('p', option 2) at the I2C prompt. Get a voltage report ('v') to make sure the power supplies are on and the Vpullup pin is connected to a voltage.
I2C>(0) <<<get list of macros
0.Macro menu
1.7bit address search
I2C>(1) <<<use address search macro
Searching 7bit I2C address space.
Found devices at:
0xA0 0xA1 <<<found devices
I2C>

We already know that the I2C address is 10100000, but we can also use the Bus Pirate's I2C search macro (1) to search for the 24AA-. The search macro found the device at the expected write (0xA0) and read (0xA1) addresses.

Step 1, write some values
I2C>[0b10100000 0 0 3 2 1]
I2C START CONDITION <<<I2C start condition
WRITE: 0xA0 GOT ACK: YES <<<24AA- write address
WRITE: 0x00 GOT ACK: YES <<<write address byte 1
WRITE: 0x00 GOT ACK: YES <<<write address byte 2
WRITE: 0x03 GOT ACK: YES <<<3 values to write (3,2,1)
WRITE: 0x02 GOT ACK: YES
WRITE: 0x01 GOT ACK: YES
I2C STOP CONDITION <<<I2C stop condition
I2C>

Begin the write with an I2C start condition ([), followed by the 24AA- write address (0xa0). Next, send the 16bit address to write at (0 0) and the data to write (3 2 1). End the I2C transaction with a stop condition (]).

Step 2, position the read pointer
I2C>[0b10100000 0 0]
I2C START CONDITION <<<I2C start condition
WRITE: 0xA0 GOT ACK: YES <<<24AA- write address
WRITE: 0x00 GOT ACK: YES <<<write address byte 1
WRITE: 0x00 GOT ACK: YES <<<write address byte 2
I2C STOP CONDITION <<<I2C stop condition
I2C>

It takes two operations to read from the 24AA-. One positions the read/write pointer, the other returns the values.

Begin with an I2C start condition ([) and the write address (0xa0). Send the 16bit address to read (0 0), and then the stop condition (]). We didn't send any data to write this time, we just positioned the read/write pointer back to the beginning of the data we wrote in step 1.

Step 3, read some values
I2C>[0b10100001 r:3]
I2C START CONDITION <<<I2C start condition
WRITE: 0xA1 GOT ACK: YES <<<24AA- read address
BULK READ 0x03 BYTES: <<<read 3 values
0x03 0x02 0x01
I2C STOP CONDITION <<<I2C stop condition
I2C>

Step 2 set the read/write pointer to the beginning of the data we want to read. Now we can read the data using the 24AA- read address.

Begin with the I2C start condition ([) and 24AA- read address (0xa1). Read the three values we wrote in step 1 (r:3), and end with a stop condition (]). If the values match, then your write was successful.

Step 4: DS2431 1-Wire EEPROM

Chip: DS2431, 1-wire EEPROM (1Kbyte).
Bus:1-Wire, <2.2Kohm pull-up resistor required.
Power requirements: 2.8volts to 5.25volts.
References:datasheet, Hack a Day demonstration.
Complete Bus Pirate session log for this demonstration.

I couldn't include some formatting and HTML tables in an Instructable, you can see the original at the Dangerous Prototypes blog.

The DS2431 draws power from the pull-up resistor and doesn't need an external supply or decoupling capacitor.

1-Wire needs a strong pull-up resistor, a maximum of 2.2Kohms. The Bus Pirate's on-board pull-up resistors are 10K, too weak to properly power the DS2431 during writes. You must use a 2.2Kohm or smaller external resistor between power and the 1-Wire bus pin. If you have difficulties writing data, make sure your pull-up resistor is large enough. The 3EEPROM explorer board includes a 1800 ohm pull-up resistor (R1) on the 1-Wire bus so no external resistor is needed.

Setup

If you're using a Bus Pirate, connect it to the 3EEPROM board or DS2431 as shown in the chart image below. The DS2431 doesn't require the power supply pin, it's used on the 3EEPROM board to power the large pull-up resistor for the 1-Wire bus.

Interfacing

Press 'm' in the Bus Pirate terminal and select 1-Wire mode. Enable the on-board power supplies (big 'W') and check the voltage monitor (v).

Step 1, find the device address
1-WIRE>(0xf0) <<<1-Wire search macro
1WIRE ROM COMMAND: SEARCH (0xF0)
Found devices at:
Macro 1WIRE address
1.0x2D 0x54 0xD2 0xEF 0x00 0x00 0x00 0x2B <<<DS2431 unique ID
*DS2431 1K EEPROM <<<device type is known
Found 0x01 devices.
The first 10 device IDs are available by MACRO, see (0).
1-WIRE>

Each 1-Wire device has a unique 8 byte ID. 1-Wire has a search procedure that detects the ID of all attached devices. The Bus Pirate implements the 1-Wire search as macro (240). Type '(240)' in the Bus Pirate terminal to start the 1-Wire search.

Each device address is printed, known devices are identified. The first ten 1-Wire device addresses are stored as macros, in this example our DS2431 address is available by typing '(1)' in the terminal.

Step 2, write 8 bytes to the scratch pad
1-WIRE>(0x55) (1) 0x0f 0 0 8 7 6 5 4 3 2 1
1WIRE BUS RESET OK <<<also { command
1WIRE WRITE ROM COMMAND: MATCH (0x55) *follow with 64bit address
1WIRE ADDRESS MACRO 1: 0x2D 0x54 0xD2 0xEF 0x00 0x00 0x00 0x2B '
WRITE: 0x0F <<<DS2431 write scratch pad command
WRITE: 0x00 <<<DS2431 write address byte 1
WRITE: 0x00 <<<DS2431 write address byte 2
WRITE: 0x08 <<<start 8 data values to write
WRITE: 0x07
WRITE: 0x06
WRITE: 0x05
WRITE: 0x04
WRITE: 0x03
WRITE: 0x02
WRITE: 0x01
1-WIRE>

Next we'll write 8 bytes to a temporary location in the DS2431 called the scratch pad.

Start the transaction with a 1-Wire bus reset and MATCH command (0x55). Both are available as macro '(0x55)'. This can also be done without a macro by typing '{ 0x55', { sends the 1-Wire reset, 0x55 is the 1-Wire MATCH command.

After the MATCH command, send the 8 byte ID of the device to address. We used the macro (1) which was populated with the DS2431 ID in step 1. You could also enter the 8 byte ID manually. At this point the DS2431 should have received it's address and be ready for commands.

0x0f is the write scratch pad command, it tells the DS2431 to expect data. The next two bytes tell it where to put the data, we'll save it at the beginning (0 0). Finally, we send 8 bytes of values to store, the numbers 8 to 1.

You must write a full 8 bytes to the DS2431. Additionally, the write address must be on an 8 byte boundary. See the datasheet for a complete overview of the write limitations.

Step 3, verify the scratch pad and get the authorization code
1-WIRE>(0x55)(1) 0xaa r:3 r:8 r:2 r:2
1WIRE BUS RESET OK <<<address the device
1WIRE WRITE ROM COMMAND: MATCH (0x55) *follow with 64bit address
1WIRE ADDRESS MACRO 1: 0x2D 0x54 0xD2 0xEF 0x00 0x00 0x00 0x2B
WRITE: 0xAA <<<read scratch pad command
BULK READ 0x03 BYTES: <<<authorization code
0x00 0x00 0x07
BULK READ 0x08 BYTES: <<<the data we sent
0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01
BULK READ 0x02 BYTES: <<<CRC for the data
0xC8 0x86
BULK READ 0x02 BYTES: <<<all 1s after CRC
0xFF 0xFF
1-WIRE>

Verify that the data was received correctly, and get a write authorization code.

Begin again with a 1-Wire reset and MATCH command macro (0x55), and the device address macro (1). This time send the DS2431 read scratch pad command (0xAA), and then read a total of 15 bytes.

The first 3 bytes read (r:3) are the write authorization code, we'll need it in the next step to copy the scratch pad to the EEPROM. The next 8 bytes (r:8) should match the data we sent in step 2. The final 2 bytes (r:2) are a CRC16 for the data. Reads after the CRC return all 1s.

Step 4, write the scratch pad to the EEPROM
1-WIRE>(0x55)(1) 0x55 0x00 0x00 0x07
1WIRE BUS RESET OK <<<address the device
1WIRE WRITE ROM COMMAND: MATCH (0x55) *follow with 64bit address
1WIRE ADDRESS MACRO 1: 0x2D 0x54 0xD2 0xEF 0x00 0x00 0x00 0x2B
WRITE: 0x55 <<<copy scratch pad command
WRITE: 0x00 <<<3 byte authorization code from step 3
WRITE: 0x00
WRITE: 0x07
1-WIRE>

We have everything we need to store the scratch pad data permanently in the EEPROM.

Address the device, then send the DS2431 copy scratch pad command (0x55) followed by the three byte authorization code we retrieved in step 3 (0x00 0x00 0x07). If the authorization code is correct, the data is moved to the EEPROM.

Step 5, verify the scratch pad write
1-WIRE>(0x55)(1) 0xaa r:3
1WIRE BUS RESET OK <<<address the device
1WIRE WRITE ROM COMMAND: MATCH (0x55) *follow with 64bit address
1WIRE ADDRESS MACRO 1: 0x2D 0x54 0xD2 0xEF 0x00 0x00 0x00 0x2B
WRITE: 0xAA <<<read scratch pad command
BULK READ 0x03 BYTES:
0x00 0x00 0x87 <<<updated authorization code
1-WIRE>

The DS2431 sets the upper most bit of the write authorization code after a successful copy scratch pad command. Send another read scratch pad command (0xAA) to get the updated authorization code, but just read the first three bytes (r:3). The previous value 0x07 has changed to 0x87, the copy command was received successfully.

Step 6, read back the values
1-WIRE>(0x55)(1) 0xf0 0x00 0x00 r:8 r:8
1WIRE BUS RESET OK <<<address the device
1WIRE WRITE ROM COMMAND: MATCH (0x55) *follow with 64bit address
1WIRE ADDRESS MACRO 1: 0x2D 0x54 0xD2 0xEF 0x00 0x00 0x00 0x2B
WRITE: 0xF0 <<<DS2431 read command
WRITE: 0x00 <<<2 byte read address
WRITE: 0x00
BULK READ 0x08 BYTES: <<<read the 8 bytes we wrote
0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01
BULK READ 0x08 BYTES: <<<read more values
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
1-WIRE>

Verify the write worked properly by retrieving the values. Address the DS2431, then send the read command (0xf0) and the address to read from(0x00 0x00).

It's possible to read the entire memory range with a single command. We read the eight bytes we wrote earlier (r:8), which returned the expected values. The eight bytes beyond these values haven't been written and return 0.

Step 5: Conclusion

Conclusion

This prototype teaches about EEPROM memory, and demonstrates how to use the Bus Pirate with three common protocols: 1-Wire, I2C, and SPI.

The 3EEPROM explorer board ensures the proper connections to each EEPROM, and provides an external pull-up resistor for the more demanding 1-Wire bus with parasitically powered components.

We can have 3EEPROM explorer board PCBs or kits produced at Seeed Studio. PCBs are about $10, kits are about $15, shipped worldwide. We need to organize a group purchase of 10 PCB or 20 kits to get started.