Categories

Demo: AT45DB041D 4Mbit SPI flash memory

Posted on Monday, January 25th, 2010 in Bus Pirate, demonstrations by Ian

This is an old version, see the latest version on the documentation wiki.

This demo is what the Bus Pirate is all about. A AT45DB041D 4Mbit flash memory stores the FPGA design on the open source logic analyzer project currently known as SUMP PUMP. We’ve worked with EEPROMs in the past, but this chip is a different beast.

Follow along as we use the Bus Pirate to learn about this chip before writing firmware for the logic analyzer.

Demo is a weekly series that demonstrates chips with the Bus Pirate. Come back next Monday for another all new demo.

Device: AT45DB041D 4Mbit 66MHz SPI ROM (~$1.20).
Bus: SPI.
Power requirements: 2.7-3.6volts.
References: datasheet.
Complete Bus Pirate session log for this demonstration.

Bus Pirate AT45DB041D
MOSI SI
CLOCK SCK
MISO SO
CS CS
GND GND

We connected the Bus Pirate to an AT45DB041D as shown in the table above. Our ROM chip is powered by a regulator on the SUMP PUMP, but you could use the Bus Pirate’s on-board 3.3volt supply if you’ve got a bare chip. For this demo, we connected the WP and RESET pins to +3.3volts to permanently disable these features.

Bus Pirate setup

Start the Bus Pirate. Press m and enter SPI mode. Choose any speed and all the default SPI configuration settings. We’ll interface this chip directly at 3.3volts, so choose normal output types.

If you’re powering the AT45DB041D from the Bus Pirate, press W to turn on the power supplies. Press v and verify that the voltage regulators are working.

Interfacing the chip

This ATMEL data ROM has lots of features not found on smaller flash EEPROM. It has multiple data buffers, erase granularity at the chip, sector, and page level, and more. We’re only going to look at the features we plan to use in the SUMP PUMP firmware, but you can learn more about them from the datasheet and this app note.

Chip ID

SPI>[ 0x9f r:4]
CS ENABLED <<<chip select pin low
WRITE: 0x9F <<<get chip ID command
READ 0x04 BYTES: <<<read JEDEC ID
0x1F 0x24 0x00 0x00
CS DISABLED <<<chip select pin high
SPI>

Flash ROM chips have standardized instruction to retrieve manufacturer and device IDs, thought the IDs themselves vary in length. The Atmel ID values are described on page 26 of the datasheet.

To get the IDs, enable chip select ([) to activate the ROM’s SPI interface, then send 0x9f and read four bytes (r:4), complete the transaction by disabling the chip select line (]).

The first byte of the response is the manufacturer ID (0x1f=Atmel). The second byte (0x24=0b00100100) contains the device ID, the first three bits are the family code (001=dataflash), the last five bits are the density code (00100=4Mbit).

The third and fourth bytes are less interesting, see page 26 of the datasheet for a complete explanation of the ID values.

Chip erase

SPI>[0xc7 0x94 0x80 0x9a]
CS ENABLED
WRITE: 0xC7<<<4byte erase chip command
WRITE: 0x94
WRITE: 0x80
WRITE: 0x9A
CS DISABLED
SPI>

Let’s erase the chip before working with it. A complete chip erase is started by sending the four byte sequence 0xc7 0x94 0x80 0x9a. The chip takes 6 to 12 seconds to complete the erase cycle, see Tce on page 35 of the datasheet.

SPI>[0xd7 r ]
CS ENABLED
WRITE: 0xD7<<<read status command
READ: 0x1C <<< 0b00011100 (busy)
CS DISABLED
SPI>[0xd7 r] <<<after 6 to 12 seconds, try again
CS ENABLED
WRITE: 0xD7<<<read status command
READ: 0x9C <<< 0b10011100 (ready)
CS DISABLED
SPI>

The erase progress can be checked by reading the status register. Send 0xd7 to the ROM and read back a byte. The most significant bit of the byte indicates that the device is ready (1) or busy (0). You can read unlimited status bytes as you like after sending one 0xd7 command, which is handy when you implement your actual microcontroller code.

Page write

A page of memory is 264bytes long. An entire page of memory is written at once. A write operation takes two steps. First, load 264 bytes of data into the buffer, then write the buffer to the memory. Check the status bit to see when the write is complete. Our ROM has two buffers for pre-loading during the long write cycle.

SPI>[0x84 0 0 0 0x55:255 0x55:9]
CS ENABLED
WRITE: 0x84<<<write to buffer1 command
WRITE: 0x00<<<3byte buffer address (000)
WRITE: 0x00
WRITE: 0x00
WRITE: 0x55 , 0xFF TIMES <<<full with 0x55
WRITE: 0x55 , 0x09 TIMES
CS DISABLED
SPI>

Load data into the buffer with command 0x84 (0x87 loads buffer 2). Send a three byte address that sets the write pointer at byte 0-264 in the buffer (0 0 0). Finally, clock in the data to write (0x55, 264 times).

SPI>[0x83 0 0 0][0xd7 r]
CS ENABLED
WRITE: 0x83<<<save buffer 1 to memory
WRITE: 0x00<<<3 byte address (000)
WRITE: 0x00
WRITE: 0x00
CS DISABLED
CS ENABLED<<<second transaction reads status
WRITE: 0xD7<<<read status bit command
READ: 0x1C <<< 0b00011100 (busy)
CS DISABLED
SPI>[0xd7 r]<<<after write time, try again
CS ENABLED
WRITE: 0xD7<<<read status bit command
READ: 0x9C<<< 0b10011100 (ready)
CS DISABLED
SPI>

Save the data to the memory with command 0x83 (0x86 for buffer 2). Send a three byte address that sets the write pointer to a memory page. If the chip has already been erased, 0x88 (0x89 for buffer 2) can be used to write without erasing the page first.

The status register shows the chip is busy immediately after the write begins. After the write completes, the status bit shows the chip is ready for another operation.

Page read

SPI>[0xe8 0 0 0 0 0 0 0 r:255 r:9]
CS ENABLED
WRITE: 0xE8 <<<read array command
WRITE: 0x00<<<3byte address
WRITE: 0x00
WRITE: 0x00
WRITE: 0x00<<<4 dummy bytes
WRITE: 0x00
WRITE: 0x00
WRITE: 0x00
READ 0xFF BYTES:<<<read back data
0x55 0x55 0x55 0x55 0x55
….<<<lots of 0x55
0x55 0x55 0x55 0x55 0x55
READ 0x09 BYTES:
0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55 0x55
CS DISABLED
SPI>

Finally, we read back the data to verify that the write was successful. The simplest read command, 0xe8, treats the memory as one long array that can be read to the end.

Send the read command (0xe8), the three byte address of the byte to start reading, and four additional 0 bytes. Now read back 264 bytes. The data we read matches what we wrote (0x55), so the write was successful.

There’s more than one read command. See pages 5-7 of the datasheet for more.

Taking it further

Check the Bus Pirate manual for a complete list of chip demonstrations. Requests are always appreciated.

This entry was posted on Monday, January 25th, 2010 at 2:16 pm and is filed under Bus Pirate, demonstrations. You can follow any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed.

Leave a Reply

Notify me of followup comments via e-mail. You can also subscribe without commenting.

Recent Comments

  • Edward Mallon: I've managed to get cheap thermistors calibrated to about to +/- 0.2C with 3.3v Arduinos. https://edwardmallon.wordpress.com/2017/04/26/calibrating-oversampled-thermistors-with-an-arduino/ Instead of playing whack-a-mole with the various sources of...
  • Ja: What the keyer do? Sends random morse code or there is some input? If someone can point me to some source to read I would...
  • Sorin: Pleasure of free!
  • hli: Sunday++
  • Max: Jolly good stuff, although the "include 100 W resistors in series with the inputs and outputs" part is quite hilarious until one realizes* they meant...