alt text

FRAM (ferroelectric RAM) is a non-volatile memory that combines the speed of SRAM with the persistence of EEPROM. It’s pretty new and much more expensive than EEPROM or flash, but check out these benefits:

  • Does not require a power supply to retain data
  • Writes are “instant”, no need to poll until the write is complete
  • 10^12 write cycles, 1 million times more than EEPROM
  • 200uA operating current vs 1mA for EEPROM
  • Page size is the entire chip, no juggling 8, 16 or 64 byte write pages!

The Fujitsu MB85RC256V is a 256Kbit (32Kbyte) FRAM memory chip with an I2C interface.

🛒

Get Bus Pirate & Accessories

Connections

Bus PirateMB85RC256VDescription
IO0/SDASDA (5)I2C Data
IO1/SCLSCL (6)I2C Clock
VoutVDD (8)3.3 volt power supply
GNDVSS (4)Ground

Connect the Bus Pirate to the FRAM as shown in the table above.

alt text

In addition to the I2C and power connections, the MB85RC256V three address pins and a write protect pin (protection active when WP is high/1).

The base I2C address is 0b1010, while A0, A1 and A2 set the lower 3 bits of the address. To use multiple chips on the same I2C bus, connect one or more of the address pins to VDD to give each a unique I2C address.

See it in action

Setup

Bus Pirate [/dev/ttyS0]
HiZ> m i2c

Mode: I2C
I2C speed
 1kHz to 1000kHz
 x. Exit
kHz (400kHz*) > 400
Clock stretching
 1. OFF*
 2. ON
 x. Exit
OFF (1) > 1
I2C> 

This particular FRAM chip has an I2C interface with a top speed of 1MHz, though others have an SPI interface with a higher top speed.

  • m i2c - change to I2C mode.
  • 400 - configure I2C for 400kHz.
  • 1 - disable clock stretching.

Power supply

alt text

Despite being a modern chip, the FRAM still has a maximum supply of up to 5 volts. This is probably part of making it a drop-in replacement for the older EEPROMs.

Bus Pirate [/dev/ttyS0]
I2C> W 3.3
3.30V requested, closest value: 3.30V
300.0mA requested, closest value: 300.0mA

Power supply:Enabled
Vreg output: 3.3V, Vref/Vout pin: 3.3V, Current: 2.6mA

I2C> 

Any voltage between 2.7 and 5.5 volts is acceptable. Let’s go with the present standard of 3.3 volts.

Images source: datasheet.

Pull-up resistors

Bus Pirate [/dev/ttyS0]
I2C> P
Pull-up resistors: Enabled (10K ohms @ 3.3V)

I2C> 

I2C is an open collector output bus, the Bus Pirate and the FRAM can only pull the line low to 0 (ground). A pull-up resistor is needed to pull the line high to 1 (3.3 volts). The Bus Pirate has built-in pull-up resistors that can be enabled with the P command.

I2C address scan

Bus Pirate [/dev/ttyS0]
I2C> scan
I2C address search:
0x50 (0xA0 W) (0xA1 R)
0x7C (0xF8 W)

Found 3 addresses, 1 W/R pairs.

I2C> 

Let’s see if we can find the FRAM I2C address. We could look in the datasheet, or we can be lazy and run an I2C address scan.

  • scan - Scan the I2C bus for devices

The scanner found an I2C device at address 0x50 (0xA0 write, 0xA1 read). That’s the FRAM main interface. The second write address 0x7c (0xf8 write) is used to get the device ID, which we’ll do later.

Write & Read Bytes

FRAM can read and write single bytes of data anywhere in the 32 Kbyte memory range.

Write Byte

alt text

Writing to the FRAM is identical to writing a 24Cxxx EEPROM. The write sequence is as follows:

  1. I2C START bit - begins an I2C transaction
  2. The I2C write address 0xA0 (Device Address + Write bit)
  3. Two byte address of the location to write in the 32 Kbytes of FRAM
  4. The data to write
  5. I2C STOP bit - ends the transaction
Bus Pirate [/dev/ttyS0]
I2C> [0xa0 0x00 0x09 0x48]

I2C START
TX: 0xA0 ACK 0x00 ACK 0x09 ACK 0x48 ACK 
I2C STOP
I2C> 

Let’s write byte 0x48 to the FRAM at address 0x0009 (9). The address is two bytes, so we send 0x00 0x09 for the high and low bytes.

  • [ - I2C START bit
  • 0xa0 - I2C address and write bit
  • 0x00 0x09 - Set write location to address 0x0009 (9)
  • 0x48 - Data to write
  • ] - I2C STOP bit

Read Byte

alt text

Reading a byte is a two step process.

  1. Set the location to read with a command to the write address (0xA0). This is the same sequency as writing a byte, but we don’t include any data (sometimes called a Dummy Write).
  2. Send the read address (0xA1) and read data from the EEPROM.

Set address pointer

Bus Pirate [/dev/ttyS0]
I2C> [0xa0 0x00 0x09]

I2C START
TX: 0xA0 ACK 0x00 ACK 0x09 ACK 
I2C STOP
I2C> 

A 0xa0 write command is used to set the address pointer to 0x0009. This time we won’t include any data. The address pointer will be updated, but nothing is written to the FRAM.

  • [ - I2C START bit
  • 0xa0 - I2C address and write bit
  • 0x00 0x09 - address pointer, high and low bytes, set to 0x0009 (9)
  • ] - I2C STOP bit

The address pointer has been set to 0x0009, the location of the data we want to read. This command didn’t include a data byte, so nothing was written to the FRAM.

Read Data

Bus Pirate [/dev/ttyS0]
I2C> [0xa1 r]

I2C START
TX: 0xA1 ACK 
RX: 0x48 NACK 
I2C STOP
I2C> 

Now that the address pointer is set to 0x0009, we can read the data at that location using the I2C read address 0xa1.

  • [ - I2C START bit
  • 0xa1 - I2C address and read bit
  • r - Read 1 byte
  • ] - I2C STOP bit

The data read from the EEPROM (RX) is 0x48, the same value we wrote earlier.

Write & Read Multiple Bytes

EEPROM and flash memory is organized into write pages of 8, 16, or 64 bytes. This means that writes must be aligned to the page size and boundary, and then you wait for the write to complete.

FRAM does not have this limitation! This is a huge advantage that we just learned about at this moment! Writing to FRAM is like writing to SRAM, you can write as much data wherever you want at top speed without juggling around page boundaries. This makes code much simpler!

Write Multiple Bytes

alt text

Writing multiple bytes is similar to writing single byte, we just send more data! Set the address pointer to the location of the first byte to write, and then send as much data as you like.

Bus Pirate [/dev/ttyS0]
I2C> [0xa0 0x00 0x00 0x55:16 0xaa:16]

I2C START
TX: 0xA0 ACK 0x00 ACK 0x00 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 
    0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 
    0x55 ACK 0x55 ACK 0x55 ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 
    0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 
    0xAA ACK 0xAA ACK 0xAA ACK 
I2C STOP
I2C> 

Let’s write 32 bytes starting at address 0x0000, the beginning of the memory.

  • [ - I2C START bit
  • 0xa0 - I2C address and write bit
  • 0x00 0x00 - set the address pointer to 0x0000 (the beginning of the memory)
  • 0x55:16 0xaa:16 - Write 0x55 and 0xaa to the FRAM, 16 times each
  • ] - I2C STOP bit

Read Multiple Bytes

alt text

Reading multiple bytes is similar to reading a single byte. First we set the address pointer to the beginning of the page with a write command, then we read the data - only more of it! The last byte read is NACKed by the Bus Pirate automatically to tell the FRAM we’re done reading.

Set Address Pointer

Bus Pirate [/dev/ttyS0]
I2C> [0xa0 0x00 0x00]

I2C START
TX: 0xA0 ACK 0x00 ACK 0x00 ACK 
I2C STOP
I2C> 

Set the address pointer to the beginning the memory, address 0x0000.

  • [ - I2C START bit
  • 0xa0 - I2C address and write bit
  • 0x00 0x00 - set the address pointer to 0x0000 (the beginning of the memory)
  • ] - I2C STOP bit

Read Bytes

Bus Pirate [/dev/ttyS0]
I2C> [0xa1 r:32]

I2C START
TX: 0xA1 ACK 
RX: 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 
    0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 0x55 ACK 
    0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 
    0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA ACK 0xAA NACK 
    
I2C STOP
I2C> 

Read back 32 bytes to verify the data was written.

  • [ - I2C START bit
  • 0xa1 - I2C address and read bit
  • r:32 - Read 32 bytes
  • ] - I2C STOP bit

The data read from the FRAM (RX) is 16 bytes of 0x55 and 16 bytes of 0xaa. The write was successful!

Read FRAM ID

alt text

The MB85RC256V has a 3 byte device ID that can be read from the Reserved Slave ID (0xf8/0xf9), a second I2C address that is not used for normal operations.

  1. I2C START bit - begins an I2C transaction
  2. Write to the Reserved Slave ID write address (0xf8)
  3. Write the I2C device address (0xa0 or 0xa1, doesn’t matter)
  4. I2C repeated START bit - prepares to read data
  5. Write the Reserved Slave ID read address (0xf9)
  6. Read 3 byte device ID
  7. I2C STOP bit - ends the transaction
Bus Pirate [/dev/ttyS0]
I2C> [0xf8 0xa0 [0xf9 r:3]

I2C START
TX: 0xF8 ACK 0xA0 ACK 
I2C REPEATED START
TX: 0xF9 ACK 
RX: 0x00 ACK 0xA5 ACK 0x10 NACK 
I2C STOP
I2C> 
  • [0xf8 0xa0 [0xf9 r:3] - Read the 3 byte device ID from the Reserved Slave ID address.

alt text

The device ID is 0x00A510.

  • The upper 12 bits (0x00A) make up the manufacturer ID, Fujitsu.
  • The lower 12 bits (0x510) make up the product ID, which includes a 4 bit density code (0x5) and a byte of proprietary info (0x10).

Get a Bus Pirate

🛒

Get Bus Pirate & Accessories

Community