-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updated Sensor API #13718
Comments
I think looking at the linux IIO subsystem and how it works would be very useful in designing a performant and usable API for both drivers and applications. Some nice things IIO does from my day exploration into it
Since each device describes its own channels with a static array of structs channel descriptors, problems relating to the current API limiting channels to 1 one of each kind is no longer a problem. I would propose that in Zephyr to obtain the performance and flexibility desired several things would need to be adapted.
So in zephyr I imagine something like the following be available in application space, I chose zio for a prefix, but it could be anything ZIO_FIFO_STATIC_INITIALIZER(my_zio_fifo, 1024, false);
struct k_poll_event events[1] = { K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_ZIO_FIFO_DATA_AVAILABLE,
K_POLL_MODE_NOTIFY_ONLY,
&my_zio_fifo)
};
int main() {
struct device *dev = device_get_binding(MY_MAGN_SENSOR);
zio_set_attribute_int(dev, ZIO_SAMPLE_RATE, 100);
zio_set_attribute_int(dev, ZIO_SAMPLE_SCALE, 4);
// these channels are statically defined and documents for whatever driver MY_MAGN_SENSOR is using, ex: lis3mdl
zio_channel_enable(dev, 0);
zio_channel_enable(dev, 1);
zio_channel_disable(dev, 2);
// at this point some default trigger source defined via DTS/K_CONFIG is enabled and handled
zio_attach_buffer(dev, &my_zio_buf);
// k_poll waits for new data to be available and our application code can deal with it as it comes in
// I imagine the fifo contains a compact representation of the sensor data, optionally with an associated
// timestamp.
// in the case of a device fifo being polled from, nothing really changes in the user interface here.
// in the case of a dma transfer happening, nothing in the user interface changes here.
int rc = k_poll(events, 1, 1000);
....
} |
Thanks for the feedback. I agree with most of the comments above personally, and I'll dig into IIO a bit on my end having never worked with it. This doesn't address the Features API idea, which I think needs to be addressed, but it definitely seems like a good starting point architecturally. |
I'm generally in favor of re-using existing architectural solutions like IIO, but I'm more in favor of starting with a clear understanding of stakeholder needs. It may be that IIO is based on assumptions that don't apply to the application domains that Zephyr's intended to support. My primary application is low-power sensors. I always know what sensor (HTU21D, BME280, SDP810, ...) is providing the readings, so I really don't care about the ability to ask for a temperature or a pressure independent of what provides the value. I want to collect at a relatively low frequency (at most 1 Hz) or on detected change, so while some DMA features might be useful if they get in my way they're not wanted. I want a single observation structure that provides a space-efficient representation of all the measurements produced by that specific device, so I know (for example) that the relative humidity I'm using was captured synchronously with the temperature I'm using, or that the three axes of acceleration were from the same observation. My application will know whether the pressure is Pa in a I want notification of relevant events: new observation, threshold change, calibration completion. At this time I want that through a callback invoked from the GPIO or alarm interrupt. I'll decide if I want to do the handoff to the application through kpoll, kwork, or simply setting a flag to be processed by the main loop, and whether I need to synchronously do some other change (such as reconfiguring the interrupt management or triggering another observation). If I need to timestamp a captured observation I'll do that myself, since I know what clock will provide the precision and range I'll want to use for the specific application. I want full control of the sensor's specific capabilities. Proper use of a CCS811 involves tracking and restoring baseline values at various points in the device and application life cycle, as well as updating stored environmental conditions. That's not going to be supported by a generic API in any usable manner. See #11993, as well as #12056 which it motivated. In short, I think Zephyr's too hung up on providing cross-platform/cross-device API. All that abstraction costs code, RAM, and power, and I believe many embedded use cases won't want to pay for it. Perhaps I'm wrong. My next/sensple branch has a primitive but functioning solution consistent with these requirements. |
I actually disagree somewhat on the Feature API, Features per device could be done via named attributes. It would require some devices providing their named attributes in a public header. In some scenarios there might be additional channels of information that can be subscribed to as well, which themselves allow the device user to take advantage of those features. Sensor Fusion example might be AHRS channels that are available but disabled by default. Enabling one, enables them all (they are tied together). The driver is responsible for reconfiguring the device with sensor fusion enabled and filling the buffer appropriately. In a similar manner gestures might be a channel of enumerated data with a timestamp given. So again additional channels of information are available from the device, like I imagine numerous TDK 9 axis sensors, which are feature rich IMU chips, might have the following channels...
Now enabling/disabling these channels provides nearly all the functionality of the chip available with a pollable buffer and optionally timestamps, by enabling or disabling those channels. Certainly there's some attributes for groups of these channels that should be mutable in some way.
Those could be attributes available on a channel or set of channels. Commonly named ones could be defined in a common header. Device specific ones would have to be exported by the driver in a different header, which is perfectly sensible. |
@pabigot I think using name, typified attributes solves most of those problems. I agree, notification of events in a convienent and compact manner is important. Doing things in a callback is ok, but in Zephyr the context of the callback matters and that's partially why there's the trigger options now at compile time for k_work or k_thread callback contexts. Providing a callback in the IRQ context leads to problems in my experience as I experimented with that. I think channels that are pollable are quite workable, would allow the kernel to sleep saving power, and provide all the potential event notifications we could want. Better still the driver is the one dealing with reading spi/i2c registers on a trigger rather than application code. You get what you want at the end rather than needing to call back in to the driver to fetch data. How that data is fetched now is partially why handling triggers in the context of a IRQ handler really isn't feasible and why the current API is not performant or timely. |
@pabigot I think this highlights why we need a two-tier approach to sensor data. There are certainly many occasions where you have full knowledge and control over the hardware you are using -- gain, integration time, etc., are known -- and memory efficiency is primary, in which case you should opt for a RAW channel and interface. I would propose that all sensor drivers, for example, should have a mandatory channel 0 that is always the raw data. But there are situations where a high level of abstraction is definitely useful, especially in networks of long-lived devices. A key problem in the embedded space is obviously parts availability, and sensors that may be available today may be EOL, or with long lead times later, meaning I need to substitute in a replacement part to ship a new batch of devices. A high level of abstraction makes it relatively easy to replace accelerometer A with model B, C, or D with very little overall impact on the end node itself, or on the logging and management systems above it. I can continue to query 'temperature' from the higher level remote management system, with little concern for the source of that temperature info at the individual device level. Both approaches are necessary and valid, but in my own case I generally am concerned with reasonably large sensor networks and collecting compatible data points that can easily be statistically analysed, etc., once a critical volumes is reached, and sensor availability is certain to change over time. The extra overhead of so much 'cross compatabiity' is very valuable to me, as is 'fast and efficient' access to raw data when I need to access something like accelerometer data at 1kHz, or something similar. |
cross compatibility and high performance are also important to me, as is the ability to reconfigure the device at run time into various modes of operation for power savings and different triggers |
This thread is really interesting to me. I am currently exploring the possibility to add FIFO capability to one of ST sensor (LSM6DSO), but there is a significant lack in the sensor APIs. I agree with all the requests listed in the @microbuilder description. I am particularly interested into following stuff:
EDIT:
EDIT2:
|
Concerning already existing code I think that linux IIO framework is good, but I also suggest taking |
@avisconti Thanks for the heads up on contexthub. It's also worth listing
This was the basis of the Adafruit unified sensor API years back, but it has definitely evolved since I first looked at it ages ago. |
@microbuilder But, yes, all that work is pretty standard now and runs on many Android based mobile phones. |
Anyway, I personally think that this new sensor API related work should be scheduled with high priority for v1.15. |
|
@microbuilder Looking at google sensorhub I see that there are more complex data structures. Data can be of folloqing types:
Embedded is used for algo data, like step_counter data, tilt/sig_motion events, gesture events and so on. Axis_one for things like environmental (pressure, temperature, humidity ...). Axis_three for accel/gyro/mag/... Each one of the 3 types has a different structure, with timestamp if it is the case. |
@avisconti Sorry that this kind of spans a couple PRs and issues at this point, but you can see some initial thoughts in code here, along with some other ideas by @BFrog earlier: #14008 (comment) I agree the current system is extremely limiting, though! |
An addition of a new header for the V2 sensors API. The API attempts to cover the most general use cases for sensors as well as include a few more advanced yet still common use cases. This API does NOT attempt to enumerate all of the sensor functionalities. It is believed that going into too much detail simply makes writing the drivers too difficult. Instead, applications requiring highly specific uses should be making direct calls to the sensor via the attached bus. The purpose of the driver is to abstract away common functionalities between sensors. If highly specific functionality is required by the application, then it is likely that a different sensor cannot be used as a drop-in replacement. It is then assumed that driver API will not be used by such an application and that the application will make more direct API calls. These direct calls can still be provided in Zephyr by the individual driver's header instead of under the common API. Fixes zephyrproject-rtos#13718 Signed-off-by: Yuval Peress <peress@google.com>
An addition of a new header for the V2 sensors API. The API attempts to cover the most general use cases for sensors as well as include a few more advanced yet still common use cases. This API does NOT attempt to enumerate all of the sensor functionalities. It is believed that going into too much detail simply makes writing the drivers too difficult. Instead, applications requiring highly specific uses should be making direct calls to the sensor via the attached bus. The purpose of the driver is to abstract away common functionalities between sensors. If highly specific functionality is required by the application, then it is likely that a different sensor cannot be used as a drop-in replacement. It is then assumed that driver API will not be used by such an application and that the application will make more direct API calls. These direct calls can still be provided in Zephyr by the individual driver's header instead of under the common API. Fixes zephyrproject-rtos#13718 Signed-off-by: Yuval Peress <peress@google.com>
@MaureenHelm @microbuilder Can you provide a status update for this task? Will this be ready for release 3.4? |
I believe much of this will have been resolved with the inclusion of #60063 while more still will come from the sensing subsystem |
I think this should remain open until #60063 is fully merged, as until then its still very much a valid thing. |
#61022 resolves the portions of this issue about multiple channels of the same type. |
API meeting (@carlescufi):
Updated Sensor API
This issue is an attempt to start identifying improvements that can be made to the current sensor API in Zephyr, with the goal of defining a new API that will eventually replace the existing one.
A more formal proposal will be made in due time, but any weaknesses in the current API can be listed here, or requirements for a new API.
The current proposals are based on existing issues and discussion during the weekly API call, and are subject to revision. They do no reflect definitive positions, rather a starting point to define a more flexible sensor architecture.
Project Management
The overall sensor API project is tracked here.
Components (Issues, PRs)
The following issues or PRs are part of the overall sensor API project, and are used for tracking purposes:
Two-tier sensor data API (raw + SI)
Both tiers must be implemented in a valid sensor driver.
General Requirements
Timestamp API
Flexible Execution Context
a single thread or limited thread count for all sensor activity.
Internal FIFO Management
Sensor Data
Channels
CHAN_ACCEL_VECT
, and may have generic catch-all versions likeCHAN_LIGHT
as well as more narrowly defined subtypes likeCHAN_LIGHT_IR
).CHAN_LIGHT
channel via theCHAN_ATTR_FREQUENCY
attribute.Attributes (Device + Channel)
A flexible, generic system is required here, though further discussion is
needed to define the initial attribute list.
Attributes will allow a high degree of flexibility, with only a minimal set of mandatory attribute required for basic drivers.
Triggers
Triggers are associate with channel attributes, and provide a mechanism to indicate how or when a channel attribute should be updated.
starting in the IRQ handler but with the blocking SPI/I2C/ADC calls
elsewhere. An slist allows this to be dynamically adjusted at runtime.
Events
Additional APIs or Requirements
Calibration API?
Logging/Storage API?
sensor data at a later date easier? Persist data in a standard format to
NVM, etc.?
Device Simulation?
While perhaps not restricted to the sensor API, a design goal should be
enabling simulation of specific sensors when HW isn't available, or specific
edge cases are difficult to reproduce on real HW (to properly test algorithms
or application code that relies on sensor data).
in a simulated environment when a generic I2C read/write request is made, the
I2C handler can redirect the request to the simulated function in the driver.
Permissions API?
Is a permissions API required/useful/relevant? Should some level of control be put in place over, for example, being able to access raw or sensitive data?
Read
,
Write
,Public
,Private
, etc.?Firmware Management?
Certain classes of sensors today have user updatable firmware. It's worth at least considering some of the implications around this, and how to update sensors on deployed devices, even if it's a very manufacturer-specific requirement.
Security Considerations
There are a number of critical security consideration to keep in mind when working with sensor data, and how it is exposed. For example, on devices with touch screens where a password may be entered, and where sensor data like accel/mag/gyro readings is publicly being streamed out, you can detect passwords based on the sensor data.
There should perhaps be some security mechanisms in situations like entering a password, where certain classes of sensors can be disabled to reduce the overall risk (disable the accel and gyro while the password screen is shown or while a keypad is being used for password or ID entry).
This fits into the permissions API idea to an extent, but is sufficiently different to merit individual consideration.
Related Issues
#14008 : WIP: Sensor API Playground
#13455 : Improvements to
drivers/sensors
for light sensors#1387 : Lack of a performant sensor API
#14245 : Sensor API channel definitions
Existing APIs to consider
sensors_event_t
sensors.hThe text was updated successfully, but these errors were encountered: