Hello,
I am currently trying to get I3C1 running in I2C mode on a custom board with Zephyr. The custom board uses the MIMXRT595SFFOC. If I configure the same pins (PIO3_1 and PIO3_2) to Flexcomm0 as I2C, the bus works fine and the sensor (LPS22HH) with ST zephyr driver responds successfully. It works also fine when I attach the same sensor to the I3C0 bus and configure it in Zephyr like this:
sensor_i3c: &i3c0 {
status = "okay";
pinctrl-0 = <&pinmux_i3c0>;
pinctrl-names = "default";
i2c-scl-hz = <400000>;
i3c-scl-hz = <8250000>;
i3c-od-scl-hz = <2500000>;
zephyr,disabling-power-states = <&suspend>;
lps22hh: lps22hh@5c0000000000000050 {
compatible = "st,lps22hh";
status = "okay";
reg = <0x5c 0x0 0x50>;
odr = <LPS22HH_DT_ODR_25HZ>;
};
};
The pinmux looks like this:
pinmux_i3c0: pinmux_i3c0 {
group0 {
pinmux = <I3C0_SCL_PIO2_29>,
<I3C0_SDA_PIO2_30>;
input-enable;
slew-rate = "normal";
drive-strength = "high";
};
};
With that setup working, I attached the same sensor to the I3C1 Pins again (where it works successfully when configured as Flexcomm0). Then I added this configuration to the device tree:
&peripheral {
i3c1: i3c@37000 {
compatible = "nxp,mcux-i3c";
reg = <0x37000 0x1000>;
interrupts = <67 0>;
clocks = <&clkctl1 MCUX_I3C_CLK>;
clk-divider = <2>;
clk-divider-slow = <1>;
clk-divider-tc = <1>;
status = "disabled";
#address-cells = <3>;
#size-cells = <0>;
};
};
sensor_i3c1: &i3c1 {
status = "okay";
pinctrl-0 = <&pinmux_i3c1>;
pinctrl-names = "default";
i2c-scl-hz = <400000>;
i3c-scl-hz = <8250000>;
i3c-od-scl-hz = <2500000>;
zephyr,disabling-power-states = <&suspend>;
lps22hh: lps22hh@5c0000000000000050 {
compatible = "st,lps22hh";
status = "okay";
reg = <0x5c 0x0 0x50>;
odr = <LPS22HH_DT_ODR_25HZ>;
};
};
Pinmux:
pinmux_i3c1: pinmux_i3c1 {
group0 {
pinmux = <I3C1_SCL_PIO3_1>,
<I3C1_SDA_PIO3_2>;
input-enable;
slew-rate = "normal";
drive-strength = "high";
};
};
With this configuration, the sensor is still responding on the bus, as the scope shows:

However the I3C1 peripheral does not receive any byte on the bus, though the response from sensor is there. This leads to a timeout in mcux_i3c_do_one_xfer_read as the RXPEND interrupt is not firing.
What I already did to debug this:
- I checked the NVIC configuration for the I3C1 IRQ. This is correct, as during initialization of the I3C driver the ISR is called multiple times because of the MERRWARN OREAD flag.
- I checked all relevant I3C1 registers (MCONFIG, MCTRL, MSTATUS, MINTSET, MERRWARN, MDMACTRL) during init, write and read. It looks the same as on I3C0 when sensor is working. DMA is not used, so received bytes should be available in the peripherals FIFO.
- I also played with the SKEW setting as the ERRATA was mentioning it may be necessary for I2C in some cases.
- I also checked the IOPCTL registers for the 2 Pins to make sure they are right. Looks exactly the same as on I3C1, too.
- Then I thought, what if the interrupt anyway does not work. So I modified the i3c_mcux.c driver like this. This way it does not use the interrupt for receiving and just reads what it gets in the FIFO. There is not a single byte getting received.
static int mcux_i3c_do_one_xfer_read(I3C_Type *base, struct mcux_i3c_data *data, uint8_t *buf,
uint8_t buf_sz, bool ibi)
{
int ret = 0;
int offset = 0;
while (offset < buf_sz) {
/*
* Transfer data from FIFO into buffer. Read
* in a loop until data is unavailable in the FIFO.
*/
uint16_t count = 0;
while (offset < buf_sz && mcux_i3c_fifo_rx_count_get(base) == 0) {
k_usleep(10);
count++;
if (count > 500) {
ret = -ETIMEDOUT;
break;
}
}
buf[offset++] = (uint8_t)base->MRDATAB;
/*
* If timed out, we abort the transaction.
*/
if ((mcux_i3c_has_error(data) & I3C_MERRWARN_TIMEOUT_MASK) || ret) {
ret = -ETIMEDOUT;
/* for ibi, ignore timeout err if any bytes were
* read, since the code doesn't know how many
* bytes will be sent by device.
*/
if (ibi && offset) {
ret = offset;
} else {
LOG_ERR("Timeout error");
}
break;
}
}
/* If no errors, then return the number of bytes read */
if (ret > 0) {
ret = offset;
}
return ret;
}
As all of this is happening in the init of the sensor driver already, I also do not see any logs on the UART, as the logging module is not initialized at that point. However, the debugger shows that it is just idling in that loop until it breaks because of the count variable getting too high. I also verified that driver changes on I3C0 to ensure it keeps working.
So currently it looks to me that the I3C1 peripheral is plainly not receiving any bytes to the FIFO and I have no clue why. Signal on the scope looks good, and similar to the signal on I3C0. However there are some small delays between each byte on I3C0 which is not present on I3C1.
I hope you have an idea what could prevent the I3C1 peripheral from receiving a byte while the bus signal looks correct.
Best Regards,
mhummels