BBAI 64 ICM20948 I2C connection fail..need help..

Hi all
I made a cape Board for the AI64 that has a I2C interface with icm20948 (Invensense,IMU).
i assign the default pin I2C2 (P9.19,P9,20) for SCL and SDA for icm20948 interface.
i made dts file for BONE-I2C2,dts below.

// SPDX-License-Identifier: GPL-2.0
/*

/dts-v1/;
/plugin/;

/*

  • Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
    */
    &{/chosen} {
    overlays {
    BONE-I2C2_imu.kernel = _ TIMESTAMP _;
    };
    };

&bone_i2c_imu {
status = β€œokay”;
imu@68{
symlink = β€œbone/i2c/imu”;
compatible = β€œinvensense,icm20948”;
reg=<0x68>;

};

};

I did check of the address of the devise is 0b1101000 but i cannot see any information about compatible for the icm20948 with beaglebone.

when i run make
src/arm64/overlays/BONE-I2C2.dts:28.3-14: Warning (reg_format): /fragment@1/overlay/imu@68:reg: property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1)
src/arm64/overlays/BONE-I2C2.dtbo: Warning (pci_device_bus_num): Failed prerequisite β€˜reg_format’
src/arm64/overlays/BONE-I2C2.dtbo: Warning (i2c_bus_reg): Failed prerequisite β€˜reg_format’
src/arm64/overlays/BONE-I2C2.dtbo: Warning (spi_bus_reg): Failed prerequisite β€˜reg_format’
src/arm64/overlays/BONE-I2C2.dts:25.8-30.4: Warning (avoid_default_addr_size): /fragment@1/overlay/imu@68: Relying on default #address-cells value
src/arm64/overlays/BONE-I2C2.dts:25.8-30.4: Warning (avoid_default_addr_size): /fragment@1/overlay/imu@68: Relying on default #size-cells value

and after make install ,re boot

debian@BeagleBone:~/BeagleBoard-DeviceTrees$ sudo beagle-version|grep UBOOT
[sudo] password for debian:
xxd: Connection timed out
UBOOT: Booted Device-Tree:[k3-j721e-beagleboneai64.dts]
UBOOT: Loaded Overlay:[BONE-I2C2.kernel]
debian@BeagleBone:~/BeagleBoard-DeviceTrees$ dmesg|grep i2c
[ 0.866498] i2c /dev entries driver
[ 0.967394] omap_i2c 40b00000.i2c: bus 0 rev0.12 at 100 kHz
[ 0.967863] omap_i2c 40b10000.i2c: bus 1 rev0.12 at 100 kHz
[ 0.992983] omap_i2c 42120000.i2c: bus 2 rev0.12 at 400 kHz
[ 0.993596] omap_i2c 2000000.i2c: bus 3 rev0.12 at 400 kHz
[ 0.994462] omap_i2c 2010000.i2c: bus 4 rev0.12 at 400 kHz
[ 0.995314] omap_i2c 2020000.i2c: bus 5 rev0.12 at 100 kHz
[ 0.995817] omap_i2c 2030000.i2c: bus 6 rev0.12 at 400 kHz
[ 0.996323] omap_i2c 2050000.i2c: bus 7 rev0.12 at 400 kHz
[ 6.605329] gb_i2c: module is from the staging directory, the quality is unknown, you have been warned.
[ 6.605746] gb_gbphy: registered new driver i2c
debian@BeagleBone:~/BeagleBoard-DeviceTrees$ tree /dev/bone
/dev/bone
β”œβ”€β”€ i2c
β”‚ └── 2 β†’ …/…/i2c-5
β”œβ”€β”€ pwm
└── uart
└── 0 β†’ …/…/ttyS2

3 directories, 2 files
debian@BeagleBone:~/BeagleBoard-DeviceTrees$ sudo i2cdetect -y -r 2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: – – – – – – – –
10: – – – 13 – – – – – – – – – – – –
20: – – – – – – – – – – – – – – – –
30: – – – – – – – – – – – – – – – –
40: – – – – – – – – 48 49 4a 4b 4c 4d 4e 4f
50: UU UU – – – – – – – – – – – – – –
60: – – – – – – – – – – – – – – – –
70: – – – – – – – –
debian@BeagleBone:~/BeagleBoard-DeviceTrees$ sudo i2cdetect -y -r 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: – – – – – – – –
10: – – 12 – – – – – – – – – – – – –
20: – – – – – – – – – – – – – – – –
30: – – – – – – – – – – – – – – – –
40: – – – – – – – – – – – – – – – –
50: – – – – – – – – – – – – – – – –
60: – – – – – – – – – – – – – – – –
70: – – – – – – – –

there is no U mark in 0x68 ,so i think connection fail.
what should i do.

I don’t think there is a driver included in the kernel currently, at least not that I can find.

I did find this https://github.com/sittner/icm20948-mod/tree/master (polling only)

Failing that, you can talk to the chip from userspace using the i2c dev driver.
Given that the above kernel driver only polls the chip, you would be no worse off reading it yourself from userspace.

Also found this (c++)v which might be of more use https://github.com/mtmal/ICM20948-linux-i2c/tree/main

1 Like

Thank you for your fast response.
I am quite new with embdded linux and beaglebone AI64.
Do you mean i need to build kernel with reference the sources?(or just build and add?)
i need more information to reference the git driver source and kernel build.
my kernel version is 5.10.168-ti-arm64-r113.

If you just go with a userspace program, then you don’t need to do anything with the kernel. As long as the I2C bus is enabled it should work.

Building a kernel module would be more work, plus if you update the kernel, you would probably need to recompile the kernel module.

How are you planning to use the device, what programming languages are you using ?

1 Like

Thank you for the reply

I did test both of the codes you recommended

  1. the polling only code
    $ make
    make -C /lib/modules/5.10.168-ti-arm64-r113/build M=/home/debian/icm20948-mod modules
    make[1]: Entering directory β€˜/lib/modules/5.10.168-ti-arm64-r113/build’

make[1]: *** No rule to make target β€˜modules’. Stop.

make[1]: Leaving directory β€˜/lib/modules/5.10.168-ti-arm64-r113/build’

2)the c++ code
After build,and run ./test_ICM20948 -l 2000 -c 1

Connected device is not ICM20948! ID:0
Fail to detect ICM20948
finished

something is connected…but
SDA,SCL vtg is 1.8vdc to ICM20948,P9_19,20 BBAI64 is 3.3vdc .

That will be a problem. Looking at the datasheet, looks like the minimum logic high voltage is stated as 2V for the BBB i/o pins . It looks like the AM3358 itself could be designed to use 1.8V i/o logic rather than 3.3V, , but that doesn’t help you any.

The -C option should be the path to the kernel source - is that true ? I suspect that is why the make is failing.

It is a bit irrelevant as I don’t think you will get that chip to work. I would look for something that is compatible with 3.3V logic.

hi
I though BBAI 64 (TDA4VM) use VSYS_IO_3V3 as default.(but i checked TDA4VM support 1.8V/3.3v with internal PU/PD)


I used level shifter(1.8 to 3.3 with 10k pull up ) and remove it today.i do not know how can set internal pull up…same result now.

For some reason I though you was using a BBB.

That table is confusing, and the datasheet on the chip is very long and not so easy to find information. The schematic shows power fo VDDSHV0 - 4 as being 3.3V, VDDSHV6 as 1.8V. So unless you can configure on a pin by pin basic what power domain it is connected to, you are stuck with what you have.
The pin multiplexing on describes the different peripherals/functions for pins and does not mention changing the power domain. I suspect you can’t. It would be dangerous in any case.

You might find it easier to connect the chip using SPI rather than I2C. You will need level shifters of course, but you don’t need to worry about the bidirectional open drain nature of I2C

thank for the advice but i desinged PCB only for using I2C (SPI need 4 pin connect routing)

in the k3-j721e-beagleboneai64-bone-nuses.dtsi
BONE_PIN(P9_19, i2c, P9_19A(PIN_INPUT_PULLUP, 4) P9_19B(PIN_INPUT, 7)) /* i2c2_scl *
BONE_PIN(P9_20, i2c, P9_20A(PIN_INPUT_PULLUP, 4) P9_20B(PIN_INPUT, 7)) /* i2c2_sda */

and the levelshifter what i use has internal 10k pull up and when i checked the impedance was 5.x(10k//10k)
I will check next week with setting dtsi as

|BONE_PIN(P9_19, i2c, P9_19A(PIN_INPUT, 4) P9_19B(PIN_INPUT, 7)) /* i2c2_scl /
|BONE_PIN(P9_20, i2c, P9_20A(PIN_INPUT, 4) P9_20B(PIN_INPUT, 7)) /
i2c2_sda */

Hi
now
debian@BeagleBone:~$ ls /sys/bus/i2c/devices
2-0050 4-0047 i2c-0 i2c-2 i2c-4 i2c-6
2-0051 5-0068 i2c-1 i2c-3 i2c-5 i2c-7
i think 5-0068 is the ICM20948

icm20948_mod
after install kernel headers :sudo apt-get install linux-headers-$(uname -r)
i can see code error of make ,and after debug ,i can see icm20948.ko
debian@BeagleBone:~/Downloads/icm20948-mod$ sudo insmod icm20948.ko
debian@BeagleBone:~/Downloads/icm20948-mod$ lsmod | grep icm20948
icm20948 20480 0

but fail to write
debian@BeagleBone:~/Downloads/icm20948-mod$ cat /var/log/syslog | grep icm20948

Jan 16 07:46:04 BeagleBone test_ICM20948: Failed to write 00 to device: 68, address: 7f.
Jan 16 07:46:04 BeagleBone test_ICM20948: Failed to write request to device: 68, address: 00 in order to olscat /varbtain data.

β†’ add 0x7f is a register bank ,acces fail
β†’ add 0x00 who am i ,access fail

i received linux kernel driver and porting guide from invensense.i am trying to add with
git clone GitHub - beagleboard/linux: The official Read Only BeagleBoard and BeagleBone kernel repository https://git.beagleboard.org/beagleboard/linux

What are you using to do the level shifting ?

Have you got access to a scope. I would double check the signals are correct. and that the pin muxing is setup correctly.

hi
sorry ,i tested changing pullup but that is no effect in changing pull up…level shifter is TCA9406DCTR

now i am trying to build with invensense driver .

The pull-ups are not that critical. The internal resistors are fine for a slow speed I2C bus. If you are going faster you might want to add some extra resistors to give an overall lower pull-up resistance.

Are you loading the overlay for the I2C2 bus ? Is it enabled by default ?
Also your overlay file does not look right to me. Where is bone_i2c_imu defined and associated with the correct I2C bus ?

As a first step I would check to make sure there are actual I2C signals on the pins. Have you got access to a scope.?
Write a simple Python program to read from the I2C bus so you can generate signals on demand and check the I2C pins. Setup the scope to trigger on the clock pin.

If the check has a status register, just try reading that. Compare it to the reset state.

1 Like

hi
i checked actual I2C signals on the pins(P9_19_SCL,P9_20_SDA of BBAI64 / ICM20948 with scope triggering and simple python script.

sudo apt-get update
sudo apt-get install python3-smbus

python script to check the i2c register read.

import smbus
import time

bus = smbus.SMBus(5) # 1 indicates /dev/i2c-5
DEVICE_ADDRESS = 0x68 # Replace with device’s address
STATUS_REG = 0x19 # status register’s address

def read_status_register():
β€œβ€β€œReads data from the status register.β€β€œβ€
try:
# Read a single byte from the specified register
status = bus.read_byte_data(DEVICE_ADDRESS, STATUS_REG)
return status
except Exception as e:
print(f"Error: {e}")
return None

def main():
while True:
status = read_status_register()
if status is not None:
print(f"Status Register: {status}")
time.sleep(1)

if name == β€œmain”:
main()

result
Status Register:128
Status Register:0
Status Register:0
Status Register:0

image

and i changed 0x00
i can see 0xEA same as described in spec

Ok that looks good, so the hardware is fine and doing what it should. The ICM20948 must be responding with an ACK or you would have seen an error I think.

That just leaves the driver.
Depending on your needs there are quite a few options.

  1. You could just talk to the chip directly yourself using the I2Cdev driver
    2 .You can get the kernel module working.
  2. As you are on the AI64 you could also write code to run on one of the R4 or PRU cores to read the IMU.

Really going to depend on what you are using it for and how fast you need to get the data. option 1 is probably the easiest as it will be easier to test and debug. Option 3 the hardest, especially as there is very little documentation for doing that. A couple of people here have managed to get code running on the R4 & PRU cores though.