To distinguish like sensors using Zephyr sensor API, and device handles? #52311
Unanswered
tedhavelka
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello Zephyr Community,
I'm working on an out-of-tree Zephyr driver for the Kionix KX132 family accelerometers, and I have a couple questions and concerns about the way Zephyr DT_INST() can support the run time distinction of two or more like peripherals on a given peripheral bus, e.g. I2C and SPI.
Zephyr's documentation for DT_INST() and similarly "for each" and "for any" type device tree macros says that there's no guarantee in what order the discovered devices with matching compatible property and 'okay' status will be returned. So while I have a basic driver up and running I am at a loss for how I could call this driver and sort out which or two or more sensors to which my Zephyr application is talking.
Devices with multiple accelerometers may be unusual in the realm of Zephyr applications, but I could definitely see a device which employs, say, multiple temperature sensors of the same type, all or many sharing one bus.
In this case, when in app code I obtain a Zephyr device "handle" or structure pointer like entity, as in:
const struct device *const sensor = DEVICE_DT_GET_ANY(st_lis2dh);
...how can I determine which instance out of two or more my pointer has been assigned? With the SPI bus I could see programmatically testing the available chip select lines against the returned device handle. With I2C connected sensors, it's not clear to me how to know on the app side to which sensor instance my code's been granted a handle.
I've noticed that in some similar drivers such as STMicro's IIS2DH driver, and CircuitDojo's Air Quality Wing Zephyr Drivers sgp40 and shtc3 that the device instantiation macros near the end of the primary driver source files often invoke Zephyr's DEVICE_DT_INST_DEFINE() macro. This seems to be a professional and conventional way to carry out device instantiation. But the order of device instances is still in question in these drivers.
In my driver I'd originally, if mistakenly, employed Zephyr's DT_LABEL() macro to obtain a known device. In hindsight this meant that my device driver was coupled to a node property-value pair in a device tree overlay file. It worked in my demo app, but is not appropriate for production use or sharing readily with other developers.
DT_LABEL() is also now deprecated in Zephyr 3.2.0. For this reason I initially changed this driver code line to call DT_NODELABEL(), which evades the non-deterministic node identifier ordering of DT_INST() type Zephyr macros, but leaves the undesirable "driver to DTS overlay" coupling problem in place. Though unsure if correct or good practice, I've tried to create a Kconfig option in my KX132 driver work, to permit end users to set a node label of their choosing in Kconfig, to match what node label value they may prefer to use in their overlay file. In this scenario there would still be a coupling between overlay file and the driver. It seems however that documentation could point to such a Kconfig option.
As I attempt to implement a Kconfig, set-able string option in my driver, to allow for users of the driver to set / match nodelabel value in Kconfig to what they place in their dts overlay file, I keep encountering build time C macro paste errors. Per Kconfig syntax rules the string value in given Kconfig file needs to be double quoted. DT_ macros which involve '##' appear to place a second set of double quotes about this Kconfig symbol. I have not been able to find a way to go the other direction, and have the first pair of quotes stripped out. I've needed this to happen on line 2 of the following code snippet.
Excerpt of KX132 out-of-tree driver:
1 DEVICE_DT_DEFINE(
2 DT_NODELABEL(CONFIG_KX132_NODELABEL_VALUE), // <-- this macro expansion fails at build time
3 kx132_1211_init, // init function
4 NULL, // pm
5 &kx132_1211_data, // data
6 NULL, // config
7 POST_KERNEL, // level
8 CONFIG_SENSOR_INIT_PRIORITY, // priority
9 &kx132_api // API
10 );
Symbol CONFIG_KX132_NODELABEL_VALUE is the Kconfig string value in question.
Looking across many of Zephyr's sensor drivers, and network library drivers as well, their Kconfigs, it's clear that Kconfig is very rarely used to express string type values. Rather bool and int type values dominate. I think too there may be a C macro limitation, that there is not a way to convey a string value given that strings in macro context are always double quoted.
So in summary I ask: Is it good or poor practice to give a developer flexibility to choose their own device nodelabel value in Kconfig? If a bad idea, is there a good way on the Zephye driver, Zephyr app side to distinguish between multiple sensors of a like compatibility on a given I2C bus?
Beta Was this translation helpful? Give feedback.
All reactions