zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.9k stars 6.64k forks source link

All I2C Messages Drop on XIAO BLE Sense #56012

Closed MattMacGregor closed 1 year ago

MattMacGregor commented 1 year ago

Describe the bug

NRFX_TWIM Fails on the XIAO BLE Sense for seemingly all I2C read/writes. Currently I am only trying to read a single byte from a register over I2C on the XIAO BLE Sense. The register is on the LS6DS3TR-C, but the I2C issues seem to be unrelated to the register I am trying to read.

To Reproduce Build the fs shell sample with west for the xiao_ble_sense board. To have the i2c devices show up you first need to sent CONFIG_I2C=y.

The command I am running to build is: west build -p -b xiao_ble_sense samples/subsys/shell/fs/

Try running any I2C commands, as all messages seem to be dropping. Specifically I am trying to read the WHO_AM_I register (0x0F) on the LSM6DS3TR-C (address 0x6a), which should always read 0x6a. I am doing this with the following command: i2c read_byte i2c@40003000 0x6a 0x0f

Note: i2c@40003000 is the internal i2c bus that the LSM6DS3TR-C is on. The LSM6DS3TR-C is powered by a regulator, but the default XIAO BLE Sense device tree has it configured to turn on at boot. I did run an i2c scan on the external i2c bus and the messages also all seemed to be dropped according to log messages.

If reproduced you should see: "Failed to read from device: 0x6a"

Expected behavior It should simply read 0x6a from the register.

Logs and console output Here are the logs from a fresh boot. Only changes from a fresh west init were enabling CONFIG_I2C, enabling I2C debug level logging, and enabling NRFX debug level logging. I included the device list output in addition.

[00:00:00.295,684] <inf> NRFX_TWIM: Function: nrfx_twim_init, error code: NRFX_SUCCESS.
[00:00:00.295,715] <inf> NRFX_TWIM: Instance enabled: 0.
*** Booting Zephyr OS build zephyr-v3.3.0-1420-g9889e8e20a4f ***
uart:~$ device list
devices:
- clock@40000000 (READY)
- gpio@50000300 (READY)
- gpio@50000000 (READY)
- cdc-acm-uart (READY)
- uart@40002000 (READY)
- flash-controller@4001e000 (READY)
- i2c@40004000 (READY)
- i2c@40003000 (READY)
- spi@40023000 (READY)
- spi@4002f000 (READY)
  requires: gpio@50000000
- lsm6ds3tr-c-en (READY)
  requires: gpio@50000300
- p25q16h@0 (READY)
  requires: gpio@50000000
  requires: spi@4002f000
uart:~$ i2c read_byte i2c@40003000 6a 0f
Failed to read from device: 6a
[00:00:17.733,612] <inf> NRFX_TWIM: Transfer type: XFER_TX.
[00:00:17.733,642] <inf> NRFX_TWIM: Transfer buffers length: primary: 1, secondary: 0.
[00:00:17.733,673] <dbg> NRFX_TWIM: nrfx_twim_xfer: Primary buffer data:
[00:00:17.733,673] <dbg> NRFX_TWIM: nrfx_twim_xfer:
                                    0f                                               |.
[00:00:17.733,703] <dbg> NRFX_TWIM: nrfx_twim_xfer: Secondary buffer data:
[00:00:17.733,734] <dbg> NRFX_TWIM: nrfx_twim_xfer:
[00:00:17.733,795] <wrn> NRFX_TWIM: Function: nrfx_twim_xfer, error code: NRFX_SUCCESS.
[00:00:18.233,856] <err> i2c_nrfx_twim: Error on I2C line occurred for message 0
[00:00:18.233,886] <inf> NRFX_TWIM: Instance disabled: 0.
[00:00:18.234,008] <inf> NRFX_TWIM: Instance enabled: 0.

I believe the warning message from nrfx_twim_xfer where it says error code: NRFX_SUCCESS is a red herring. Unsure why that logging message is even in there but it logs the warning unconditionally at the end of the function, even if the return code is NRFX_SUCCESS.

Environment (please complete the following information):

Additional context I initially created this issue here: https://github.com/zephyrproject-rtos/zephyr/issues/55892 believing it to be an issue with the sensor. But the more I looked into it the more it seemed to be the nrfx_twim driver.

Some notable lines:

This is where the Zephyr driver always fails. It fails to take the completion_sync semaphore. https://github.com/zephyrproject-rtos/zephyr/blob/b0ea0c8ec6135aa5cb8d0e70ca72af2abe1f38fa/drivers/i2c/i2c_nrfx_twim.c#L155-L178

This should be released by in the event_handler here: https://github.com/zephyrproject-rtos/zephyr/blob/9889e8e20a4ffe1f442f499d51e55fa7cb73c806/drivers/i2c/i2c_nrfx_twim.c#L215-L235 But this event handler doesn't seem to be being called, as I have added logging into it and didn't get any output.

nordicjm commented 1 year ago

I'm going to guess that this board has no pull-up resistors and is assuming that the SoC enables them, but isn't set up to do that. Try adding this to the pinctrl files for the board for the i2c instance you are using for the default mode:

    bias-pull-up;
MattMacGregor commented 1 year ago

I tried adding bias-pull-up; to the i2c0_default node (left sleep pin alone) as follows but saw no change in the log output or behavior:

    i2c0_default: i2c0_default {
        group1 {
            psels = <NRF_PSEL(TWIM_SDA, 0, 7)>,
                <NRF_PSEL(TWIM_SCL, 0, 27)>;
            bias-pull-up;
        };
    };

which according to the xiao_ble_sense.dts is the assigned pin for default https://github.com/zephyrproject-rtos/zephyr/blob/d44e36d4388dc20a0f66ba6b742efb5356a25238/boards/arm/xiao_ble/xiao_ble_sense.dts#L24-L39

MattMacGregor commented 1 year ago

Issue was the same as the issue specified here. I came across this article before but dismissed it since the poster mention his I2C messages would work sometimes, but not all the times. Anyways the fix is simply:

--- a/boards/arm/xiao_ble/xiao_ble_sense.dts
+++ b/boards/arm/xiao_ble/xiao_ble_sense.dts
@@ -7,6 +7,7 @@
 /dts-v1/;
 #include "xiao_ble_common.dtsi"
 #include <zephyr/dt-bindings/i2c/i2c.h>
+#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>

 / {
        model = "Seeed XIAO BLE Sense";
@@ -14,7 +15,7 @@

        lsm6ds3tr-c-en {
                compatible = "regulator-fixed-sync", "regulator-fixed";
-               enable-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+               enable-gpios = <&gpio1 8 (NRF_GPIO_DRIVE_S0H1 | GPIO_ACTIVE_HIGH)>;
                regulator-name = "LSM6DS3TR_C_EN";
                regulator-boot-on;
                startup-delay-us = <900>;
carlescufi commented 1 year ago

Since you found a solution we will close this issue. Feel free to send a Pull Request with your suggested fix.

MattMacGregor commented 1 year ago

PR created here: https://github.com/zephyrproject-rtos/zephyr/pull/56640