-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Adxl345 refac and FIFO #97500
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
Open
Rubusch
wants to merge
42
commits into
zephyrproject-rtos:main
Choose a base branch
from
Rubusch:adxl345-fifo-v0.36
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Adxl345 refac and FIFO #97500
+1,092
−689
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add a dedicated devicetree binding to configure the interrupt line, INT1 or INT2, used for FIFO events. FIFO events can be data ready, watermark or overrun. Signed-off-by: Lothar Rubusch <[email protected]>
The FIFO is used either to buffer values in Analog's "stream mode" or to record a set of measurements triggered by a specific sensor event in Analog's "trigger mode". Since sensor event handling is not yet implemented in this driver, only stream mode is applicable. In both cases - especially in stream mode - setting the watermark to 1 is not practical. Doing so would generate an interrupt for every single measured value. If capturing every measurement in real time is the goal, Analog's "bypass mode" is more appropriate, as it avoids the additional overhead of handling interrupts like watermark or data ready. Moreover, generating frequent interrupts can easily cause overrun issues. Therefore, the minimum configurable watermark should be changed to 2. Signed-off-by: Lothar Rubusch <[email protected]>
It does not make sense to prioritize one interrupt line over the other on the ADXL345. Once interrupt events are implemented, each event can be individually mapped to either INT1 or INT2. In such configurations, both interrupt lines must be physically connected, and the mapping should be defined accordingly. Remove that comment line. Signed-off-by: Lothar Rubusch <[email protected]>
Adjustment in the driver according to the minimum change for the devicetree. Signed-off-by: Lothar Rubusch <[email protected]>
Use more consistent naming conventions. A significant number of the current defines in this driver are unused. Clarify that this define refers to a configuration register by adding the _REG suffix to its name. Signed-off-by: Lothar Rubusch <[email protected]>
Use more consistent naming conventions. A significant number of the current defines in this driver are unused. Clarify that this define refers to a configuration register by adding the _REG suffix to its name. Signed-off-by: Lothar Rubusch <[email protected]>
Use more consistent naming conventions. A significant number of the current defines in this driver are unused. Clarify that this define refers to a configuration register by adding the _REG suffix to its name. Signed-off-by: Lothar Rubusch <[email protected]>
The current name neither accurately represents its purpose nor indicates its context when viewed in debug symbols. Therefore, prefix the define with ADXL345_ and apply consistent naming for clarity. Signed-off-by: Lothar Rubusch <[email protected]>
The current name neither accurately represents its purpose nor indicates its context when viewed in debug symbols. Therefore, prefix the define with ADXL345_ and apply consistent naming for clarity. Signed-off-by: Lothar Rubusch <[email protected]>
Use a descriptive and complete name for this constant. It represents a field within the FIFO_CTL register and is part of the ADXL345 sensor driver. Signed-off-by: Lothar Rubusch <[email protected]>
Since the variable is used as a boolean, it should be defined as a bool. Signed-off-by: Lothar Rubusch <[email protected]>
The FIFO sample count is stored within a portion of an 8-bit register. Since only 8-bit configuration registers are involved, it's better to use uint8_t to avoid unnecessary mixing with uint16_t. Signed-off-by: Lothar Rubusch <[email protected]>
The function is intended to update only the selected, i.e. masked, bits. However, it doesn't currently behave as expected. Update it to function correctly, following the typical behavior of a *_assign_bits() helper. Signed-off-by: Lothar Rubusch <[email protected]>
Remove dead code. Signed-off-by: Lothar Rubusch <[email protected]>
Remove dead code. Signed-off-by: Lothar Rubusch <[email protected]>
Introduce a function to handle enabling and standby mode for measurements. According to the datasheet, placing the sensor in standby is recommended before applying certain configurations. This function will manage enabling and disabling measurement in subsequent patches. Introduce a helper function to conditionally set or clear specific masked bits. This change prepares the codebase for upcoming patches in this series. Signed-off-by: Lothar Rubusch <[email protected]>
Currently, this function performs two distinct tasks: it retrieves both "status" and "status1" i.e. the interrupt status and a field used to indicate the number of FIFO entries. In upcoming patches, these two pieces of information are not always required together. When only one is needed, the current implementation forces the use of a dummy variable as a workaround. To improve clarity and efficiency, it's better to split get_status() into two separate functions - one that retrieves the interrupt status (as the name suggests), and another that retrieves the current number of entries in the sensor's FIFO. Signed-off-by: Lothar Rubusch <[email protected]>
…tree The ADXL345 sensor provides two configurable interrupt lines that can be mapped to various sensor events such as data ready, overrun, and watermark. The previous hardcoded approach wiring only INT2, and the subsequent quickfix using INT1 with a "routed_to_int2" boolean flag, may served as a temporary solution. However, dynamically checking what is essentially a soldered (or jumpered) interrupt configuration at every function call introduces unnecessary complexity and bus traffic. The use of ternary operators for determining the active interrupt line also reduces code readability and consistency, making the interrupt mapping logic easy to overlook. This commit aims to implement support for the FIFO interrupt lines via the devicetree drdy-pin and keeps this setting in the constant driver configuration. Mapping shall happen only once at probing, thus does not need to be rechecked either. Additionally, introduce generic functions to enable interrupt lines and implements logic to determine which line is currently in use. This refactoring lays the groundwork for upcoming changes in this series. While Zephyr’s trigger mode will compile with this commit, its runtime behavior will be finalized in subsequent patches. Signed-off-by: Lothar Rubusch <[email protected]>
Cosmetical change to simplify local variable name. Signed-off-by: Lothar Rubusch <[email protected]>
Currently, the ODR supposed to be configured in the devicetree, then at the start of the adxl345_init() re-written to hardcoded ADXL345_RATE_25HZ, and at the end of the adxl345_init() set again to data->odr. Why?! Refactor sensor ODR initialization and define a reasonable default in case devicetree configuration fails. In adxl345_init(), use the ODR value already provided in the config to update the corresponding register, ensuring that only the relevant field is modified. Use FIELD_GET() on the ODR mask when setting the value, and write directly to the register both during sensor initialization and within the attribute function. This removes an unnecessary layer of indirection, allowing the setter function to be dropped entirely. Signed-off-by: Lothar Rubusch <[email protected]>
Refactor the configuration of the g-range settings. Group together the setup of g-range selection, the full_res field, implicit clearing of the justify bit, and interrupt inversion handling. Also refactor the initialization probe function accordingly. Signed-off-by: Lothar Rubusch <[email protected]>
Remove default values for FIFO mode, FIFO trigger and samples (the fifo watermark) in the driver config. Defaulting the fifo_watermark value to 0 is meaningless and potentially problematic (see ADXL345 Data Sheet (Rev. G, p. 28: "undesired operation may occur"), especially in a fixed configuration. In the best case, the sensor would immediately trigger a watermark interrupt, effectively disabling the FIFO buffer functionality. FIFO mode is derrived from available interrupt and watermark (e.g. drdy_pin) configuration. FIFO trigger is actually senseless, since it would initialize the corresponding field in the ADXL345 register. This implements Analog's trigger mode, which is not implemented here and most likely does not make sense to be implemented. Note: Analog trigger mode is not Zephyr trigger mode, pls. consult the ADXL345 datasheet for the details. Signed-off-by: Lothar Rubusch <[email protected]>
…_XYZ_REGS Rename this register for better clarity. According to the datasheet, this register corresponds to the first x-axis data byte, followed by the second x-axis byte, then the y-axis, and finally the z-axis data in a similar sequence. The sensor does not provide an option to selectively enable or disable specific axes for FIFO usage. Consequently, all three axis data must be fetched together for a single FIFO sample line. By using this register as the starting point for the fetch, it is always used to retrieve x-, y-, and z-axis samples in a single operation. Therefore, renaming it to ADXL345_REG_DATA_XYZ_REGS would be more appropriate and meaningful for the driver implementation. Signed-off-by: Lothar Rubusch <[email protected]>
Remove the adxl345_interrupt_config() function entirely. Move the initialization of interrupt-to-GPIO mapping directly into adxl345_init(). Eliminate the redundant reads of ADXL345_INT_MAP_REG and ADXL345_INT_ENABLE_REG, as the function neither used the retrieved data nor evaluated the return values. Configure the FIFO mode based on the availability of interrupt lines, selecting either FIFO_STREAM or FIFO_BYPASSED. Clean up the mode fields and add clarifying comments. Current FIFO setup behavior: A) If Zephyr’s .config includes CONFIG_ADXL345_TRIGGER or STREAM set to 'y': * If INT1 or INT2 are defined in the devicetree: use FIFO_STREAM * If no interrupt lines are defined: use FIFO_BYPASSED B) If Zephyr’s .config does not include CONFIG_ADXL345_TRIGGER or STREAM: * Interrupt lines are ignored: use FIFO_BYPASSED Note that FIFO_STREAM, FIFO_BYPASSED, and FIFO_TRIGGER are hardware operation modes of the Analog Devices ADXL345 sensor. They are unrelated to Zephyr's "STREAM" or "TRIGGER" APIs. Past versions of this driver incorrectly mixed these concepts (e.g. initializing a trigger interrupt when FIFO_STREAM mode was set). To implement FIFO_TRIGGER (where the sensor stores samples upon being triggered) or FIFO_FIFO (an alternative retention mode), refer to the ADXL345 datasheet. In most cases, STREAM and BYPASS modes are sufficient. Lastly, note that reading from the FIFO queue in FIFO_STREAM mode is currently broken in this driver; this issue is addressed in one of the subsequent patches in this series. Signed-off-by: Lothar Rubusch <[email protected]>
The FIFO configuration has to be configured based on the configuration but also on the availability of interrupt lines. Since both interrupt lines are available, this configuration cannot be done in the constant static sensor config anymore. Signed-off-by: Lothar Rubusch <[email protected]>
This event loop is unused and was likely copied from similar accelerometer drivers. Remove dead code. Signed-off-by: Lothar Rubusch <[email protected]>
Remove unused defines and masks that reference fields in the interrupt registers which are neither specified nor accessed anywhere in the code. Signed-off-by: Lothar Rubusch <[email protected]>
For the simplified fetch-and-get implementation, clean up the trigger source by removing the unnecessary re-mapping of interrupt lines left over from the old trigger logic. Allow applications to register handlers for data-ready, overrun, and watermark sensor events, as also activity. Provide a mechanism for applications to register these handlers, and alternatively offer default handling that clears and resets the FIFO after an interrupt is received. Additionally, introduce a dedicated function to flush and reset the FIFO. Signed-off-by: Lothar Rubusch <[email protected]>
In Analog Devices' FIFO modes (e.g. STREAM), samples are stored in the sensor's internal buffer, and a watermark interrupt signals when enough samples are ready. The driver should then fetch all available samples in a burst read. Currently, the driver handles interrupts but reads only a single sample each time, regardless of FIFO mode. This effectively reduces all modes (FIFO, TRIGGER, STREAM) to BYPASS behavior. Additionally, fetch operations only returned the last sample repeatedly instead of the full FIFO contents. This commit restores proper FIFO operation by converting sample storage back to an array, but fixing the fetch logic to read and return all configured FIFO entries. Signed-off-by: Lothar Rubusch <[email protected]>
Reorganize function order to simplify future refactoring. Structure the source so that generic helper functions appear first, API-level functions with RTIO calls and callbacks are placed in the middle, and consumer-facing functions are positioned at the end. Signed-off-by: Lothar Rubusch <[email protected]>
Clarify what is actually meant and handled-whether it refers to entries or samples. Remove any unnecessary handling of these variables. According to the datasheet, fifo_entries represents the number of entries required to trigger a watermark interrupt, while fifo_samples indicates the number of samples collected. Also, avoid using status1, since the ADXL345 has only a single interrupt status field. Signed-off-by: Lothar Rubusch <[email protected]>
Add a way for dynamic FIFO watermark configuration from the app when using the memory-efficient fetch-and-get implementation. Implement this consistently with the stream implementation using only the devicetree configuration of fifo_watermark. Correspondingly, update the memory configuration to allocate sufficient space for the fifo_watermark number of samples in the RTIO/stream implementation. Signed-off-by: Lothar Rubusch <[email protected]>
Eliminate the use of status1 for the RTIO/stream implementation of this driver. Using status1 here is misleading, especially when it refers to a register rather than a status field. Improve member variable naming for better clarity and consistency. Signed-off-by: Lothar Rubusch <[email protected]>
Introduce the function adxl345_sqe_done() in the RTIO/stream implementation to improve and refactor error handling in the streaming component of the ADXL345 driver. Signed-off-by: Lothar Rubusch <[email protected]>
For both stream/RTIO and fetch-and-get, provide a generic bus access interface. Implement simple caching of configuration registers to reduce bus traffic, especially when updating specific bits. This approach maintains a more generic driver implementation for common functionality and avoids redundant reimplementations that depend solely on either fetch-and-get or RTIO calls. Additionally, to efficiently update register bits without reading configuration registers that cannot be modified externally, maintain cached copies of written settings and avoid reading their values from the bus again. Signed-off-by: Lothar Rubusch <[email protected]>
For the stream/RTIO implementation, add the function adxl345_rtio_init_hdr() to initialize the stream driver header. Also, add the function adxl345_rtio_init_buffer() to allocate the buffer using rtio_sqe_rx_buf(), based on the initialized header. Signed-off-by: Lothar Rubusch <[email protected]>
For the stream/RTIO implementation, add the function adxl345_rtio_cqe_consume() to consume any remaining CQEs that have not yet been processed. Signed-off-by: Lothar Rubusch <[email protected]>
Introduce adxl345_check_streaming() in the stream/RTIO implementation to handle the standard streaming check routines. Signed-off-by: Lothar Rubusch <[email protected]>
Provide a function to flush the FIFO using both RTIO and fetch-and-get mechanisms. In both cases, the FIFO must be flushed from Analog’s FIFO_STREAM mode, which according to the datasheet, requires a complete readout of all elements in order to reset both the interrupt source register and the FIFO status register. Currently, FIFO flushing is implemented by switching to FIFO_BYPASS mode and then back again - the approach recommended by the datasheet for FIFO_TRIGGER mode. However, Analog's FIFO_TRIGGER mode is a very specific case and is typically not implemented in a generic ADXL345 drivers, including this one. Switching over to FIFO_BYPASS might not reset the interrupt register, when it comes to interrupt events. Signed-off-by: Lothar Rubusch <[email protected]>
Extends the coverage of sensor events to overrun and watermark for the stream/RTIO implementation. Signed-off-by: Lothar Rubusch <[email protected]>
…tation Restrict the RTIO stream handler to the kconfig condition. Signed-off-by: Lothar Rubusch <[email protected]>
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
area: Boards/SoCs
area: Devicetree Bindings
area: Sensors
Sensors
platform: ADI
Analog Devices, Inc.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
TL;DR
I tried to refac this driver, fix some of the FIFO related issues and introduce an approach to cover trigger/fetch&get and stream/RTIO bus access.
Long story
In my opinion, the ADXL345 driver in Zephyr still has room for improvement. Having worked on parts of the ADXL345 driver for the Linux kernel, I found it a familiar starting point when getting into Zephyr.
Current State of the ADXL345 Driver in Zephyr:
FIFO Mode Configuration
The driver currently (at least) offers setting up Analog Devices' FIFO_TRIGGER mode. However, this appears to be a misunderstanding of its purpose, especially when viewed in the context of Zephyr’s Trigger API versus a Stream/RTIO-based approach. It's important to note that Analog Devices did not define the FIFO_TRIGGER bit with Zephyr’s trigger model in mind - Analog's FIFO_TRIGGER serves a different function entirely. For typical usage in Zephyr, starting with either FIFO_STREAM or FIFO_BYPASSED modes would be more appropriate, in my opinion.
Broken FIFO Handling
FIFO functionality has been broken for several months and remains so. Currently, a FIFO watermark event is triggered once, but the driver only fetches the most recent measurement(s), rather than reading out the entire FIFO buffer. As a result, no further watermark interrupts are generated after the initial one, since the FIFO is never properly emptied.
Additional Issues
The FIFO watermark should ideally trigger at 2 stored samples, not just 1.
The current FIFO flush mechanism relies on the process described for FIFO_TRIGGER mode in the datasheet. However, when using FIFO_STREAM mode - as recommended - the FIFO should be flushed by reading out all entries manually, as per the datasheet.
Initialization in stream/RTIO mode uses direct bus writes, which makes later fetch/get operations or RTIO usage somewhat redundant. A better approach would be to consolidate these accesses under shared functions that abstract the bus type (RTIO or plain bus).
For register updates where only a few bits need changing, using an _update_bits() function with cached register values could reduce bus traffic. Since configuration registers are not expected to change externally, this kind of caching (similar to the regmap cache mechanism in Linux) could be beneficial. I'm not sure if Zephyr has a general caching mechanism like this, but it could be worth considering.
General Refactoring Needed
Overall, the driver would benefit from a thorough refactoring. There are inconsistencies in naming, instances of dead code, and unnecessarily complex implementations - likely due to the driver evolving without consistent maintenance. In my view, many of these parts are no longer robust or maintainable and need cleanup.
@MaureenHelm : I had a chat with you as the Analog Devices maintainer during OSS in Amsterdam this year. I'm not sure if you remember, anyway you had suggested that I first submit the full series as-is, so that we could later decide how to proceed—whether to split, squash, accept, or drop parts of it. Since it's generally easier to squash commits than to separate them after the fact, I tried to break the series down as much as possible from the beginning. That’s why you're now seeing over 40 commits. I’m also aware that some maintainers prefer this level of granularity.
Please let me know if this approach is excessive or if it's aligned with your expectations. All commits build successfully and pass strict checkpatch. For verification, I used my own test applications for fetch&get, device handler registration, and stream/RTIO integration, as the existing samples didn’t provide enough coverage in those areas. Does the set - all or in pieces - qualify for upstreaming? What should be squashed? What is missing? What needs to be improved? Actually I pretend writing drivers for similar accelerometers by this kind of approach. So, this is kind of a proposal to get a bit into discussion, too.
In a summary of the main topics of this series, I'd like to address:
refac: comments, simplify variable names, adjust variable types, removal of dead code, remove redundant code
refac: control measurement on/off by dedicate function and mech
refac: separate function get_status() into get_fifo_entries() and get_status() for interrupt status
refac: introduce an api to use common function calls diverting to use underlying either triggered/fetch&get or stream/RTIO implementation
refac: make interrupt lines configurable over devicetree, and remove rechecking over and over again in the running code for such constant setting
refac: simplify overly complicated ODR setup, as then also g ranges
refac: stream handler registration
fix: change minimum watermark to 2
fix: stream initialization using direct register write, while partly using RTIO
fix: stream flush FIFO performs the action documented for reset Analog Device's trigger mode (switch to FIFO BYPASS and back), in Analyg Device's FIFO STREAM mode, entries need actually to be read, to reset fifo status register and interrupt status register (would come much more into play when implementing sensor events)
fix: fetch&get using FIFO did actually fetch the recent measurements, but did not read out fifo entries
fix: rework FIFO mode setup - Analog Device's "FIFO TRIGGER" mode seems to be confused with Zephyr's "triggered" config?
fix/add: let FIFO watermark being configured also dynamically by attribute for fetch&get
fix/add: overrun and data ready handler, optionally to be overwritten in application
NB: I used AI to elaborate code comments and improve the English descriptions, simply because I'm not a native speaker. I did not use AI / Copilots or the like for sources.