Using a 24C256 / 24LC256 EEPROM on Raspberry Pi with device overlays

For my HappyPlayer project I needed non-volatile storage for some settings, but I wanted to make the RPIs SD card read-only to prevent data-loss or file system corruption in case of power loss of the whole device. So I used an EEPROM (Atmel 24C256) to store the settings in regular intervals to be able to restore them when the HappyPlayer boots.


Connecting the EEPROM

This is pretty easy. Connect the SDA, SCL, 3.3V and GND lines of the chip to the Rapsberry Pi:

  • EEPROM SDA -> RPi SDA (Pin 3)
  • EEPROM SCL -> RPi SCL (Pin 5)
  • EEPROM Vcc -> RPi 3.3V (Pin 1)
  • EEPROM GND -> RPi GND (e.g. Pin 6)

Thats’ it for the electrical part. It will put the device at address 0x50 (it’s address lines are internally pulled to GND, so A0-A2 are low / 0).

Now enable the RPIs I2C device. Run raspi-config or edit “/boot/config.txt” and add or uncomment:

dtparam=i2c_arm=on

to enable the I2C bus #1 (on the RPi Zero. It might be bus #0 on other RPis) and reboot. Now add your user to the I2C user group so you can access the I2C bus:

sudo usermod -aG i2c pi

Now, when you run:

i2cdetect -l

it should list one i2c bus named “i2c1”. When you run:

i2cdetect -y 1

it will scan that bus #1 for I2C devices. and will print something like this:

...
50: 50 -- -- -- -- -- -- -- 58 -- -- -- -- -- -- --
...

Meaning it has found a device at address 0x50 / 0x58. This is your EEPROM. So far, so good.

Accessing the EEPROM as a device file

There’s a couple of options on how to integrate the EEPROM into the system or access it from user-space. I used a device tree overlay, like I did for the rotary encoder. This is possible because there’s already a 24Cxxx driver (aptly named at24.c, device tree docs) available as a module on the Raspberry Pi / Raspbian, which we will use. Create a file called “at24c256.dts” with the following content:

/dts-v1/;
/plugin/;
/ {
  fragment@0 {
    target = <&i2c1>;
    overlay {
      pinctrl-names = "default";
      pinctrl-0 = <&i2c1_pins>;
      clock-frequency = <100000>;
      status = "okay";
      at24@50 {
        compatible = "atmel,24c256","at24";
        #address-cells = <1>;
        #size-cells = <0>;
        reg = <0x50>;
        pagesize = <64>;
        size = <32768>;
        address-width = <16>;
      };
    };
  };
};

This is the device overlay source file. You need to compile it to use it. Run:

dtc -O dtb -o at24c256.dtbo -b 0 -@ at24c256.dts

and copy “at24c256.dtbo” it to the “/boot/overlays” directory (might need su-rights). Then activate the overlay in “/boot/config.txt” by adding:

dtoverlay=at24c256

and reboot. After rebooting run “dmesg” and you should see a message similar to this:

[ 16.476626] at24 1-0050: 32768 byte 24c256 EEPROM, writable, 64 bytes/write

meaning the at24 driver was loaded an configured correctly. Now you can try writing to the EEPROM using:

echo 'Hello World' | sudo tee /sys/class/i2c-dev/i2c-1/device/1-0050/eeprom

and show its content using:

sudo more /sys/class/i2c-dev/i2c-1/device/1-0050/eeprom

If you want to write to the EEPROM as a regular user, make sure you can by changing the file mode:

sudo chmod 666 /sys/class/i2c-dev/i2c-1/device/1-0050/eeprom

To make that change on every boot, create a systemd service:

sudo nano /lib/systemd/system/eeprom.service

and add the following text:

[Unit]
Description=Make EEPROM device user-accessible
After=basic.target
Before=multi-user.target

[Service]
Type=oneshot
ExecStart=chmod 666 /sys/class/i2c-dev/i2c-1/device/1-0050/eeprom
RemainAfterExit=yes

Save the file and change its mode to:

sudo chmod 644 /lib/systemd/system/eeprom.service

The reload the systemd state and enable the service:

sudo systemctl daemon-reload
sudo systemctl enable eeprom.service

You can check the state of the service using:

systemctl status eeprom.service

and if it fails to start, check the log (add “-b” to view messages since the last boot using:

journalctl -u eeprom.service

Now reboot and the EEPROM should now be a regular file you can write to as you wish. Keep in mind though, that reading and writing is slow and EEPROM cells / individual bytes have only a certain number of write cycles until they break (there’s no wear-leveling whatsoever). Don’t write to each individual byte too often.

Published by HorstBaerbel

Software developer by trade and interest, but I venture into the electronics- and diy-world from time to time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website at WordPress.com
Get started
%d bloggers like this: