• Support
  • Zephyr DEVICE_DT_GET(), proper arguments to pass this

Hello CircuitDojo Community,

I am struggling with a Zephyr 2.6.0 device tree macro, DEVICE_DT_GET() as I work to port firmware running on a Sparkfun_Thing_Plus_nrf9160 dev’ board to a custom board. I’ve spent several hours today reviewing Zephyr Project documentation on Zephyr’s device driver API and macros. My particular situation is that I have two like sensors on the i2c2 bus peripheral of the 9160’s ARM M33. Here is a snippet from a dts .overlay file that shows the sensors in question:

36 stmicro_sensor: iis2dh@19 {
37 compatible = "st,iis2dh";
38 reg = <0x19>;
39 label = "IIS2DH";
40 };
41 stmicro_sensor_addr_18: iis2dh@18 {
42 compatible = "st,iis2dh";
43 reg = <0x18>;
44 label = "IIS2DH";
45 };

Zephyr macro DEVICE_DT_GET_ANY(st_iis2dh) returns me the first of these sensors, but Zephyr docs say that there’s no guarantee which of a like sensor the “get any” device macro will return. In my present dev tasks I could really benefit from a working macro which returns a device object pointer to the dts node of my choosing.

Is there anyone familiar with these macros, enough so to share a working syntax? I recognize that Zephyr apps often nest two or three such macros to achieve the desired end. I’ve tried a couple of those combos which documentation and sample apps from Nordic nrf sdk seemed to indicate would work. No luck so far. Spinning my wheels with build errors in the intermediate artifacts generated by west build . . ..

Thanks ahead of time for any insights into this yet cryptic realm of Zephyr and DTS.

  • Ted

Hey @tedhavelka66

Maybe try:

DEVICE_DT_GET(DT_NODELABEL(stmicro_sensor))
DEVICE_DT_GET(DT_NODELABEL(stmicro_sensor_addr_18))

or

DEVICE_DT_GET(DT_INST(0, st_iis2dh));
DEVICE_DT_GET(DT_INST(1, st_iis2dh));

Good evening Jared,

Thank you for the fast reply! These syntax examples both work in a limited way, that is, I can compile these lines themselves. But soon as I refer to the const struct device *sensor = DEVICE_DT_GET(DT_NODELABEL(stmicro_sensor_addr_18)) or = DEVICE_DT_GET(DT_INST(1, st_iis2dh));, I get a link time error:

/opt/zephyr-sdk-0.12.4/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.2.0/../../../../arm-zephyr-eabi/bin/ld: app/libapp.a(thread-iis2dh.c.obj): in functioniis2dh_thread_entry_point’:
/home/ted/projects/zephyr-based/sandbox/stage1-firmware-aws-iot-mqtt-client/src/thread-iis2dh.c:1230: undefined reference to __device_dts_ord_76'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

Strange thing here is that source code line 1230 is about one hundred eighty lines beyond the reference, and not related to a Zephyr device object pointer in any way. I get this same link time error for each pairing of device tree macros above. I also tried making the node label string shorter, but same result.

Though the custom board I’m bringing up is work related, so that I cannot share much detail of the hardware, it employs the nRF9160 for many of the same uses as are present in the Sparkfun_Thing_Plus_nrf9160 board. I’m working with sensors on the third of four i2c peripherals. GPIOs have changed in their assignments, but I’m pretty sure Nordic’s 9160 SiP Cortex-M33 supports i2c2 clock and data lines to be map-able to any of the general purpose GPIOs on P0.

In the custom board’s “primary” device tree file, whcih I named [custom_board_name]_common.dts to match the convention in Zephyr and Nordic supported boards, I’ve made sure that pins I assign to SCL and SDA of my one active I2C peripheral are not assigned to any other devices. I also made sure to enable this peripheral with:

i2c2 {
status = "okay";
};

Device Tree Source paradigm gets converted into C code sometime early during project build, but it’s not clear to me where an intermediate C source file generated by dts compiler lives. If I knew this, I could compare such a source-file-as-build-artifact between the working Sparkfun board project and the new project branch for a custom board.

Is there another configuration step I have or may be missing here, checking to see that I’ve properly configured and enabled the I2C bus on which these sensors reside?

  • Ted

ps: following the clue from that link time error message, I can see in my [app_top_dir]/build/zephyr/include/generated/devicetree_unfixed.h that the dts node of interest is the 76th node under the device tree root /:

* 74 /soc/peripheral@40000000/flash-controller@39000/flash@0/partitions/partition@fa000
* 75 /soc/peripheral@40000000/i2c@a000
* 76 /soc/peripheral@40000000/i2c@a000/iis2dh@18
* 77 /soc/peripheral@40000000/i2c@a000/iis2dh@19

Very strange that I am able to use one of the device object pointers in code, (device with reg = <19>) but not the other!

7 days later

Hello CircuitDojo Community,

Want to share a solution (two solutions) to the I2C peripheral bring up issue I posted last week here to resolve. I was having trouble initially with obtaining a Zephyr 2.6.0 device pointer via Zephyr’s macros. Jared’s reply (post 2 in this chain) helped me to obtain run time usable device pointers. But I encountered a later blocking issue with the call to Zephyr’s routine device_is_read(device_ptr).

Tracing the three or four levels of routine wrapping, this API eventually in my case was looking for two device status parameters to be either zero or ‘true’. I was passing a pointer to a sensor that is attached in DTS code to the nRF9160 i2c2 on chip peripheral. Declaring and assigning the device pointer per Jared’s suggestion DEVICE_DT_GET(DT_NODELABEL(stmicro_sensor)) was building without errors – a step forward! – but my sensor’s internal device state was failing Zephyr / Nordic HAL level initialization with the following error code in the second data structure element:

 `device_ptr->state->initialized` came back `true`,
 `device_ptr->state->init_res` came back `5`

If Zephyr RTOS is indeed using [west_workspace]/zephyr/lib/libc/minimal/include/errno.h, then error code 5 means an I/O error. After much effort in wrong directions, a more careful third review of custom board files showed that I missed copying over sparkfun_thing_plus_nrf9160.yaml. I knew about device tree source and Kconfig boards files, but I had not read enough to understand the critical import of at least this board yaml file. The key stanza here, I am guessing, is the line indicating i2c is supported.

Strange to me that there is no build time error when [custom_board_name|custom_board_namens].yaml is missing.

Assuring [custom_board].yaml is present in the Zephyr based app boards directory is solution 1. Solution 2 which I encountered is that I must, for the nRF9160 ARM Cortex-M33 application processor assure that serial like devices UART, SPI, I2C are not enabled in an overlapping way. That is, when UART0 is enabled, this precludes the option to enable I2C0 and SPI0 on-chip peripherals. Similarly if SPI3 is enabled, UART3 and I2C3 are not available as peripherals in that configuration. There are four of each bus or serial device type, but they are not all able to be used simultaneously.

Wanted to share that I’d found a solution, if not one directly asked about in the initial post. Thank you again for the help!

  • Ted
Terms and Conditions | Privacy Policy