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.
Hello,
I am trying to do this, but when I reboot after copying the .dtbo file and adding to config.txt, I get the following error:
dterror. no overlay in fragment0
What can I do to fix this? I do get several warnings when I compile the .dts file that I copied from here.
LikeLike
The format of the .dts and .dtbo files might have changed… Check the docs and if you find out let me known.
LikeLike