Skip to content

How-To EEPROM

Description

The Pi-Tron CM4 has an M24C32 EEPROM onboard, which offers the user 4 Kbytes of special storage for any kind of data. What's interesting about this EEPROM is, that it is compatible with a similar EEPROM named AT24xxx for which the Raspberry Pi OS includes a driver to access the EEPROM via a SysFS interface. However, currently there is no device tree file which uses this AT24 driver.

This How-To will try to show 2 ways to use and work with the EEPROM on the Pi-Tron CM4. The first part will be a direct communication via I2C with the chip programmed in Python. The second part will use a self-made device tree file which activates the AT24 driver and creates a SysFS interface in the OS for the user to work with.

Requirements

  • 24 volts power supply with 2 pin power plug for the Pi-Tron CM4.
  • Development computer with network access to the Pi-Tron CM4 or alternatively connect an HDMI monitor, mouse and keyboard.
  • To login into the Pi-Tron CM4 via network, it is requires that the SSH server is running.
  • The login details are by default: username: pi and password: raspberry
    • Note: The latest version of the Raspberry Pi OS requires the user creating the initial SD card or writing the system to eMMC memory to choose a username and password or the information has to be entered during first boot of the system. The above mentioned defaults may not apply to your situation.
  • A Terminal application (e.g. TeraTerm or Putty on the Windows host, or screen on Linux).
  • An active Internet connection to install additional software.
  • The EEPROM is connected to I2C bus 1 and has the address 0x50.

How-To

Preparation

Activate I2C

First make sure the I2C bus 1 is activated. Use the raspi-config program to enable the I2C interface, if this is not already the case. Afterwards reboot the Pi-Tron CM4.

raspi-config-main

raspi-config-interfaces

raspi-config-i2c-enable

raspi-config-i2c-enabled-ok

Install the SMBus Python module

To access any device on the I2C bus from Python, the module SMBus can be used. To install the SMBus module use pip for example.

On Raspberry Pi OS versions before Bullseye run this command to install the module globally.

sudo pip3 install smbus

If the Raspberry Pi OS version is Bullseye or later, try this command instead.

sudo pip install smbus

Starting with Raspberry Pi OS Bullseye only Python 3 is installed by default, which means pip3 defaults to pip and python3 defaults to python. In the past pip and python without a number would default to Python 2.

Install the i2c-tools

Installing the i2c-tools allows the user to perform an I2C bus scan to see which addresses (devices) are available on the bus.

sudo apt update
sudo apt install i2c-tools

Accessing the EEPROM via I2C

The EEPROM is connected to I2C bus 1 on the Pi-Tron CM4 and has the address 0x50. This means using the SMBus module in Python, the EEPROM can be accessed directly via I2C under that address. With a few lines of Python code reading and writing from and to the chip can be done in a fairly straightforward manner.

The examples shown below utilize a byte oriented access, which might not offer the best performance but allows for a free access to the stored data or to write/modify existing data on the chip.

  • Log in into the Pi-Tron CM4 and run the i2cdetect program to see if the EEPROM is present at address 0x50.

    sudo i2cdetect -y 1
    
  • The result should look something like the following table:

        0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    
    00:                         -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    50: 50 -- 52 -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --
    

Write data to the EEPROM

  • With the EEPROM now accessible, writing data to it can be done with the following example or download the example program eeprom_write_example.py.

    #!/usr/bin/env python3
    
    import smbus
    import time
    
    # The EEPROM address is by default 50h
    eepromadr = 0x50
    # To write a byte to an address byte of the EEPROM, a 2 byte address is needed
    eepromdata = [0] * 2
    # The EEPROM is connected to I2C Bus 1
    i2cbus = 1
    
    # Create an I2C Bus 1 instance
    mybus = smbus.SMBus(i2cbus)
    
    # Wait for the bus to initialize
    time.sleep(1)
    
    # Data (text) to store in the EEPROM
    mytext="The quick brown fox jumps over the lazy dog"
    # Convert the string to bytes
    mybytes = mytext.encode()
    
    # Write mytext to the EEPROM
    for i in range(0 ,len(mytext)):
    
        # Using "i" as the address selector and splitting it up into
        # the 2 needed address bytes for the EEPROM chip
        eepromdata[0] = i & 0xFF  # Low address byte
        eepromdata[1] = (i >> 8) & 0xFF  # High address byte
    
        # Create an address and data array combination.
        # The first byte must be the lower address byte and the byte
        # to write to the EEPROM must be second byte.
        data = [eepromdata[0], mybytes[i]]
    
        # Writing one byte to the EEPROM. The high address byte
        # is used for the address parameter. The SMBus function then creates
        # the needed sequence: Device-Selector, Adr-Byte-1, Adr-Byte-0, Data-Byte
        # on the bus as shown in the datasheet for the M24C32 EEPROM chip.
        mybus.write_i2c_block_data(eepromadr, eepromdata[1], data)
        # After a write, wait a short while
        time.sleep(0.015)
    
    print(str(len(mytext)) + " bytes written to EEPROM")
    
  • Run the Python program to write some data to the EEPROM.

    pi@raspberrypi:~ $ sudo python eeprom_write_example.py
                       43 bytes written to EEPROM
    

Read data from the EEPROM

  • Once the program completes, the information is now stored on the EEPROM and is available for further use. The next example will try to read the data from the EEPROM and print it to the console. Download the example program eeprom_read_example.py.

    #!/usr/bin/env python3
    
    # Note: Run the EEPROM write example before running the read example!
    
    import smbus
    import time
    
    # The EEPROM address is by default 50 hex
    eepromadr = 0x50
    # To read an address byte from EEPROM, a 2 byte address is needed
    eepromdata = [0] * 2
    # The EEPROM is connected to I2C Bus 1
    i2cbus = 1
    
    # Create an I2C Bus 1 instance
    mybus = smbus.SMBus(i2cbus)
    
    # Wait for the bus to initialize
    time.sleep(1)
    
    # Store the text read from the EEPROM. Requires that the
    # EEPROM write example was run beforehand.
    mytext=""
    
    # The text whih should be in the EEPROM
    textineeprom="The quick brown fox jumps over the lazy dog"
    
    # Read the first bytes as needed from the EEPROM in sequence
    for i in range(0, len(textineeprom)):
    
        # Using "i" as the address selector and splitting it up into
        # the 2 needed address bytes for the EEPROM chip
        eepromdata[0] = i & 0xFF  # Low address byte
        eepromdata[1] = (i >> 8) & 0xFF  # High address byte
    
        # Send the address change request to the EEPROM
        mybus.write_byte_data(eepromadr, eepromdata[1], eepromdata[0])
        # Read the selected byte from the EEPROM
        j = mybus.read_byte(eepromadr)
        # Convert the read byte into a character and add it to a string
        mytext += chr(j)
    
    # Once done, print the string to the console
    print (mytext)
    
  • Run the Python program to read back the data which was just written to the EEPROM.

    pi@raspberrypi:~ $ sudo python eeprom_read_example.py
                       The quick brown fox jumps over the lazy dog
    

Accessing the EEPROM through SysFS

The EEPROM can also be access through a SysFS interface which is provided by the Linux driver at24 (24c32). The only problem right now is that there is no device tree overlay to activate the driver. This means an overlay has to be created in order to utilize the EEPROM. An example DTS file can be downloaded from here.

Device Tree Overlay

This device tree file will load the at24 driver and also tells the driver that the EEPROM has address 0x50, a pagesize of 32, has 4096 bytes of storage and the register-address is 16 bits.

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

Compiling

In order for the Raspberry Pi OS to use the device tree overlay, the above shown text version has to be compiled in to a dtbo file which the OS can read.

  • Place the downloaded file on the Pi or create one manually and name it at24c32.dts for example.
  • Place the file in the pi users home folder for example and then issue the compile command

    dtc -O dtb -o at24c32.dtbo -b 0 -@ at24c32.dts
    
  • Now the compiled device tree file can be copied to the overlays folder in the boot partition of the SD card or eMMC memory.

    sudo cp at24c32.dtbo /boot/overlays/
    

Configure Overlay

  • The final step is to edit the config.txt file and add the overlay for the EEPROM.

    sudo nano /boot/config.txt
    
  • At the end of the file add

    # EEPROM at adr 0x50
    dtoverlay=at24c32
    
  • Reboot the Raspberry Pi

    sudo reboot
    

Verify the driver was loaded

After the reboot it makes sense to check that the driver for the EEPROM was actually loaded, otherwise the following examples would not work.

pi@raspberrypi:~ $ dmesg | grep at24
         at24 1-0050: supply vcc not found, using dummy regulator
         at24 1-0050: 4096 byte 24c32 EEPROM, writable, 32 bytes/write

The driver should produce to messages in the Kernel log, otherwise something went wrong.

Write data to the EEPROM

To write data to the EEPROM using the SysFS interface the commands echo and tee can be combined.

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

Executing this command will initiate a data transfer of the string Hello World! to the EEPROM, but also print Hello World! to the console.

Read data from the EEPROM

To read data from the EEPROM through the SysFS interface the command more can be used.

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

This command will read the entire EEPROM storage and print it to the console. The first part should be the Hello World! text from earlier, but the rest are just some placeholder characters signaling that the remaining space in the EEPROM is empty.

Hello World!
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒


This concludes the How-To for the EEPROM on the Pi-Tron CM4. Writing and read to and from the EEPROM should now be possible, either directly with a program or through the SysFS driver.

Restrictions

  • No known Restrictions