Verdin i.MX8M Plus EEPROM disappears when an 3 I2C peripherals are connected on the extension slot X20

Hello Bruno,

This I2C bus is on /dev/verdin-i2c-on-module (/dev/i2c-0 ) is redirected on i2c-3. Am I right ? I believe so.

torizon@verdin-imx8mp-15229850:~$ ls -la /dev | grep i2c*
crw-rw-r--  1 root i2cdev   89,   0 Apr 16 05:56 i2c-0
crw-rw-r--  1 root i2cdev   89,   1 Apr 16 05:56 i2c-1
crw-rw-r--  1 root i2cdev   89,   2 Apr 16 05:56 i2c-2
crw-rw-r--  1 root i2cdev   89,   3 Apr 16 05:56 i2c-3
lrwxrwxrwx  1 root root          94 Apr 16 05:56 verdin-adc1 -> /sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0049/iio:device0/in_voltage3_raw
lrwxrwxrwx  1 root root          94 Apr 16 05:56 verdin-adc2 -> /sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0049/iio:device0/in_voltage2_raw
lrwxrwxrwx  1 root root          94 Apr 16 05:56 verdin-adc3 -> /sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0049/iio:device0/in_voltage1_raw
lrwxrwxrwx  1 root root          94 Apr 16 05:56 verdin-adc4 -> /sys/devices/platform/soc@0/30800000.bus/30a20000.i2c/i2c-0/0-0049/iio:device0/in_voltage0_raw
lrwxrwxrwx  1 root root           5 Apr 16 05:56 verdin-i2c-on-module -> i2c-0
lrwxrwxrwx  1 root root           5 Apr 16 05:56 verdin-i2c1 -> i2c-3
lrwxrwxrwx  1 root root           5 Apr 16 05:56 verdin-i2c2 -> i2c-1
lrwxrwxrwx  1 root root           5 Apr 16 05:56 verdin-i2c4 -> i2c-2

I am checking the presence of the EEPROM by checking the presence of the virtual file created by the driver so that you can read/write its content.

But, I have discovered that there is also a similar problem with the temperature sensor @ 004F on i2c-3

Here is what I have when the Dahlia board is not connected to my board:

torizon@verdin-imx8mp-15229850:~$ i2cdetect -y -r 3
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: UU -- -- -- -- -- -- -- -- -- UU -- -- -- -- UU
50: UU -- -- -- -- -- -- UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

torizon@verdin-imx8mp-15229850:~$ ls -al /sys/class/i2c-dev/i2c-3/device/3-0057/
total 0
drwxr-xr-x  4 root root    0 Apr 16 05:56 .
drwxr-xr-x 12 root root    0 Apr 16 05:56 ..
drwxr-xr-x  3 root root    0 Apr 16 05:56 3-00574
lrwxrwxrwx  1 root root    0 Apr 16 05:56 driver -> ../../../../../../../bus/i2c/drivers/at24
-rw-------  1 root root  256 Apr 16 06:10 eeprom
-r--r--r--  1 root root 4096 Apr 16 06:10 modalias
-r--r--r--  1 root root 4096 Apr 16 05:56 name
lrwxrwxrwx  1 root root    0 Apr 16 06:10 of_node -> ../../../../../../../firmware/devicetree/base/soc@0/bus@30800000/i2c@30a50000/eeprom@57
drwxr-xr-x  2 root root    0 Apr 16 06:10 power
lrwxrwxrwx  1 root root    0 Apr 16 05:56 subsystem -> ../../../../../../../bus/i2c
lrwxrwxrwx  1 root root    0 Apr 16 06:10 supplier:regulator:regulator.0 -> ../../../../../../virtual/devlink/regulator:regulator.0--i2c:3-0057
-rw-r--r--  1 root root 4096 Apr 16 05:56 uevent
torizon@verdin-imx8mp-15229850:~$

Just above, you can see that there is a file named eeprom.

And for the temperature sensor attached on the i2c-3 bus at the address 0x4F, here is the directory content where temp1_input is mounted.

torizon@verdin-imx8mp-15229850:~$ ls /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/
hwmon2
torizon@verdin-imx8mp-15229850:~$ ls -al /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2
total 0
drwxr-xr-x 3 root root    0 Apr 16 06:18 .
drwxr-xr-x 3 root root    0 Apr 16 06:18 ..
lrwxrwxrwx 1 root root    0 Apr 16 06:43 device -> ../../../3-004f
-r--r--r-- 1 root root 4096 Apr 16 06:43 name
lrwxrwxrwx 1 root root    0 Apr 16 06:43 of_node -> ../../../../../../../../../firmware/devicetree/base/soc@0/bus@30800000/i2c@30a50000/sensor@4f
drwxr-xr-x 2 root root    0 Apr 16 06:43 power
lrwxrwxrwx 1 root root    0 Apr 16 06:18 subsystem -> ../../../../../../../../../class/hwmon
-r--r--r-- 1 root root 4096 Apr 16 06:43 temp1_input
-rw-r--r-- 1 root root 4096 Apr 16 06:43 temp1_max
-rw-r--r-- 1 root root 4096 Apr 16 06:43 temp1_max_hyst
-rw-r--r-- 1 root root 4096 Apr 16 06:18 uevent
-r--r--r-- 1 root root 4096 Apr 16 06:43 update_interval
torizon@verdin-imx8mp-15229850:~$

As you can see, the path of the virtual file mounted by the driver of the Temperature Sensor TMP1075, is:
/sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2/temp1_input
So, the file temp1_input is located in the directory named: hwmon2

We’ve worked together on this topic on the ticket named : I2C Access from .NET SDK 8.0 Application : CLR/System.IO.IOException.

Just have a look and you will remind what you advised me for both EEPROM and for Temperature Sensor, as well as the C console application and the right I needed to set in .vscode\settings.json (“torizon_run_as”: “root”) and the paths I need to specify in docker-compose.yml file.

version: "3.9"
services:
  i2c-eeprom-and-temp-debug:
    build:
      context: .
      dockerfile: Dockerfile.debug
    image: ${LOCAL_REGISTRY}:5002/i2c-eeprom-and-temp-debug:${TAG}
    ports:
      - 2230:2230
    user: 0:0
    volumes:
      - type: bind
        source: /sys/class/i2c-dev/i2c-3/device/3-0057/eeprom
        target: /carrier_board_eeprom

      - type: bind
        source: /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2/temp1_input
        target: /carrier_board_temp

  i2c-eeprom-and-temp:
    build:
      context: .
      dockerfile: Dockerfile
    image: ${DOCKER_LOGIN}/i2c-eeprom-and-temp:${TAG}
    user: 0:0
    volumes:
      - type: bind
        source: /sys/class/i2c-dev/i2c-3/device/3-0057/eeprom
        target: /carrier_board_eeprom
      - type: bind
        source: /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2/temp1_input
        target: /carrier_board_temp

So, my application runs perfectly well when the Dahlia board is not connected to my board.

Here is the code for the community.

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]){
    printf("Hello Torizon!\n");

    FILE *eepromFile = fopen("/carrier_board_eeprom", "rwb");

    if(eepromFile == NULL){
        printf("Failed to open eeprom\n");
        return -1;
    }

    FILE *temperatureFile = fopen("/carrier_board_temp", "r");

    if(temperatureFile == NULL){
        printf("Failed to open temperature\n");
        fclose(eepromFile);
        return -1;
    }

    uint8_t eepromData[32];
    char temperatureString[32];

    // Run 10 cycles
    for(int i = 0; i < 10; i++){
        // Read first 32 bytes of EEPROM
        fseek(eepromFile, 0, SEEK_SET);
        fread(eepromData, 1, sizeof(eepromData), eepromFile);
        // Print Read Data
        printf("EEPROM:");
        for(int j = 0; j < sizeof(eepromData); j++){
            printf(" %X", eepromData[j]);
        }
        printf("\n");

        // Read temperature
        fseek(temperatureFile, 0, SEEK_END);
        // Get the current file pointer position, which is the file size
        size_t fileSize = ftell(temperatureFile);
        // Reset the file pointer back to the beginning of the file
        fseek(temperatureFile, 0, SEEK_SET);
        
        // Read temperature string
        fread(temperatureString, 1, fileSize, temperatureFile);
        // Convert to floating point
        float temperature = atoi(temperatureString)/1000.0;

        printf("Temperature: %f ºC\n", temperature);
        fflush(stdout);

        // Wait for 1 second
        usleep(1000000);
    }

    // Close files
    fclose(temperatureFile);
    fclose(eepromFile);

    return 0;
}

Now, here is what happens to the system when I connect on the connector X20 of the Dahlia board, the pins J5 (GND), J6 (SDA1), J7(SCL1) to the I2C bus of my expansion board, and the pins J1 (ADC1) and J11 (GND) to the output analog signal of the same expansion card ( 0 Volts < J1 < 1.38 Volts).

torizon@verdin-imx8mp-15229850:~$ i2cdetect -y -r 3
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- UU -- -- --
30: -- -- -- -- -- -- -- -- 38 39 -- -- 3c -- -- --
40: UU -- -- -- -- -- -- -- -- -- UU -- -- -- -- UU
50: 50 -- -- -- -- -- -- 57 -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

As, you can see the system has detected my 3 I2C devices at address 0x38, 0x39, and 0x3C, which is normal, since their addresses are configured this way, so at this step, everything is normal. We still have the TMP1075’s driver mounted at address 0x4F, which is also normal.

But, the EEPROM 24C02-F’s driver is no more loaded, and when we list the directory where the virtual eeprom file shoudl appear, here is what we have:

torizon@verdin-imx8mp-15229850:~$ ls -al /sys/class/i2c-dev/i2c-3/device/3-0057/
total 0
drwxr-xr-x  3 root root    0 Apr 16 07:27 .
drwxr-xr-x 12 root root    0 Apr 16 07:27 ..
-r--r--r--  1 root root 4096 Apr 16 07:29 modalias
-r--r--r--  1 root root 4096 Apr 16 07:27 name
lrwxrwxrwx  1 root root    0 Apr 16 07:29 of_node -> ../../../../../../../firmware/devicetree/base/soc@0/bus@30800000/i2c@30a50000/eeprom@57
drwxr-xr-x  2 root root    0 Apr 16 07:29 power
lrwxrwxrwx  1 root root    0 Apr 16 07:27 subsystem -> ../../../../../../../bus/i2c
-rw-r--r--  1 root root 4096 Apr 16 07:27 uevent
-r--r--r--  1 root root 4096 Apr 16 07:29 waiting_for_supplier

There is no eeprom file, so we cannot read/write anymore the EEPROM content.

Also, sometimes the file for the TMP1075 is not mounted in the same directory.

Usually, the file is mounted in /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2`:

torizon@verdin-imx8mp-15229850:~$ ls -al /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2
total 0
drwxr-xr-x 3 root root    0 Apr 16 07:57 .
drwxr-xr-x 3 root root    0 Apr 16 07:57 ..
lrwxrwxrwx 1 root root    0 Apr 16 08:03 device -> ../../../3-004f
-r--r--r-- 1 root root 4096 Apr 16 08:03 name
lrwxrwxrwx 1 root root    0 Apr 16 08:03 of_node -> ../../../../../../../../../firmware/devicetree/base/soc@0/bus@30800000/i2c@30a50000/sensor@4f
drwxr-xr-x 2 root root    0 Apr 16 08:03 power
lrwxrwxrwx 1 root root    0 Apr 16 07:57 subsystem -> ../../../../../../../../../class/hwmon
-r--r--r-- 1 root root 4096 Apr 16 08:03 temp1_input
-rw-r--r-- 1 root root 4096 Apr 16 08:03 temp1_max
-rw-r--r-- 1 root root 4096 Apr 16 08:03 temp1_max_hyst
-rw-r--r-- 1 root root 4096 Apr 16 07:57 uevent
-r--r--r-- 1 root root 4096 Apr 16 08:03 update_interval

And sometimes, the file is mounted in /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon3:
instead of /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2 which does not exist.

torizon@verdin-imx8mp-15229850:~$ ls -al /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon3
total 0
drwxr-xr-x 3 root root    0 Apr 16 07:57 .
drwxr-xr-x 3 root root    0 Apr 16 07:57 ..
lrwxrwxrwx 1 root root    0 Apr 16 08:03 device -> ../../../3-004f
-r--r--r-- 1 root root 4096 Apr 16 08:03 name
lrwxrwxrwx 1 root root    0 Apr 16 08:03 of_node -> ../../../../../../../../../firmware/devicetree/base/soc@0/bus@30800000/i2c@30a50000/sensor@4f
drwxr-xr-x 2 root root    0 Apr 16 08:03 power
lrwxrwxrwx 1 root root    0 Apr 16 07:57 subsystem -> ../../../../../../../../../class/hwmon
-r--r--r-- 1 root root 4096 Apr 16 08:03 temp1_input
-rw-r--r-- 1 root root 4096 Apr 16 08:03 temp1_max
-rw-r--r-- 1 root root 4096 Apr 16 08:03 temp1_max_hyst
-rw-r--r-- 1 root root 4096 Apr 16 07:57 uevent
-r--r--r-- 1 root root 4096 Apr 16 08:03 update_interval

The both problems only happen when our expansion board is connected to the Dahlia board through the X20 connector using the pins described above.

Could you please help me on these blocking issues ?

When these this happens, I cannot deploy my application on the SOM i.XM8M Plus since the bindings done in the docker-compose file do not work anymore since the files do not exist anymore.

volumes:
      - type: bind
        source: /sys/class/i2c-dev/i2c-3/device/3-0057/eeprom
        target: /carrier_board_eeprom

      - type: bind
        source: /sys/class/i2c-dev/i2c-3/device/3-004f/hwmon/hwmon2/temp1_input
        target: /carrier_board_temp

Many thanks.

Sincerely,
François.