Hello Circuit Dojo Community,

I’ve run into a strange issue in Zephyr RTOS and specifically the accelerometer sensor driver code from STMicro, located in zephyr/drivers/sensor/iis2dh/iis2dh.h. While I may not do so long term, I would like to declare an instance of iis2dh_device_config as defined in https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/sensor/iis2dh/iis2dh.h#L49.

I would like to use an instance of this structure, with its i2c member declared and available at run time. But I’m not able to get the pre-compile time test about iis2dh.h line 50 to evaluate to ‘true’.

The problem I have encountered today is that the macro DT_ANY_INST_ON_BUS_STATUS_OK(i2c) evaluates to false in my present project. Strangely, I have left prj.conf Kconfig symbols for I2C, IIS2DH and related enabled. I have also left device tree overlay for my target board, an lpcxpresso55s69_cpu0, also as these files were when I built against Zephyr 3.1.0.

( I have moved forward from Zephyr 3.1.0 to 3.2.0 for real time clock support, plus a few other changes. )

Excerpt of sensor related Kconfig enables in my prj.conf:

CONFIG_SENSOR=y
CONFIG_KX132_1211=y

# 2021-10-16 SAT . . . note this alone does not inform `cmake` where
#  to find STMicro's driver sources in sdk-nrf modules/hal/...:
CONFIG_IIS2DH=y
CONFIG_IIS2DH_RANGE=0
CONFIG_IIS2DH_ODR=0

Excerpt of DTS overlay file:

        stmicro_sensor: iis2dh@19 {
                compatible = "st,iis2dh";
                reg = <0x19>;
                label = "IIS2DH";
        };
};

Excerpt from build/zephyr/zephyr.dts:

                                compatible = "nxp,lpc-i2c";
                                reg = < 0x8a000 0x1000 >;
                                interrupts = < 0x12 0x0 >;
                                clocks = < &syscon 0x4 >;
                                status = "okay";
                                clock-frequency = < 0x186a0 >;
                                #address-cells = < 0x1 >;
                                #size-cells = < 0x0 >;
                                pinctrl-0 = < &pinmux_flexcomm4_i2c >;
                                pinctrl-names = "default";
                                mma8652fc: mma8652fc@1d {
                                        compatible = "nxp,fxos8700", "nxp,mma8652fc";
                                        reg = < 0x1d >;
                                        int1-gpios = < &gpio1 0x13 0x1 >;
                                };
                                kionix_sensor: kx132_1211@1f {
                                        compatible = "kionix,kx132_1211";
                                        reg = < 0x1f >;
                                        label = "KX132_1211";
                                };
                                stmicro_sensor: iis2dh@19 {
                                        compatible = "st,iis2dh";
                                        reg = < 0x19 >;
                                        label = "IIS2DH";
                                };
                        };

Note from this excerpt of the build artifact file zephyr.dts, device node flexcomm4 is compatible with “nxp,lpc-i2c”, and has a node property of status set to “okay”. If I read Zephyr Project documentation correctly, at https://docs.zephyrproject.org/latest/build/dts/api/api.html#c.DT_ANY_INST_ON_BUS_STATUS_OKAY, these properties seem sufficient to produce a final device tree file with a node which will pass the test on line 49 of STMicro’s iis2dh.h header file in Zephyr’s 3.2.0 release.

One final code excerpt from [custom_zephyr_app]/build/zephyr/include/generated/devicetree_generated.h, these are the final lines in this relatively long compile-time artifact:

10530  * Bus information for status "okay" nodes of each compatible
10531  */
10532 #define DT_COMPAT_nxp_lpc_i2c_BUS_i2c 1
10533 #define DT_COMPAT_nxp_fxos8700_BUS_i2c 1
10534 #define DT_COMPAT_nxp_mma8652fc_BUS_i2c 1
10535 #define DT_COMPAT_kionix_kx132_1211_BUS_i2c 1
10536 #define DT_COMPAT_st_iis2dh_BUS_i2c 1
10537 #define DT_COMPAT_zephyr_sdmmc_disk_BUS_sd 1

I’m wondering how these lines can build and appear in this intermediate file, and that macro does not detect that an IIS2DH sensor is on a valid, enabled I2C bus?

Have I overlooked some basic or other critical code in the Kconfig and or device tree parts of my project? Has anyone else encountered similar issue?

One final note: the project compiles against Zephyr 3.1.0 and runs, talking over I2C to the IIS2DH sensor on the bench there. Can also talk to a KX132 accelerometer attached to the same board, firmware, and same I2C bus. Both sensors respond, so hardware checks out as working. Problem seems to be in Zephyr build tools’ search for “any instance on I2C bus, with status of okay”.

  • Ted
7 days later

@tedhavelka66 do you have multiple I2C buses? I haven’t played with 3.2 but you should be able to look up a device based on it’s name/label. DT_ANY_INST_ON_BUS_STATUS_OK seems a bit like a wildcard..

Hi Jared,

In my project I have only one I2C bus enabled, and two sensors on this bus. I think however that I have figured out the issue. I must be very careful to place Zephyr’s DT_DRV_COMPAT before pound including STMicro’s in-tree contributed header file iis2dh.h.

I’ve posted a small Zephyr 3.2.0 app here on github, which demonstrates I2C communications with an IIS2DH: https://github.com/tedhavelka/iis2dh-minimal.

Going back and reviewing the old project I think I’d actually had DT_DRV_COMPAT appear before most of the header file includes, but I’d gotten into a habit of putting all pound includes just after the opening comment block in my source files. When I returned to “clean up” my older code I bet I moved this device tree macro to a “defines” section just after pound includes.

A couple of things I noticed while debugging, I’d copied a pre-processor check for “okay” I2C device instances on the bus, from ii2dh.h to my app sources. These tests either compile or omit SPI and I2C data members of a sensor structure for the IIS2DH. If no “okay” device instances are found on either bus, compilation succeeds but produces a mostly useless driver, for run time purposes. I added #warning stanzas to get feedback during build.

Is there a reason or convention that Zephyr developers would allow a check like this to silently fail on both bus counts? With neither bus data member compiled into the sensor structure, the sensor will never pass the call to device_is_read(sensor).

Another small nuance I learned is that I must put a line in of the form #define DT_DRV_COMPAT in order to use DT_ANY_INST_ON_BUS_STATUS_OK, but I must also #include Zephyr’s kernel.h header in order to use this test. So now there seems to be this arbitrary ordering of #defining and #including to support some of Zephyr’s device tree build time features. That seems like something that should at minimum be documented.

And to your comment yes, I think this is a wildcard type macro. So far I don’t really like these wildcard macros, they seem to put an extra level of indirection to seeing what’s going on at build time.

  • Ted

By the way, I’m actually working to update my code to call STMicro’s sensor API, a standard form of Zephyr’s sensor API, rather than call Zephyr’s I2C API directly. I had trouble a year ago getting a sequence of multi-register configurations to work using the proper sensor API. I’m going to try again, however, and I wanted first to make sure that my hacky code worked against Zephyr 3.2.0.

I would have needed to figure this out one way or another!

    tedhavelka66 yea I’ve had to create my own version of the LIS2DH12TR driver to support some more advanced operations (using FIFO etc). Doesn’t seem like there’s a lot of backing from ST to make their drivers more robust and feature complete. 😥

    Terms and Conditions | Privacy Policy