Hi there,
We have an issue when making calls on i2c5 (pin 10,11 - ALT5) and i2c10/0 at the same time, where the signals seem to be getting crossed.
If we poll i2c5 for open addresses at the same time as i2c10, there are "Ghost" addresses that show up on the buses that randomly appear and disappear. I'm wondering if this is a product of our device tree overlay or a quirk of the system, and if there is a solution around it?
Here are the steps to reproduce the results
1) enable i2c5 with pins 10,11, and i2c0/10 with i2c_csi_dsi
2) run i2cdetect -y 5 and i2cdetect -y 10 at the same time.
In order to run the command at the same time you can run "i2cdetect -y 5 & i2cdetect -y 10", but the output is hard to parse because of overlapping outputs. To help with this, we wrote a script to give cleaner output. you will need to run this from two separate terminal sessions via ssh.
Terminal 1:Terminal 2: Example output:The script simply runs i2cdetect multiple times a second. The parameters allow you to select the buses you want to test. The final parameter uses a global mutex; if set to 0 the i2cdetect calls are concurrent, if set to 1, they are consecutive and will not produce ghost signals.
The test script:Our imx258_i2c5 overlay was written to allow i2c5 access to the cameras. Here is the DTS:And here is the config.txtThe current system is based on Bullseye 64 bit lite, running on a CM4. Tested on the official pi CM4 io board, and our own custom io board.
Testing against i2c0 and i2c10 at the same time (across the muxer) will not produce mixed signals.
Any help would be greatly appreciated!
We have an issue when making calls on i2c5 (pin 10,11 - ALT5) and i2c10/0 at the same time, where the signals seem to be getting crossed.
If we poll i2c5 for open addresses at the same time as i2c10, there are "Ghost" addresses that show up on the buses that randomly appear and disappear. I'm wondering if this is a product of our device tree overlay or a quirk of the system, and if there is a solution around it?
Here are the steps to reproduce the results
1) enable i2c5 with pins 10,11, and i2c0/10 with i2c_csi_dsi
2) run i2cdetect -y 5 and i2cdetect -y 10 at the same time.
In order to run the command at the same time you can run "i2cdetect -y 5 & i2cdetect -y 10", but the output is hard to parse because of overlapping outputs. To help with this, we wrote a script to give cleaner output. you will need to run this from two separate terminal sessions via ssh.
Terminal 1:
Code:
python3 detectI2cGhosts.py 10 0
Code:
python3 detectI2cGhosts.py 5 0
Code:
python3 detectI2cGhosts.py 10,5 0Starting I2C monitoring on buses 10, 5. Press Ctrl+C to exit.Locking enabled: FalseInitializing bus 10...Initial addresses on bus 10: 1b, UUInitializing bus 5...Initial addresses on bus 5: UUChange detected on I2C bus 5: Addresses added: 0f, 15Change detected on I2C bus 5: Addresses added: 09, 0b, 0d, 10, 13, 18, 1c Addresses removed: 0fChange detected on I2C bus 5: Addresses removed: 09, 0b, 0d, 10, 13, 15, 18, 1cChange detected on I2C bus 5: Addresses added: 09, 0b, 12, 19
The test script:
Code:
import subprocessimport timeimport osimport sysfrom collections import defaultdictLOCKFILE = '/tmp/i2c_detect.lock'def i2c_detect(bus, use_lock): """ Run i2cdetect on a specified I2C bus. If use_lock is True, use flock to ensure exclusive access. Return the detected addresses as a set. """ if use_lock: with open(LOCKFILE, 'w') as lock_file: result = subprocess.run(['flock', '-x', lock_file.name, '-c', f'i2cdetect -y {bus}'], capture_output=True, text=True, shell=True) else: # Construct the command as a single string command = f'i2cdetect -y {bus} > /tmp/i2c_{bus}.out' result = subprocess.run(['i2cdetect', '-y', str(bus)], capture_output=True, text=True) # Read the output from the temporary file lines = result.stdout.strip().split("\n")[1:] # Skip the header line addresses = set() for line in lines: parts = line.split()[1:] # Skip the first column which is row header for part in parts: if part != '--': addresses.add(part) return addressesdef detect_changes(previous, current): """ Detect added and removed addresses between two scans. Returns two sets: added addresses and removed addresses. """ added = current - previous removed = previous - current return added, removeddef main(): if len(sys.argv) < 3: print("Usage: python3 detect_ghost.py <i2c_bus_numbers> <use_lock>") print("<i2c_bus_numbers> : Comma-delimited list of I2C bus numbers to scan (e.g., 1,5,10).") print("<use_lock> : 1 to use the lock, 0 to not use the lock.") sys.exit(1) buses = [int(bus) for bus in sys.argv[1].split(',')] use_lock = bool(int(sys.argv[2])) scan_interval = 0.1 # 100 ms print(f"Starting I2C monitoring on buses {', '.join(map(str, buses))}. Press Ctrl+C to exit.") print(f"Locking enabled: {use_lock}") # Initialize previous state for each bus previous_state = {} for bus in buses: print(f"Initializing bus {bus}...") previous_state[bus] = i2c_detect(bus, use_lock) print(f"Initial addresses on bus {bus}: {', '.join(sorted(previous_state[bus])) if previous_state[bus] else 'None'}") try: while True: for bus in buses: current_addresses = i2c_detect(bus, use_lock) added, removed = detect_changes(previous_state[bus], current_addresses) if added or removed: print(f"\nChange detected on I2C bus {bus}:") if added: added_sorted = ', '.join(sorted(added)) print(f" Addresses added: {added_sorted}") if removed: removed_sorted = ', '.join(sorted(removed)) print(f" Addresses removed: {removed_sorted}") # Update the previous state previous_state[bus] = current_addresses time.sleep(scan_interval) except KeyboardInterrupt: print("\nI2C monitoring stopped by user.")if __name__ == "__main__": main()
Code:
// SPDX-License-Identifier: GPL-2.0-only// Definitions for IMX258 camera module on VC I2C bus/dts-v1/;/plugin/;#include <dt-bindings/gpio/gpio.h>/{compatible = "brcm,bcm2835";clk_frag_0: fragment@30 {target = <&cam0_clk>;cam_clk_0: __overlay__ {clock-frequency = <24000000>;status = "okay";};};clk_frag_1: fragment@31 {target = <&cam1_clk>;cam_clk_1: __overlay__ {clock-frequency = <24000000>;status = "okay";};};fragment@1 {target = <&i2c5>;__overlay__ {status = "okay";brcm,pins = <10 11>;};};fragment@3 {target = <&i2c0if>;__overlay__ {status = "okay";};};fragment@4 { target = <&i2c0mux>;__overlay__ {status = "okay";};};reg_frag_0: fragment@6 {target = <&cam0_reg>;cam_reg_0: __overlay__ {regulator-name = "imx258_vana";startup-delay-us = <300000>;regulator-min-microvolt = <1800000>;regulator-max-microvolt = <1800000>;};};reg_frag_1: fragment@7 {target = <&cam1_reg>;cam_reg_1: __overlay__ {regulator-name = "imx258_vana";startup-delay-us = <300000>;regulator-min-microvolt = <1800000>;regulator-max-microvolt = <1800000>;};};cam_left: fragment@100 {target = <&i2c_csi_dsi>;__overlay__ {#address-cells = <1>;#size-cells = <0>;status = "okay";imx258_cam_0: imx258@10 {compatible = "sony,imx258-pdaf";reg = <0x1A>;status = "okay";clocks = <&cam0_clk>;clock-names = "xclk";vana-supply = <&cam0_reg>;/* 2.8v */vdig-supply = <&cam_dummy_reg>;/* 1.05v */vif-supply = <&cam_dummy_reg>;/* 1.8v */rotation = <0>;orientation = <2>;port {imx258_0: endpoint {remote-endpoint = <&csi_ep_0>;clock-lanes = <0>;clock-noncontinuous;link-frequencies =/bits/ 64 <633600000320000000>;};};};vcm_cam_0: ad5398@c {compatible = "adi,ad5398";reg = <0x0c>;status = "disabled";VANA-supply = <&cam0_reg>;};};};cam_right: fragment@110 {target = <&i2c5>;__overlay__ {#address-cells = <1>;#size-cells = <0>;status = "okay";imx258_cam_1: imx258@5 {compatible = "sony,imx258-pdaf";reg = <0x1A>;status = "okay";clocks = <&cam1_clk>;clock-names = "xclk";vana-supply = <&cam1_reg>;/* 2.8v */vdig-supply = <&cam_dummy_reg>;/* 1.05v */vif-supply = <&cam_dummy_reg>;/* 1.8v */rotation = <0>;orientation = <2>;port {imx258_1: endpoint {remote-endpoint = <&csi_ep_1>;clock-lanes = <0>;clock-noncontinuous;link-frequencies =/bits/ 64 <633600000320000000>;};};};vcm_cam_1: ad5398@c {compatible = "adi,ad5398";reg = <0x0c>;status = "disabled";VANA-supply = <&cam1_reg>;};};};csi_0_frag: fragment@101 {target = <&csi0>;csi_0: __overlay__ {status = "okay";brcm,media-controller;port {csi_ep_0: endpoint {remote-endpoint = <&imx258_0>;clock-lanes = <0>;clock-noncontinuous;};};};};csi_1_frag: fragment@111 {target = <&csi1>;csi_1: __overlay__ {status = "okay";brcm,media-controller;port {csi_ep_1: endpoint {remote-endpoint = <&imx258_1>;clock-lanes = <0>;clock-noncontinuous;};};};};fragment@102 {target = <&imx258_0>;__overlay__ {data-lanes = <1 2>;link-frequencies = /bits/ 64 <633600000 320000000>;};};fragment@112 {target = <&imx258_1>;__overlay__ {data-lanes = <1 2 3 4>;link-frequencies = /bits/ 64 <633600000 320000000>;};};fragment@113 {target = <&imx258_1>;__dormant__ {data-lanes = <1 2 3 4>;link-frequencies =/bits/ 64 <633600000 320000000>;};};fragment@104 {target = <&csi_ep_0>;__overlay__ {data-lanes = <1 2>;};};fragment@114 {target = <&csi_ep_1>;__overlay__ {data-lanes = <1 2 3 4>;};};fragment@115 {target = <&csi_ep_1>;__dormant__ {data-lanes = <1 2 3 4>;};};__overrides__ {rotation = <&imx258_cam_1>,"rotation:0",<&imx258_cam_0>,"rotation:0";orientation = <&imx258_cam_1>,"orientation:0",<&imx258_cam_0>,"orientation:0";/*oldboard = <&i2c_frag_5>, "target:0=",<&i2c_vc>; <&csi_0_frag>, "target:0=",<&csi0>, <&clk_frag_0>, "target:0=",<&cam0_clk>, <®_frag_0>, "target:0=",<&cam0_reg>, <&imx258_cam_0>, "clocks:0=",<&cam0_clk>, <&imx258_cam_0>, "vana-supply:0=",<&cam0_reg>;vcm = <&vcm_cam_0>, "status=okay", <&imx258_cam_0>,"lens-focus:0=", <&vcm_cam_0>;4lane = <0>, "-102+103-104+105";*/};};
Code:
# Run in 64-bit modearm_64bit=1arm_boost=1#enable Antenna externaldtparam=ant2# Add support for software i2c on gpio pinsdtoverlay=i2c5,pins_10_11#add gpu memory for image processinggpu_mem=256#add the camera overlaydtoverlay=imx258_i2c5,rotation=180#shutdown button setupgpio=9=ip,np#other hardware on gpio=19=op,np,dh#buttongpio=18=ip,np#disable bluetoothdtoverlay=disable-bt
Testing against i2c0 and i2c10 at the same time (across the muxer) will not produce mixed signals.
Any help would be greatly appreciated!
Statistics: Posted by drewsipher — Mon Aug 26, 2024 9:11 pm — Replies 0 — Views 3