From 182bc8fdd0c70036adec17f8f8707d674ad16a10 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Thu, 26 Jun 2025 20:02:10 +0200 Subject: [PATCH 01/42] sensor: adxl345: DTS: add binding for FIFO interrupts 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 --- dts/bindings/sensor/adi,adxl345-common.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dts/bindings/sensor/adi,adxl345-common.yaml b/dts/bindings/sensor/adi,adxl345-common.yaml index 0ce7191c67a7d..a796f8e822c76 100644 --- a/dts/bindings/sensor/adi,adxl345-common.yaml +++ b/dts/bindings/sensor/adi,adxl345-common.yaml @@ -52,3 +52,12 @@ properties: The INT2 signal defaults to active high as produced by the sensor. The property value should ensure the flags properly describe the signal that is presented to the driver. + + drdy-pin: + type: int + enum: [1, 2] + description: | + This property selects the interrupt line (INT1 or INT2) used to deliver + the data ready signal, if enabled. + - 1 + - 2 From 655870d592434d6f26884488f84c4047e2889233 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Mon, 6 Oct 2025 16:48:48 +0200 Subject: [PATCH 02/42] sensor: adxl345: DTS: set minimum watermark to 2 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 --- dts/bindings/sensor/adi,adxl345-common.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/bindings/sensor/adi,adxl345-common.yaml b/dts/bindings/sensor/adi,adxl345-common.yaml index a796f8e822c76..e09d782640af1 100644 --- a/dts/bindings/sensor/adi,adxl345-common.yaml +++ b/dts/bindings/sensor/adi,adxl345-common.yaml @@ -35,7 +35,7 @@ properties: type: int description: | Specify the FIFO watermark level in frame count. - Valid range: 1 - 31 + Valid range: 2 - 31 int1-gpios: type: phandle-array From e4ce8f5e41710cf9eddb8d8a79c5a7cf46ff4ef5 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Wed, 8 Oct 2025 16:19:48 +0200 Subject: [PATCH 03/42] sensor: adxl345: DTS: adjust comment for interrupt binding 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 --- dts/bindings/sensor/adi,adxl345-common.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/dts/bindings/sensor/adi,adxl345-common.yaml b/dts/bindings/sensor/adi,adxl345-common.yaml index e09d782640af1..b56fcdd9e5c03 100644 --- a/dts/bindings/sensor/adi,adxl345-common.yaml +++ b/dts/bindings/sensor/adi,adxl345-common.yaml @@ -43,8 +43,6 @@ properties: The INT1 signal defaults to active high as produced by the sensor. The property value should ensure the flags properly describe the signal that is presented to the driver. - Either this or INT2 will be used to route interrupts. If both - are defined, then int1 is prioritized. int2-gpios: type: phandle-array From eaf2b48df09e841b7392281629ed78a8be52fc4f Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Wed, 8 Oct 2025 15:37:06 +0200 Subject: [PATCH 04/42] sensor: adxl345: set minimum watermark to 2 Adjustment in the driver according to the minimum change for the devicetree. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 4ead4f5867b2d..13ce573ef108b 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -589,10 +589,10 @@ static int adxl345_init(const struct device *dev) "Streaming requires fifo-watermark property. Please set it in the" \ "device-tree node properties"); \ BUILD_ASSERT(COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, fifo_watermark), \ - ((DT_INST_PROP(inst, fifo_watermark) > 0) && \ + ((DT_INST_PROP(inst, fifo_watermark) > 1) && \ (DT_INST_PROP(inst, fifo_watermark) < 32)), \ (true)), \ - "fifo-watermark must be between 1 and 32. Please set it in " \ + "fifo-watermark must be between 2 and 32. Please set it in " \ "the device-tree node properties"); \ \ IF_ENABLED(CONFIG_ADXL345_STREAM, (ADXL345_RTIO_DEFINE(inst))); \ From f2400ba6ebf6a03dc277bc40350ebe0cd4f52cc8 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 19:34:36 +0200 Subject: [PATCH 05/42] sensor: adxl345: rename ADXL345_INT_ENABLE to ADXL345_INT_ENABLE_REG 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 --- drivers/sensor/adi/adxl345/adxl345.c | 4 ++-- drivers/sensor/adi/adxl345/adxl345.h | 2 +- drivers/sensor/adi/adxl345/adxl345_trigger.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 13ce573ef108b..c853d90df71b0 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -400,7 +400,7 @@ static int adxl345_interrupt_config(const struct device *dev, return ret; } - ret = adxl345_reg_write_byte(dev, ADXL345_INT_ENABLE, int1); + ret = adxl345_reg_write_byte(dev, ADXL345_INT_ENABLE_REG, int1); if (ret) { return ret; } @@ -408,7 +408,7 @@ static int adxl345_interrupt_config(const struct device *dev, uint8_t samples; ret = adxl345_reg_read_byte(dev, ADXL345_INT_MAP, &samples); - ret = adxl345_reg_read_byte(dev, ADXL345_INT_ENABLE, &samples); + ret = adxl345_reg_read_byte(dev, ADXL345_INT_ENABLE_REG, &samples); #ifdef CONFIG_ADXL345_TRIGGER gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 4a7ebea3ba1b9..3e3e77940dfa6 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -66,7 +66,7 @@ #define ADXL345_MAX_FIFO_SIZE 32 -#define ADXL345_INT_ENABLE 0x2Eu +#define ADXL345_INT_ENABLE_REG 0x2E #define ADXL345_INT_MAP 0x2Fu #define ADXL345_INT_SOURCE 0x30u diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index cb7b61e361142..d576da88ad405 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -144,7 +144,7 @@ int adxl345_trigger_set(const struct device *dev, (void)adxl345_configure_fifo(dev, ADXL345_FIFO_BYPASSED, ADXL345_INT2, 0); #endif - ret = adxl345_reg_write_mask(dev, ADXL345_INT_ENABLE, int_mask, 0); + ret = adxl345_reg_write_mask(dev, ADXL345_INT_ENABLE_REG, int_mask, 0); if (ret < 0) { return ret; } @@ -170,7 +170,7 @@ int adxl345_trigger_set(const struct device *dev, return ret; } - ret = adxl345_reg_write_mask(dev, ADXL345_INT_ENABLE, int_mask, int_en); + ret = adxl345_reg_write_mask(dev, ADXL345_INT_ENABLE_REG, int_mask, int_en); if (ret < 0) { return ret; } From baf2957d7a6ca1e34f4edb1af19b366cfb72e1ec Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 19:35:28 +0200 Subject: [PATCH 06/42] sensor: adxl345: rename ADXL345_INT_MAP to ADXL345_INT_MAP_REG 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 --- drivers/sensor/adi/adxl345/adxl345.c | 4 ++-- drivers/sensor/adi/adxl345/adxl345.h | 2 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 2 +- drivers/sensor/adi/adxl345/adxl345_trigger.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index c853d90df71b0..e51f6c6d57695 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -395,7 +395,7 @@ static int adxl345_interrupt_config(const struct device *dev, int ret; const struct adxl345_dev_config *cfg = dev->config; - ret = adxl345_reg_write_byte(dev, ADXL345_INT_MAP, cfg->route_to_int2 ? int1 : ~int1); + ret = adxl345_reg_write_byte(dev, ADXL345_INT_MAP_REG, cfg->route_to_int2 ? int1 : ~int1); if (ret) { return ret; } @@ -407,7 +407,7 @@ static int adxl345_interrupt_config(const struct device *dev, uint8_t samples; - ret = adxl345_reg_read_byte(dev, ADXL345_INT_MAP, &samples); + ret = adxl345_reg_read_byte(dev, ADXL345_INT_MAP_REG, &samples); ret = adxl345_reg_read_byte(dev, ADXL345_INT_ENABLE_REG, &samples); #ifdef CONFIG_ADXL345_TRIGGER gpio_pin_interrupt_configure_dt(&cfg->interrupt, diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 3e3e77940dfa6..8949eb5cf2e0e 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -67,7 +67,7 @@ #define ADXL345_MAX_FIFO_SIZE 32 #define ADXL345_INT_ENABLE_REG 0x2E -#define ADXL345_INT_MAP 0x2Fu +#define ADXL345_INT_MAP_REG 0x2F #define ADXL345_INT_SOURCE 0x30u #define ADXL345_THRESH_ACT_REG 0x24 diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 9550efb43bdd3..05750952b8008 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -35,7 +35,7 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode uint8_t status; if (fifo_watermark_irq != data->fifo_watermark_irq) { data->fifo_watermark_irq = fifo_watermark_irq; - rc = adxl345_reg_write_mask(dev, ADXL345_INT_MAP, ADXL345_INT_MAP_WATERMARK_MSK, + rc = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, ADXL345_INT_MAP_WATERMARK_MSK, cfg_345->route_to_int2 ? int_value : ~int_value); if (rc < 0) { return; diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index d576da88ad405..7e43023e1f5f6 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -149,7 +149,7 @@ int adxl345_trigger_set(const struct device *dev, return ret; } - ret = adxl345_reg_write_mask(dev, ADXL345_INT_MAP, int_mask, + ret = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, int_mask, cfg->route_to_int2 ? int_en : ~int_en); if (ret < 0) { return ret; From 05ef6aea52528ba66a6d223c4177283c1c9f9e3f Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 19:36:05 +0200 Subject: [PATCH 07/42] sensor: adxl345: rename ADXL345_INT_SOURCE to ADXL345_INT_SOURCE_REG 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 --- drivers/sensor/adi/adxl345/adxl345.c | 2 +- drivers/sensor/adi/adxl345/adxl345.h | 2 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index e51f6c6d57695..fea4c63c763f9 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -132,7 +132,7 @@ int adxl345_get_status(const struct device *dev, uint8_t buf[2], length = 1U; int ret; - ret = adxl345_reg_read(dev, ADXL345_INT_SOURCE, buf, length); + ret = adxl345_reg_read(dev, ADXL345_INT_SOURCE_REG, buf, length); *status1 = buf[0]; ret = adxl345_reg_read(dev, ADXL345_FIFO_STATUS_REG, buf+1, length); diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 8949eb5cf2e0e..4dac76c10cd76 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -68,7 +68,7 @@ #define ADXL345_INT_ENABLE_REG 0x2E #define ADXL345_INT_MAP_REG 0x2F -#define ADXL345_INT_SOURCE 0x30u +#define ADXL345_INT_SOURCE_REG 0x30 #define ADXL345_THRESH_ACT_REG 0x24 #define ADXL345_ACT_INACT_CTL_REG 0x27 diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 05750952b8008..e8de259c7a90c 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -387,7 +387,7 @@ void adxl345_stream_irq_handler(const struct device *dev) struct rtio_sqe *write_status_addr = rtio_sqe_acquire(data->rtio_ctx); struct rtio_sqe *read_status_reg = rtio_sqe_acquire(data->rtio_ctx); struct rtio_sqe *check_status_reg = rtio_sqe_acquire(data->rtio_ctx); - uint8_t reg = ADXL345_REG_READ(ADXL345_INT_SOURCE); + uint8_t reg = ADXL345_REG_READ(ADXL345_INT_SOURCE_REG); rtio_sqe_prep_tiny_write(write_status_addr, data->iodev, RTIO_PRIO_NORM, ®, 1, NULL); write_status_addr->flags |= RTIO_SQE_TRANSACTION; From 89012863176b873d93211e58e0ec0013d04b23ca Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Thu, 24 Jul 2025 00:01:27 +0200 Subject: [PATCH 08/42] sensor: adxl345: rename SAMPLE_SIZE to ADXL345_FIFO_SAMPLE_SIZE 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 --- drivers/sensor/adi/adxl345/adxl345.h | 2 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 4dac76c10cd76..be561635303e5 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -37,7 +37,7 @@ #define ADXL345_REG_READ(x) ((x & 0xFF) | ADXL345_READ_CMD) -#define SAMPLE_SIZE 6 +#define ADXL345_FIFO_SAMPLE_SIZE 6 #define SAMPLE_MASK 0x3F #define SAMPLE_NUM 0x1F diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index e8de259c7a90c..ca163ff13fbf0 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -132,8 +132,8 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *current_sqe = data->sqe; uint16_t fifo_samples = (data->fifo_ent[0]) & SAMPLE_MASK; - size_t sample_set_size = SAMPLE_SIZE; - uint16_t fifo_bytes = fifo_samples * SAMPLE_SIZE; + size_t sample_set_size = ADXL345_FIFO_SAMPLE_SIZE; + uint16_t fifo_bytes = fifo_samples * ADXL345_FIFO_SAMPLE_SIZE; data->sqe = NULL; @@ -222,8 +222,8 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq write_fifo_addr->flags |= RTIO_SQE_TRANSACTION; rtio_sqe_prep_read(read_fifo_data, data->iodev, RTIO_PRIO_NORM, read_buf + data->fifo_total_bytes, - SAMPLE_SIZE, current_sqe); - data->fifo_total_bytes += SAMPLE_SIZE; + ADXL345_FIFO_SAMPLE_SIZE, current_sqe); + data->fifo_total_bytes += ADXL345_FIFO_SAMPLE_SIZE; if (cfg->bus_type == ADXL345_BUS_I2C) { read_fifo_data->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; } From d120c480f47a0ba89790156d8bcc3970b08260d2 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Thu, 24 Jul 2025 00:04:48 +0200 Subject: [PATCH 09/42] sensor: adxl345: rename SAMPLE_MASK to ADXL345_FIFO_SAMPLE_MSK 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 --- drivers/sensor/adi/adxl345/adxl345.h | 5 ++--- drivers/sensor/adi/adxl345/adxl345_stream.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index be561635303e5..8cffdaea6b2e8 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -38,8 +38,8 @@ #define ADXL345_REG_READ(x) ((x & 0xFF) | ADXL345_READ_CMD) #define ADXL345_FIFO_SAMPLE_SIZE 6 -#define SAMPLE_MASK 0x3F -#define SAMPLE_NUM 0x1F +#define ADXL345_FIFO_ENTRIES_MSK GENMASK(5, 0) /* FIFO status entries */ +#define ADXL345_FIFO_CTL_SAMPLES_MSK GENMASK(4, 0) /* FIFO control, samples */ /* Registers */ #define ADXL345_DEVICE_ID_REG 0x00 @@ -119,7 +119,6 @@ #define ADXL345_FIFO_CTL_MODE_MODE(x) (((x) & 0x3) << 6) #define ADXL345_FIFO_CTL_TRIGGER_MSK BIT(5) #define ADXL345_FIFO_CTL_TRIGGER_MODE(x) (((x) & 0x1) << 5) -#define ADXL345_FIFO_CTL_SAMPLES_MSK BIT(0) #define ADXL345_FIFO_CTL_SAMPLES_MODE(x) ((x) & 0x1F) #define ADXL345_ODR_MSK GENMASK(3, 0) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index ca163ff13fbf0..46a36111ac3b5 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -131,7 +131,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *current_sqe = data->sqe; - uint16_t fifo_samples = (data->fifo_ent[0]) & SAMPLE_MASK; + uint16_t fifo_samples = (data->fifo_ent[0]) & ADXL345_FIFO_ENTRIES_MSK; size_t sample_set_size = ADXL345_FIFO_SAMPLE_SIZE; uint16_t fifo_bytes = fifo_samples * ADXL345_FIFO_SAMPLE_SIZE; From d075536f14a3dc7204c75551984157b4a53fb8c7 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 19:14:00 +0200 Subject: [PATCH 10/42] sensor: adxl345: rename SAMPLE_NUM to ADXL345_FIFO_CTL_SAMPLES_MSK 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 --- drivers/sensor/adi/adxl345/adxl345.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 8cffdaea6b2e8..9e824c36cef46 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -39,7 +39,7 @@ #define ADXL345_FIFO_SAMPLE_SIZE 6 #define ADXL345_FIFO_ENTRIES_MSK GENMASK(5, 0) /* FIFO status entries */ -#define ADXL345_FIFO_CTL_SAMPLES_MSK GENMASK(4, 0) /* FIFO control, samples */ +#define ADXL345_FIFO_CTL_SAMPLES_MSK GENMASK(4, 0) /* FIFO control samples */ /* Registers */ #define ADXL345_DEVICE_ID_REG 0x00 From 6928939e1f24ca9422058c1f8c0a297ba093fe9a Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Mon, 21 Jul 2025 23:31:03 +0200 Subject: [PATCH 11/42] sensor: adxl345: change type of member is_full_res Since the variable is used as a boolean, it should be defined as a bool. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345.h | 2 +- drivers/sensor/adi/adxl345/adxl345_decoder.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 9e824c36cef46..2467d96004ca0 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -166,7 +166,7 @@ struct adxl345_dev_data { int16_t z; } samples; struct adxl345_fifo_config fifo_config; - uint8_t is_full_res; + bool is_full_res; uint8_t selected_range; enum adxl345_odr odr; #ifdef CONFIG_ADXL345_TRIGGER diff --git a/drivers/sensor/adi/adxl345/adxl345_decoder.c b/drivers/sensor/adi/adxl345/adxl345_decoder.c index aee7af41a325b..785193a0ac4cb 100644 --- a/drivers/sensor/adi/adxl345/adxl345_decoder.c +++ b/drivers/sensor/adi/adxl345/adxl345_decoder.c @@ -51,8 +51,9 @@ static const uint32_t range_to_shift[] = { [ADXL345_RANGE_16G] = 8, }; -static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, int32_t range, - uint8_t is_full_res) +static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, + int32_t range, + bool is_full_res) { if (is_full_res) { switch (range) { @@ -123,7 +124,7 @@ static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec uint8_t sample_set_size = enc_data->sample_set_size; uint64_t period_ns = accel_period_ns[enc_data->accel_odr]; - uint8_t is_full_res = enc_data->is_full_res; + bool is_full_res = enc_data->is_full_res; /* Calculate which sample is decoded. */ if ((uint8_t *)*fit >= buffer) { From b6347809c353d59f65c1c494414bd5781e2a1886 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 19:39:45 +0200 Subject: [PATCH 12/42] sensor: adxl345: change type of member fifo_samples 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 --- drivers/sensor/adi/adxl345/adxl345.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 2467d96004ca0..766f0a05027c6 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -151,7 +151,7 @@ enum adxl345_fifo_mode { struct adxl345_fifo_config { enum adxl345_fifo_mode fifo_mode; enum adxl345_fifo_trigger fifo_trigger; - uint16_t fifo_samples; + uint8_t fifo_samples; }; enum adxl345_op_mode { From c742a13defabb6eff2ce301f43124c5bffc93de7 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Mon, 21 Jul 2025 23:50:15 +0200 Subject: [PATCH 13/42] sensor: adxl345: fix function adxl345_write_mask() 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 --- drivers/sensor/adi/adxl345/adxl345.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index fea4c63c763f9..f3b14e1bd1561 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -100,20 +100,20 @@ int adxl345_reg_read_byte(const struct device *dev, uint8_t addr, uint8_t *buf) } int adxl345_reg_write_mask(const struct device *dev, - uint8_t reg_addr, - uint8_t mask, - uint8_t data) + uint8_t reg_addr, + uint8_t mask, + uint8_t data) { + uint8_t regval, tmp; int ret; - uint8_t tmp; - ret = adxl345_reg_read_byte(dev, reg_addr, &tmp); + ret = adxl345_reg_read_byte(dev, reg_addr, ®val); if (ret) { return ret; } - tmp &= ~mask; - tmp |= data; + tmp = regval & ~mask; + tmp |= data & mask; return adxl345_reg_write_byte(dev, reg_addr, tmp); } From 013925b0f6f09dcbc846adcc6f16b42d9c1f8c8d Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Mon, 21 Jul 2025 23:16:54 +0200 Subject: [PATCH 14/42] sensor: adxl345: remove unused adxl345_set_op_mode() Remove dead code. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345.c | 14 -------------- drivers/sensor/adi/adxl345/adxl345.h | 1 - 2 files changed, 15 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index f3b14e1bd1561..786fb6236e499 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -189,20 +189,6 @@ int adxl345_configure_fifo(const struct device *dev, return 0; } -/** - * Set the mode of operation. - * @param dev - The device structure. - * @param op_mode - Mode of operation. - * Accepted values: ADXL345_STANDBY - * ADXL345_MEASURE - * @return 0 in case of success, negative error code otherwise. - */ -int adxl345_set_op_mode(const struct device *dev, enum adxl345_op_mode op_mode) -{ - return adxl345_reg_write_mask(dev, ADXL345_POWER_CTL_REG, - ADXL345_POWER_CTL_MEASURE_MSK, - ADXL345_POWER_CTL_MEASURE_MODE(op_mode)); -} /** * Set Output data rate. diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 766f0a05027c6..f1b4021a94ad7 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -285,7 +285,6 @@ int adxl345_reg_write_byte(const struct device *dev, uint8_t addr, uint8_t val); int adxl345_reg_read_byte(const struct device *dev, uint8_t addr, uint8_t *buf); -int adxl345_set_op_mode(const struct device *dev, enum adxl345_op_mode op_mode); int adxl345_read_sample(const struct device *dev, struct adxl345_sample *sample); #ifdef CONFIG_SENSOR_ASYNC_API void adxl345_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); From d8a9f58577ce7c6819aedb8a05f27227bf8dbc20 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 19:43:28 +0200 Subject: [PATCH 15/42] sensor: adxl345: remove unused field op_mode Remove dead code. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index f1b4021a94ad7..c35e50f69217e 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -243,7 +243,6 @@ struct adxl345_dev_config { adxl345_bus_is_ready_fn bus_is_ready; adxl345_reg_access_fn reg_access; enum adxl345_odr odr; - bool op_mode; struct adxl345_fifo_config fifo_config; uint8_t bus_type; #ifdef CONFIG_ADXL345_TRIGGER From c17796575a51485ad7e4dce8eb6148e89450bde2 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 17:43:18 +0200 Subject: [PATCH 16/42] sensor: adxl345: control measurement by a dedicated function 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 --- drivers/sensor/adi/adxl345/adxl345.c | 24 +++++++++++++++++++----- drivers/sensor/adi/adxl345/adxl345.h | 16 +++++++--------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 786fb6236e499..2aa8f75f8e243 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -118,6 +118,12 @@ int adxl345_reg_write_mask(const struct device *dev, return adxl345_reg_write_byte(dev, reg_addr, tmp); } +int adxl345_reg_assign_bits(const struct device *dev, uint8_t reg, uint8_t mask, + bool en) +{ + return adxl345_reg_write_mask(dev, reg, mask, en ? mask : 0x00); +} + static inline bool adxl345_bus_is_ready(const struct device *dev) { const struct adxl345_dev_config *cfg = dev->config; @@ -125,6 +131,12 @@ static inline bool adxl345_bus_is_ready(const struct device *dev) return cfg->bus_is_ready(&cfg->bus); } +int adxl345_set_measure_en(const struct device *dev, bool en) +{ + return adxl345_reg_assign_bits(dev, ADXL345_POWER_CTL_REG, + ADXL345_POWER_CTL_MODE_MSK, en); +} + int adxl345_get_status(const struct device *dev, uint8_t *status1, uint16_t *fifo_entries) @@ -408,6 +420,7 @@ static int adxl345_init(const struct device *dev) int rc; struct adxl345_dev_data *data = dev->data; const struct adxl345_dev_config *cfg = dev->config; + enum adxl345_fifo_mode fifo_mode; uint8_t dev_id, full_res; if (!adxl345_bus_is_ready(dev)) { @@ -452,11 +465,7 @@ static int adxl345_init(const struct device *dev) return rc; } - rc = adxl345_reg_write_byte(dev, ADXL345_POWER_CTL_REG, ADXL345_ENABLE_MEASURE_BIT); - if (rc < 0) { - LOG_ERR("Enable measure bit failed\n"); - return -EIO; - } + fifo_mode = data->fifo_config.fifo_mode; #ifdef CONFIG_ADXL345_TRIGGER rc = adxl345_init_interrupt(dev); @@ -483,6 +492,11 @@ static int adxl345_init(const struct device *dev) uint8_t is_full_res_set = (full_res & ADXL345_DATA_FORMAT_FULL_RES) != 0; data->is_full_res = is_full_res_set; + + if (fifo_mode == ADXL345_FIFO_BYPASSED) { + return adxl345_set_measure_en(dev, true); + } + return 0; } diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index c35e50f69217e..917d21f07db6a 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -58,7 +58,7 @@ #define ADXL345_RANGE_8G 0x2 #define ADXL345_RANGE_16G 0x3 #define ADXL345_RATE_25HZ 0x8 -#define ADXL345_ENABLE_MEASURE_BIT (1 << 3) + #define ADXL345_FIFO_STREAM_MODE (1 << 7) #define ADXL345_FIFO_COUNT_MASK 0x3f #define ADXL345_COMPLEMENT_MASK(x) GENMASK(15, (x)) @@ -110,9 +110,7 @@ #define ADXL345_POWER_CTL_WAKEUP_2HZ_MODE(x) (((x) & 0x1) << 1) #define ADXL345_POWER_CTL_SLEEP BIT(2) #define ADXL345_POWER_CTL_SLEEP_MODE(x) (((x) & 0x1) << 2) -#define ADXL345_POWER_CTL_MEASURE_MSK GENMASK(3, 3) -#define ADXL345_POWER_CTL_MEASURE_MODE(x) (((x) & 0x1) << 3) -#define ADXL345_POWER_CTL_STANDBY_MODE(x) (((x) & 0x0) << 3) +#define ADXL345_POWER_CTL_MODE_MSK BIT(3) /* ADXL345_FIFO_CTL */ #define ADXL345_FIFO_CTL_MODE_MSK GENMASK(7, 6) @@ -154,11 +152,6 @@ struct adxl345_fifo_config { uint8_t fifo_samples; }; -enum adxl345_op_mode { - ADXL345_STANDBY, - ADXL345_MEASURE -}; - struct adxl345_dev_data { struct { int16_t x; @@ -251,6 +244,8 @@ struct adxl345_dev_config { #endif }; +int adxl345_set_measure_en(const struct device *dev, bool en); + void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); void adxl345_stream_irq_handler(const struct device *dev); @@ -271,6 +266,9 @@ int adxl345_reg_write_mask(const struct device *dev, uint8_t mask, uint8_t data); +int adxl345_reg_assign_bits(const struct device *dev, uint8_t reg, uint8_t mask, + bool en); + int adxl345_reg_access(const struct device *dev, uint8_t cmd, uint8_t addr, uint8_t *data, size_t len); From adcbc725838bb01218d0552428e9f83e4f275071 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 17:32:33 +0200 Subject: [PATCH 17/42] sensor: adxl345: split function get_status() 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 --- drivers/sensor/adi/adxl345/adxl345.c | 27 ++++++++++---------- drivers/sensor/adi/adxl345/adxl345.h | 4 +-- drivers/sensor/adi/adxl345/adxl345_trigger.c | 2 +- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 2aa8f75f8e243..aec8bfc5cdcf7 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -137,22 +137,22 @@ int adxl345_set_measure_en(const struct device *dev, bool en) ADXL345_POWER_CTL_MODE_MSK, en); } -int adxl345_get_status(const struct device *dev, - uint8_t *status1, - uint16_t *fifo_entries) +int adxl345_get_fifo_entries(const struct device *dev) { - uint8_t buf[2], length = 1U; - int ret; - - ret = adxl345_reg_read(dev, ADXL345_INT_SOURCE_REG, buf, length); + uint8_t regval; + int rc; - *status1 = buf[0]; - ret = adxl345_reg_read(dev, ADXL345_FIFO_STATUS_REG, buf+1, length); - if (fifo_entries) { - *fifo_entries = buf[1] & 0x3F; + rc = adxl345_reg_read_byte(dev, ADXL345_FIFO_STATUS_REG, ®val); + if (rc) { + return rc; } - return ret; + return FIELD_GET(ADXL345_FIFO_ENTRIES_MSK, regval); +} + +int adxl345_get_status(const struct device *dev, uint8_t *status) +{ + return adxl345_reg_read_byte(dev, ADXL345_INT_SOURCE_REG, status); } /** @@ -201,7 +201,6 @@ int adxl345_configure_fifo(const struct device *dev, return 0; } - /** * Set Output data rate. * @param dev - The device structure. @@ -285,7 +284,7 @@ int adxl345_read_sample(const struct device *dev, if (!IS_ENABLED(CONFIG_ADXL345_TRIGGER)) { do { - adxl345_get_status(dev, &status1, NULL); + adxl345_get_status(dev, &status1); } while (!(ADXL345_STATUS_DATA_RDY(status1))); } diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 917d21f07db6a..d3c8370ae9eba 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -250,8 +250,8 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode void adxl345_stream_irq_handler(const struct device *dev); #ifdef CONFIG_ADXL345_TRIGGER -int adxl345_get_status(const struct device *dev, - uint8_t *status, uint16_t *fifo_entries); +int adxl345_get_fifo_entries(const struct device *dev); +int adxl345_get_status(const struct device *dev, uint8_t *status); int adxl345_trigger_set(const struct device *dev, const struct sensor_trigger *trig, diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index 7e43023e1f5f6..22917c8ee602a 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -25,7 +25,7 @@ static void adxl345_thread_cb(const struct device *dev) int ret; /* Clear the status */ - if (adxl345_get_status(dev, &status1, NULL) < 0) { + if (adxl345_get_status(dev, &status1) < 0) { return; } From e6718a8a139b321c32624ab7287e9963953ce314 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 18:36:56 +0200 Subject: [PATCH 18/42] sensor: adxl345: refactor both interrupt lines configurable in devicetree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- drivers/sensor/adi/adxl345/adxl345.c | 53 ++++--- drivers/sensor/adi/adxl345/adxl345.h | 9 +- drivers/sensor/adi/adxl345/adxl345_rtio.c | 7 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 34 ++--- drivers/sensor/adi/adxl345/adxl345_trigger.c | 140 ++++++++++++++----- 5 files changed, 148 insertions(+), 95 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index aec8bfc5cdcf7..81cb98797eac9 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -390,12 +390,6 @@ static int adxl345_interrupt_config(const struct device *dev, uint8_t int1) { int ret; - const struct adxl345_dev_config *cfg = dev->config; - - ret = adxl345_reg_write_byte(dev, ADXL345_INT_MAP_REG, cfg->route_to_int2 ? int1 : ~int1); - if (ret) { - return ret; - } ret = adxl345_reg_write_byte(dev, ADXL345_INT_ENABLE_REG, int1); if (ret) { @@ -406,10 +400,7 @@ static int adxl345_interrupt_config(const struct device *dev, ret = adxl345_reg_read_byte(dev, ADXL345_INT_MAP_REG, &samples); ret = adxl345_reg_read_byte(dev, ADXL345_INT_ENABLE_REG, &samples); -#ifdef CONFIG_ADXL345_TRIGGER - gpio_pin_interrupt_configure_dt(&cfg->interrupt, - GPIO_INT_EDGE_TO_ACTIVE); -#endif + return 0; } #endif @@ -500,22 +491,19 @@ static int adxl345_init(const struct device *dev) } #ifdef CONFIG_ADXL345_TRIGGER - -#define ADXL345_CFG_IRQ(inst) \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ - ( \ - .interrupt = GPIO_DT_SPEC_INST_GET(inst, int1_gpios), \ - .route_to_int2 = false, \ - ), \ - ( \ - .interrupt = GPIO_DT_SPEC_INST_GET(inst, int2_gpios), \ - .route_to_int2 = true, \ - )) - +#define ADXL345_CFG_IRQ(inst) \ + .gpio_int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, {0}), \ + .gpio_int2 = GPIO_DT_SPEC_INST_GET_OR(inst, int2_gpios, {0}), \ + .drdy_pad = DT_INST_PROP_OR(inst, drdy_pin, -1), #else #define ADXL345_CFG_IRQ(inst) #endif /* CONFIG_ADXL345_TRIGGER */ +#define ADXL345_CONFIG_COMMON(inst) \ + IF_ENABLED(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ + DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \ + (ADXL345_CFG_IRQ(inst))) + #define ADXL345_RTIO_SPI_DEFINE(inst) \ COND_CODE_1(CONFIG_SPI_RTIO, \ (SPI_DT_IODEV_DEFINE(adxl345_iodev_##inst, DT_DRV_INST(inst), \ @@ -564,9 +552,10 @@ static int adxl345_init(const struct device *dev) .reg_access = adxl345_reg_access_spi, \ .bus_type = ADXL345_BUS_SPI, \ ADXL345_CONFIG(inst) \ - COND_CODE_1(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ - DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \ - (ADXL345_CFG_IRQ(inst)), ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ + (ADXL345_CONFIG_COMMON(inst)), ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int2_gpios), \ + (ADXL345_CONFIG_COMMON(inst)), ()) \ } #define ADXL345_CONFIG_I2C(inst) \ @@ -576,9 +565,10 @@ static int adxl345_init(const struct device *dev) .reg_access = adxl345_reg_access_i2c, \ .bus_type = ADXL345_BUS_I2C, \ ADXL345_CONFIG(inst) \ - COND_CODE_1(UTIL_OR(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ - DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \ - (ADXL345_CFG_IRQ(inst)), ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int1_gpios), \ + (ADXL345_CONFIG_COMMON(inst)), ()) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int2_gpios), \ + (ADXL345_CONFIG_COMMON(inst)), ()) \ } #define ADXL345_DEFINE(inst) \ @@ -605,6 +595,11 @@ static int adxl345_init(const struct device *dev) \ SENSOR_DEVICE_DT_INST_DEFINE(inst, adxl345_init, NULL, \ &adxl345_data_##inst, &adxl345_config_##inst, POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, &adxl345_api_funcs); + CONFIG_SENSOR_INIT_PRIORITY, &adxl345_api_funcs); \ + \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, drdy_pin), \ + (BUILD_ASSERT(DT_INST_NODE_HAS_PROP(inst, \ + CONCAT(int, DT_INST_PROP(inst, drdy_pin), _gpios)), \ + "No GPIO pin defined for ADXL345 DRDY interrupt");)) DT_INST_FOREACH_STATUS_OKAY(ADXL345_DEFINE) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index d3c8370ae9eba..aebaf30648bc1 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -163,7 +163,8 @@ struct adxl345_dev_data { uint8_t selected_range; enum adxl345_odr odr; #ifdef CONFIG_ADXL345_TRIGGER - struct gpio_callback gpio_cb; + struct gpio_callback int1_cb; + struct gpio_callback int2_cb; sensor_trigger_handler_t th_handler; const struct sensor_trigger *th_trigger; @@ -239,11 +240,13 @@ struct adxl345_dev_config { struct adxl345_fifo_config fifo_config; uint8_t bus_type; #ifdef CONFIG_ADXL345_TRIGGER - struct gpio_dt_spec interrupt; - bool route_to_int2; + struct gpio_dt_spec gpio_int1; + struct gpio_dt_spec gpio_int2; + int8_t drdy_pad; #endif }; +int adxl345_set_gpios_en(const struct device *dev, bool enable); int adxl345_set_measure_en(const struct device *dev, bool en); void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); diff --git a/drivers/sensor/adi/adxl345/adxl345_rtio.c b/drivers/sensor/adi/adxl345/adxl345_rtio.c index c8f0d682a067f..10d9eeb08cdff 100644 --- a/drivers/sensor/adi/adxl345/adxl345_rtio.c +++ b/drivers/sensor/adi/adxl345/adxl345_rtio.c @@ -52,9 +52,10 @@ void adxl345_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) __ASSERT_NO_MSG(req); rtio_work_req_submit(req, iodev_sqe, adxl345_submit_fetch); - } else if (IS_ENABLED(CONFIG_ADXL345_STREAM)) { + } +#if defined(CONFIG_ADXL345_STREAM) adxl345_submit_stream(dev, iodev_sqe); - } else { +#else rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); - } +#endif } diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 46a36111ac3b5..a75bd0bb31bab 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -16,13 +16,11 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode const struct sensor_read_config *cfg = (const struct sensor_read_config *) iodev_sqe->sqe.iodev->data; struct adxl345_dev_data *data = (struct adxl345_dev_data *)dev->data; - const struct adxl345_dev_config *cfg_345 = dev->config; uint8_t int_value = (uint8_t)~ADXL345_INT_MAP_WATERMARK_MSK; uint8_t fifo_watermark_irq = 0; - int rc = gpio_pin_interrupt_configure_dt(&cfg_345->interrupt, - GPIO_INT_DISABLE); + int rc; - if (rc < 0) { + if (adxl345_set_gpios_en(dev, false)) { return; } @@ -35,11 +33,6 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode uint8_t status; if (fifo_watermark_irq != data->fifo_watermark_irq) { data->fifo_watermark_irq = fifo_watermark_irq; - rc = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, ADXL345_INT_MAP_WATERMARK_MSK, - cfg_345->route_to_int2 ? int_value : ~int_value); - if (rc < 0) { - return; - } /* Flush the FIFO by disabling it. Save current mode for after the reset. */ enum adxl345_fifo_mode current_fifo_mode = data->fifo_config.fifo_mode; @@ -54,11 +47,10 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode rc = adxl345_reg_read_byte(dev, ADXL345_FIFO_STATUS_REG, &status); } - rc = gpio_pin_interrupt_configure_dt(&cfg_345->interrupt, - GPIO_INT_EDGE_TO_ACTIVE); - if (rc < 0) { + if (adxl345_set_gpios_en(dev, true)) { return; } + data->sqe = iodev_sqe; } @@ -67,9 +59,8 @@ static void adxl345_irq_en_cb(struct rtio *r, const struct rtio_sqe *sqe, int re ARG_UNUSED(result); const struct device *dev = (const struct device *)arg; - const struct adxl345_dev_config *cfg = dev->config; - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + adxl345_set_gpios_en(dev, true); } static void adxl345_fifo_flush_rtio(const struct device *dev) @@ -111,13 +102,12 @@ static void adxl345_fifo_read_cb(struct rtio *rtio_ctx, const struct rtio_sqe *s const struct device *dev = (const struct device *)arg; struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; - const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *iodev_sqe = sqe->userdata; if (data->fifo_samples == 0) { data->fifo_total_bytes = 0; rtio_iodev_sqe_ok(iodev_sqe, 0); - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + adxl345_set_gpios_en(dev, true); } } @@ -140,7 +130,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq /* Not inherently an underrun/overrun as we may have a buffer to fill next time */ if (current_sqe == NULL) { LOG_ERR("No pending SQE"); - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + adxl345_set_gpios_en(dev, true); return; } @@ -153,7 +143,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq if (rtio_sqe_rx_buf(current_sqe, min_read_size, ideal_read_size, &buf, &buf_len) != 0) { LOG_ERR("Failed to get buffer"); rtio_iodev_sqe_err(current_sqe, -ENOMEM); - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + adxl345_set_gpios_en(dev, true); return; } LOG_DBG("Requesting buffer [%u, %u] got %u", (unsigned int)min_read_size, @@ -265,7 +255,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq return; } - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_DISABLE); + adxl345_set_gpios_en(dev, false); struct sensor_stream_trigger *fifo_wmark_cfg = NULL; @@ -284,7 +274,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq } if (!fifo_full_irq) { - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + adxl345_set_gpios_en(dev, true); return; } @@ -324,7 +314,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq if (rtio_sqe_rx_buf(current_sqe, sizeof(struct adxl345_fifo_data), sizeof(struct adxl345_fifo_data), &buf, &buf_len) != 0) { rtio_iodev_sqe_err(current_sqe, -ENOMEM); - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + adxl345_set_gpios_en(dev, true); return; } @@ -342,7 +332,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq adxl345_fifo_flush_rtio(dev); } - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_EDGE_TO_ACTIVE); + adxl345_set_gpios_en(dev, true); return; } diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index 22917c8ee602a..8eb22bab9f78c 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -16,10 +16,37 @@ #include LOG_MODULE_DECLARE(ADXL345, CONFIG_SENSOR_LOG_LEVEL); +static int adxl345_set_int_pad_state(const struct device *dev, uint8_t pad, + bool en) +{ + const struct adxl345_dev_config *cfg = dev->config; + int state = en ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; + + /* in case of neither INT_1 nor INT_2 being defined */ + if (!cfg->gpio_int1.port && !cfg->gpio_int2.port) { + return -ENOTSUP; + } + + if (pad == 1) { + return gpio_pin_interrupt_configure_dt(&cfg->gpio_int1, state); + } else if (pad == 2) { + return gpio_pin_interrupt_configure_dt(&cfg->gpio_int2, state); + } + + /* pad may be -1, e.g. if no INT line defined in DT */ + return -EINVAL; +} + +int adxl345_set_gpios_en(const struct device *dev, bool en) +{ + const struct adxl345_dev_config *cfg = dev->config; + + return adxl345_set_int_pad_state(dev, cfg->drdy_pad, en); +} + #if defined(CONFIG_ADXL345_TRIGGER_OWN_THREAD) || defined(CONFIG_ADXL345_TRIGGER_GLOBAL_THREAD) static void adxl345_thread_cb(const struct device *dev) { - const struct adxl345_dev_config *cfg = dev->config; struct adxl345_dev_data *drv_data = dev->data; uint8_t status1; int ret; @@ -39,24 +66,39 @@ static void adxl345_thread_cb(const struct device *dev) drv_data->act_handler(dev, drv_data->act_trigger); } - ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt, - GPIO_INT_EDGE_TO_ACTIVE); + ret = adxl345_set_gpios_en(dev, true); __ASSERT(ret == 0, "Interrupt configuration failed"); } #endif -static void adxl345_gpio_callback(const struct device *dev, - struct gpio_callback *cb, uint32_t pins) +static void adxl345_int1_gpio_callback(const struct device *dev, + struct gpio_callback *cb, + uint32_t pins) { struct adxl345_dev_data *drv_data = - CONTAINER_OF(cb, struct adxl345_dev_data, gpio_cb); - const struct adxl345_dev_config *cfg = drv_data->dev->config; + CONTAINER_OF(cb, struct adxl345_dev_data, int1_cb); - gpio_pin_interrupt_configure_dt(&cfg->interrupt, GPIO_INT_DISABLE); + ARG_UNUSED(pins); - if (IS_ENABLED(CONFIG_ADXL345_STREAM)) { - adxl345_stream_irq_handler(drv_data->dev); - } + adxl345_set_int_pad_state(dev, 1, false); + +#if defined(CONFIG_ADXL345_TRIGGER_OWN_THREAD) + k_sem_give(&drv_data->gpio_sem); +#elif defined(CONFIG_ADXL345_TRIGGER_GLOBAL_THREAD) + k_work_submit(&drv_data->work); +#endif +} + +static void adxl345_int2_gpio_callback(const struct device *dev, + struct gpio_callback *cb, + uint32_t pins) +{ + struct adxl345_dev_data *drv_data = + CONTAINER_OF(cb, struct adxl345_dev_data, int2_cb); + + ARG_UNUSED(pins); + + adxl345_set_int_pad_state(dev, 2, false); #if defined(CONFIG_ADXL345_TRIGGER_OWN_THREAD) k_sem_give(&drv_data->gpio_sem); @@ -93,16 +135,14 @@ int adxl345_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { - const struct adxl345_dev_config *cfg = dev->config; struct adxl345_dev_data *drv_data = dev->data; struct adxl345_sample sample; uint8_t int_mask, int_en; uint8_t samples_count; int ret; - ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt, - GPIO_INT_DISABLE); - if (ret < 0) { + ret = adxl345_set_gpios_en(dev, false); + if (ret) { return ret; } @@ -149,12 +189,6 @@ int adxl345_trigger_set(const struct device *dev, return ret; } - ret = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, int_mask, - cfg->route_to_int2 ? int_en : ~int_en); - if (ret < 0) { - return ret; - } - /* Clear status and read sample-set to clear interrupt flag */ (void)adxl345_read_sample(dev, &sample); @@ -164,9 +198,8 @@ int adxl345_trigger_set(const struct device *dev, return ret; } - ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt, - GPIO_INT_EDGE_TO_ACTIVE); - if (ret < 0) { + ret = adxl345_set_gpios_en(dev, true); + if (ret) { return ret; } @@ -184,24 +217,23 @@ int adxl345_init_interrupt(const struct device *dev) struct adxl345_dev_data *drv_data = dev->data; int ret; - if (!gpio_is_ready_dt(&cfg->interrupt)) { - LOG_ERR("GPIO port %s not ready", cfg->interrupt.port->name); - return -EINVAL; + /* TRIGGER is set, but no INT line was defined in DT */ + if (!cfg->gpio_int1.port && !cfg->gpio_int2.port) { + return -ENOTSUP; } - ret = gpio_pin_configure_dt(&cfg->interrupt, GPIO_INPUT); - if (ret < 0) { - return ret; + if (cfg->gpio_int1.port) { + if (!gpio_is_ready_dt(&cfg->gpio_int1)) { + LOG_ERR("INT_1 line defined, but not ready"); + return -ENODEV; + } } - gpio_init_callback(&drv_data->gpio_cb, - adxl345_gpio_callback, - BIT(cfg->interrupt.pin)); - - ret = gpio_add_callback(cfg->interrupt.port, &drv_data->gpio_cb); - if (ret < 0) { - LOG_ERR("Failed to set gpio callback!"); - return ret; + if (cfg->gpio_int2.port) { + if (!gpio_is_ready_dt(&cfg->gpio_int2)) { + LOG_ERR("INT_2 line defined, but not ready"); + return -ENODEV; + } } drv_data->dev = dev; @@ -220,5 +252,37 @@ int adxl345_init_interrupt(const struct device *dev) drv_data->work.handler = adxl345_work_cb; #endif + if (cfg->gpio_int1.port) { + ret = gpio_pin_configure_dt(&cfg->gpio_int1, GPIO_INPUT); + if (ret) { + return ret; + } + + gpio_init_callback(&drv_data->int1_cb, adxl345_int1_gpio_callback, + BIT(cfg->gpio_int1.pin)); + + ret = gpio_add_callback(cfg->gpio_int1.port, &drv_data->int1_cb); + if (ret) { + LOG_ERR("Failed to set INT_1 gpio callback!"); + return -EIO; + } + } + + if (cfg->gpio_int2.port) { + ret = gpio_pin_configure_dt(&cfg->gpio_int2, GPIO_INPUT); + if (ret < 0) { + return ret; + } + + gpio_init_callback(&drv_data->int2_cb, adxl345_int2_gpio_callback, + BIT(cfg->gpio_int2.pin)); + + ret = gpio_add_callback(cfg->gpio_int2.port, &drv_data->int2_cb); + if (ret < 0) { + LOG_ERR("Failed to set INT_2 gpio callback!"); + return -EIO; + } + } + return 0; } From da743391d27a6d61f3ce72e964acabee8454ac80 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Fri, 10 Oct 2025 19:06:17 +0200 Subject: [PATCH 19/42] sensor: adxl345: rename local status1 to status Cosmetical change to simplify local variable name. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345_trigger.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index 8eb22bab9f78c..20873f70b77de 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -48,21 +48,21 @@ int adxl345_set_gpios_en(const struct device *dev, bool en) static void adxl345_thread_cb(const struct device *dev) { struct adxl345_dev_data *drv_data = dev->data; - uint8_t status1; + uint8_t status; int ret; /* Clear the status */ - if (adxl345_get_status(dev, &status1) < 0) { + if (adxl345_get_status(dev, &status) < 0) { return; } if ((drv_data->drdy_handler != NULL) && - ADXL345_STATUS_DATA_RDY(status1)) { + ADXL345_STATUS_DATA_RDY(status)) { drv_data->drdy_handler(dev, drv_data->drdy_trigger); } if ((drv_data->act_handler != NULL) && - ADXL345_STATUS_ACTIVITY(status1)) { + ADXL345_STATUS_ACTIVITY(status)) { drv_data->act_handler(dev, drv_data->act_trigger); } From 012004eeb649b35a9526bbe57dc29e0917b0200f Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 17:11:44 +0200 Subject: [PATCH 20/42] sensor: adxl345: refactor ODR initialization 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 --- drivers/sensor/adi/adxl345/adxl345.c | 47 +++++++--------------------- drivers/sensor/adi/adxl345/adxl345.h | 4 +-- 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 81cb98797eac9..675bcd279db58 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -201,25 +201,6 @@ int adxl345_configure_fifo(const struct device *dev, return 0; } -/** - * Set Output data rate. - * @param dev - The device structure. - * @param odr - Output data rate. - * Accepted values: ADXL345_ODR_12_5HZ - * ADXL345_ODR_25HZ - * ADXL345_ODR_50HZ - * ADXL345_ODR_100HZ - * ADXL345_ODR_200HZ - * ADXL345_ODR_400HZ - * @return 0 in case of success, negative error code otherwise. - */ -static int adxl345_set_odr(const struct device *dev, enum adxl345_odr odr) -{ - return adxl345_reg_write_mask(dev, ADXL345_RATE_REG, - ADXL345_ODR_MSK, - ADXL345_ODR_MODE(odr)); -} - static int adxl345_attr_set_odr(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, @@ -251,13 +232,10 @@ static int adxl345_attr_set_odr(const struct device *dev, return -EINVAL; } - int ret = adxl345_set_odr(dev, odr); - - if (ret == 0) { - data->odr = odr; - } + data->odr = odr; - return ret; + return adxl345_reg_write_mask(dev, ADXL345_RATE_REG, ADXL345_ODR_MSK, + ADXL345_ODR_MODE(odr)); } static int adxl345_attr_set(const struct device *dev, @@ -440,12 +418,6 @@ static int adxl345_init(const struct device *dev) data->selected_range = ADXL345_RANGE_8G; - rc = adxl345_reg_write_byte(dev, ADXL345_RATE_REG, ADXL345_RATE_25HZ); - if (rc < 0) { - LOG_ERR("Rate setting failed\n"); - return -EIO; - } - rc = adxl345_configure_fifo(dev, IS_ENABLED(CONFIG_ADXL345_STREAM) ? ADXL345_FIFO_STREAMED : ADXL345_FIFO_BYPASSED, @@ -455,6 +427,13 @@ static int adxl345_init(const struct device *dev) return rc; } + rc = adxl345_reg_write_mask(dev, ADXL345_RATE_REG, ADXL345_ODR_MSK, + ADXL345_ODR_MODE(cfg->odr)); + if (rc) { + LOG_ERR("Rate setting failed\n"); + return rc; + } + fifo_mode = data->fifo_config.fifo_mode; #ifdef CONFIG_ADXL345_TRIGGER @@ -464,10 +443,6 @@ static int adxl345_init(const struct device *dev) return -EIO; } - rc = adxl345_set_odr(dev, cfg->odr); - if (rc) { - return rc; - } rc = adxl345_interrupt_config(dev, ADXL345_INT_MAP_WATERMARK_MSK); if (rc) { return rc; @@ -536,7 +511,7 @@ static int adxl345_init(const struct device *dev) 2 * DT_INST_PROP(inst, fifo_watermark) + 2); #define ADXL345_CONFIG(inst) \ - .odr = DT_INST_PROP(inst, odr), \ + .odr = DT_INST_PROP_OR(inst, odr, ADXL345_RATE_25HZ), \ .fifo_config.fifo_mode = ADXL345_FIFO_STREAMED, \ .fifo_config.fifo_trigger = ADXL345_INT2, \ .fifo_config.fifo_samples = DT_INST_PROP_OR(inst, fifo_watermark, 0), diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index aebaf30648bc1..acde7ebe28aa8 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -119,8 +119,8 @@ #define ADXL345_FIFO_CTL_TRIGGER_MODE(x) (((x) & 0x1) << 5) #define ADXL345_FIFO_CTL_SAMPLES_MODE(x) ((x) & 0x1F) -#define ADXL345_ODR_MSK GENMASK(3, 0) -#define ADXL345_ODR_MODE(x) ((x) & 0xF) +#define ADXL345_ODR_MSK GENMASK(3, 0) +#define ADXL345_ODR_MODE(x) FIELD_GET(ADXL345_ODR_MSK, x) #define ADXL345_BUS_I2C 0 #define ADXL345_BUS_SPI 1 From a5248fb7b3645f4f084570a6ba3dc02c02bab263 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 16:20:28 +0200 Subject: [PATCH 21/42] sensor: adxl345: init the ADXL345_DATA_FORMAT_REG register 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 --- drivers/sensor/adi/adxl345/adxl345.c | 28 ++++++++++++-------- drivers/sensor/adi/adxl345/adxl345.h | 27 ++++++++++++++----- drivers/sensor/adi/adxl345/adxl345_decoder.c | 15 ++++++----- 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 675bcd279db58..5ad8e18591a9d 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -385,11 +385,12 @@ static int adxl345_interrupt_config(const struct device *dev, static int adxl345_init(const struct device *dev) { - int rc; struct adxl345_dev_data *data = dev->data; const struct adxl345_dev_config *cfg = dev->config; enum adxl345_fifo_mode fifo_mode; - uint8_t dev_id, full_res; + uint8_t dev_id; + uint8_t regval; + int rc; if (!adxl345_bus_is_ready(dev)) { LOG_ERR("bus not ready"); @@ -409,15 +410,25 @@ static int adxl345_init(const struct device *dev) return -EIO; } #endif - - rc = adxl345_reg_write_byte(dev, ADXL345_DATA_FORMAT_REG, ADXL345_RANGE_8G); + data->selected_range = ADXL345_RANGE_8G; + data->is_full_res = true; + + /* + * Reset the following sensor fields (in case of warm starts) + * - turn off measurements as MSB values, use left justified vals + * - configure full resolution accordingly + * - turn off interrupt inversion + * - turn off 3-wire SPI + * - turn off self test mode + */ + regval = (data->is_full_res ? ADXL345_DATA_FORMAT_FULL_RES : 0x00); + regval |= adxl345_range_init[data->selected_range]; + rc = adxl345_reg_write_byte(dev, ADXL345_DATA_FORMAT_REG, regval); if (rc < 0) { LOG_ERR("Data format set failed\n"); return -EIO; } - data->selected_range = ADXL345_RANGE_8G; - rc = adxl345_configure_fifo(dev, IS_ENABLED(CONFIG_ADXL345_STREAM) ? ADXL345_FIFO_STREAMED : ADXL345_FIFO_BYPASSED, @@ -453,11 +464,6 @@ static int adxl345_init(const struct device *dev) } #endif - rc = adxl345_reg_read_byte(dev, ADXL345_DATA_FORMAT_REG, &full_res); - uint8_t is_full_res_set = (full_res & ADXL345_DATA_FORMAT_FULL_RES) != 0; - - data->is_full_res = is_full_res_set; - if (fifo_mode == ADXL345_FIFO_BYPASSED) { return adxl345_set_measure_en(dev, true); } diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index acde7ebe28aa8..637dcdc6d112c 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -53,10 +53,25 @@ #define ADXL345_PART_ID 0xe5 -#define ADXL345_RANGE_2G 0x0 -#define ADXL345_RANGE_4G 0x1 -#define ADXL345_RANGE_8G 0x2 -#define ADXL345_RANGE_16G 0x3 +#define ADXL345_DATA_FORMAT_RANGE_2G 0x0 +#define ADXL345_DATA_FORMAT_RANGE_4G 0x1 +#define ADXL345_DATA_FORMAT_RANGE_8G 0x2 +#define ADXL345_DATA_FORMAT_RANGE_16G 0x3 + +enum adxl345_range { + ADXL345_RANGE_2G, + ADXL345_RANGE_4G, + ADXL345_RANGE_8G, + ADXL345_RANGE_16G, +}; + +static const uint8_t adxl345_range_init[] = { + [ADXL345_RANGE_2G] = ADXL345_DATA_FORMAT_RANGE_2G, + [ADXL345_RANGE_4G] = ADXL345_DATA_FORMAT_RANGE_4G, + [ADXL345_RANGE_8G] = ADXL345_DATA_FORMAT_RANGE_8G, + [ADXL345_RANGE_16G] = ADXL345_DATA_FORMAT_RANGE_16G, +}; + #define ADXL345_RATE_25HZ 0x8 #define ADXL345_FIFO_STREAM_MODE (1 << 7) @@ -160,7 +175,7 @@ struct adxl345_dev_data { } samples; struct adxl345_fifo_config fifo_config; bool is_full_res; - uint8_t selected_range; + enum adxl345_range selected_range; enum adxl345_odr odr; #ifdef CONFIG_ADXL345_TRIGGER struct gpio_callback int1_cb; @@ -199,7 +214,7 @@ struct adxl345_dev_data { struct adxl345_fifo_data { uint8_t is_fifo: 1; uint8_t is_full_res: 1; - uint8_t selected_range: 2; + enum adxl345_range selected_range: 2; uint8_t sample_set_size: 4; uint8_t int_status; uint16_t accel_odr: 4; diff --git a/drivers/sensor/adi/adxl345/adxl345_decoder.c b/drivers/sensor/adi/adxl345/adxl345_decoder.c index 785193a0ac4cb..fbbd8fb6e8df6 100644 --- a/drivers/sensor/adi/adxl345/adxl345_decoder.c +++ b/drivers/sensor/adi/adxl345/adxl345_decoder.c @@ -52,7 +52,7 @@ static const uint32_t range_to_shift[] = { }; static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, - int32_t range, + enum adxl345_range range, bool is_full_res) { if (is_full_res) { @@ -114,11 +114,12 @@ static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec } struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)data_out; + enum adxl345_range selected_range = enc_data->selected_range; memset(data, 0, sizeof(struct sensor_three_axis_data)); data->header.base_timestamp_ns = enc_data->timestamp; data->header.reading_count = 1; - data->shift = range_to_shift[enc_data->selected_range]; + data->shift = range_to_shift[selected_range]; buffer += sizeof(struct adxl345_fifo_data); @@ -148,15 +149,15 @@ static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec uint8_t buff_offset = 0; adxl345_accel_convert_q31(&data->readings[count].x, *(int16_t *)buffer, - enc_data->selected_range, is_full_res); + selected_range, is_full_res); buff_offset = 2; adxl345_accel_convert_q31(&data->readings[count].y, - *(int16_t *)(buffer + buff_offset), - enc_data->selected_range, is_full_res); + *(int16_t *)(buffer + buff_offset), + selected_range, is_full_res); buff_offset += 2; adxl345_accel_convert_q31(&data->readings[count].z, - *(int16_t *)(buffer + buff_offset), - enc_data->selected_range, is_full_res); + *(int16_t *)(buffer + buff_offset), + selected_range, is_full_res); break; default: return -ENOTSUP; From 917e51ead787a71709416024b8555fcd1e93d36a Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Fri, 25 Jul 2025 19:30:51 +0200 Subject: [PATCH 22/42] sensor: adxl345: fix FIFO default configuration 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 --- drivers/sensor/adi/adxl345/adxl345.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 5ad8e18591a9d..5d9bf11a1ed0a 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -517,10 +517,7 @@ static int adxl345_init(const struct device *dev) 2 * DT_INST_PROP(inst, fifo_watermark) + 2); #define ADXL345_CONFIG(inst) \ - .odr = DT_INST_PROP_OR(inst, odr, ADXL345_RATE_25HZ), \ - .fifo_config.fifo_mode = ADXL345_FIFO_STREAMED, \ - .fifo_config.fifo_trigger = ADXL345_INT2, \ - .fifo_config.fifo_samples = DT_INST_PROP_OR(inst, fifo_watermark, 0), + .odr = DT_INST_PROP_OR(inst, odr, ADXL345_RATE_25HZ), #define ADXL345_CONFIG_SPI(inst) \ { \ From 4b6e074715746bc10fd69683ca1ee980931f9e49 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Sun, 27 Jul 2025 16:05:11 +0200 Subject: [PATCH 23/42] sensor: adxl345: introduce ADXL345_REG_DATA_XYZ_REGS Rename ADXL345_X_AXIS_DATA_0_REG to ADXL345_REG_DATA_XYZ_REGS for better clarity. This sensor is to be read always in block read over all directions, thus naming individual axis fields does actually not make sense. 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 --- drivers/sensor/adi/adxl345/adxl345.c | 4 ++-- drivers/sensor/adi/adxl345/adxl345.h | 2 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 5d9bf11a1ed0a..ffce69e3719a7 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -266,8 +266,8 @@ int adxl345_read_sample(const struct device *dev, } while (!(ADXL345_STATUS_DATA_RDY(status1))); } - int rc = adxl345_reg_read(dev, ADXL345_X_AXIS_DATA_0_REG, axis_data, 6); - + int rc = adxl345_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, + axis_data, ADXL345_FIFO_SAMPLE_SIZE); if (rc < 0) { LOG_ERR("Samples read failed with rc=%d\n", rc); return rc; diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 637dcdc6d112c..76016e6e2db52 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -47,7 +47,7 @@ #define ADXL345_POWER_CTL_REG 0x2d #define ADXL345_DATA_FORMAT_REG 0x31 #define ADXL345_DATA_FORMAT_FULL_RES 0x08 -#define ADXL345_X_AXIS_DATA_0_REG 0x32 +#define ADXL345_REG_DATA_XYZ_REGS 0x32 #define ADXL345_FIFO_CTL_REG 0x38 #define ADXL345_FIFO_STATUS_REG 0x39 diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index a75bd0bb31bab..5740872242a1f 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -204,7 +204,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq struct rtio_sqe *read_fifo_data = rtio_sqe_acquire(data->rtio_ctx); data->fifo_samples--; - const uint8_t reg_addr = ADXL345_REG_READ(ADXL345_X_AXIS_DATA_0_REG) + const uint8_t reg_addr = ADXL345_REG_READ(ADXL345_REG_DATA_XYZ_REGS) | ADXL345_MULTIBYTE_FLAG; rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, ®_addr, From 8014790ff6d2150b33c8840d3749b22f5c305050 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 17:35:47 +0200 Subject: [PATCH 24/42] sensor: adxl345: rework FIFO mode and interrupt initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- drivers/sensor/adi/adxl345/adxl345.c | 152 ++++++++++---------- drivers/sensor/adi/adxl345/adxl345.h | 42 ++++-- drivers/sensor/adi/adxl345/adxl345_stream.c | 12 +- 3 files changed, 111 insertions(+), 95 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index ffce69e3719a7..c5eb8793c92c5 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -17,6 +17,12 @@ LOG_MODULE_REGISTER(ADXL345, CONFIG_SENSOR_LOG_LEVEL); +static const uint8_t adxl345_fifo_ctl_trigger_init[] = { + [ADXL345_FIFO_CTL_TRIGGER_INT1] = ADXL345_INT1, + [ADXL345_FIFO_CTL_TRIGGER_INT2] = ADXL345_INT2, + [ADXL345_FIFO_CTL_TRIGGER_UNSET] = ADXL345_INT_UNSET, +}; + #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) static bool adxl345_bus_is_ready_i2c(const union adxl345_bus *bus) { @@ -155,50 +161,69 @@ int adxl345_get_status(const struct device *dev, uint8_t *status) return adxl345_reg_read_byte(dev, ADXL345_INT_SOURCE_REG, status); } +int adxl345_flush_fifo(const struct device *dev) +{ +#ifdef CONFIG_ADXL345_TRIGGER + int8_t sample_number; + uint8_t regval; + int rc; + + rc = adxl345_set_measure_en(dev, false); + if (rc) { + return rc; + } + + sample_number = adxl345_get_fifo_entries(dev); + while (sample_number >= 0) { /* Read FIFO entries + 1 sample lines */ + rc = adxl345_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, + ®val, ADXL345_FIFO_SAMPLE_SIZE); + if (rc) { + return rc; + } + + sample_number--; + } +#endif /* CONFIG_ADXL345_TRIGGER */ + + return adxl345_set_measure_en(dev, true); +} + /** * Configure the operating parameters for the FIFO. * @param dev - The device structure. - * @param mode - FIFO Mode. Specifies FIFO operating mode. - * Accepted values: ADXL345_FIFO_BYPASSED - * ADXL345_FIFO_STREAMED - * ADXL345_FIFO_TRIGGERED - * ADXL345_FIFO_OLD_SAVED - * @param trigger - FIFO trigger. Links trigger event to appropriate INT. - * Accepted values: ADXL345_INT1 - * ADXL345_INT2 + * @param mode - FIFO Mode. Specifies FIFO operating mode, currently either + * ADXL345_FIFO_BYPASSED or ADXL345_FIFO_STREAMED. + * @param trigger - Currently ignored, thus set to ADXL345_INT_UNSET. * @param fifo_samples - FIFO Samples. Watermark number of FIFO samples that * triggers a FIFO_FULL condition when reached. * Values range from 0 to 32. - + * + * Note: The terms "trigger", "ADXL345_FIFO_TRIGGERED", "ADXL345_FIFO_STREAMED" + * and "ADXL345_FIFO_BYPASSED" in this context are specific to the ADXL345 + * sensor and are defined in its datasheet. These terms are unrelated to + * Zephyr's TRIGGER or STREAM APIs. + * * @return 0 in case of success, negative error code otherwise. */ int adxl345_configure_fifo(const struct device *dev, enum adxl345_fifo_mode mode, enum adxl345_fifo_trigger trigger, - uint16_t fifo_samples) + uint8_t fifo_samples) { struct adxl345_dev_data *data = dev->data; uint8_t fifo_config; - int ret; - - if (fifo_samples > 32) { - return -EINVAL; - } - - fifo_config = (ADXL345_FIFO_CTL_TRIGGER_MODE(trigger) | - ADXL345_FIFO_CTL_MODE_MODE(mode) | - ADXL345_FIFO_CTL_SAMPLES_MODE(fifo_samples)); - ret = adxl345_reg_write_byte(dev, ADXL345_FIFO_CTL_REG, fifo_config); - if (ret) { - return ret; - } + fifo_config = adxl345_fifo_ctl_mode_init[mode]; + data->fifo_config.fifo_mode = mode; + fifo_config |= adxl345_fifo_ctl_trigger_init[trigger]; data->fifo_config.fifo_trigger = trigger; - data->fifo_config.fifo_mode = mode; + + fifo_samples = MIN(fifo_samples, ADXL345_FIFO_CTL_SAMPLES_MSK); + fifo_config |= fifo_samples; data->fifo_config.fifo_samples = fifo_samples; - return 0; + return adxl345_reg_write_byte(dev, ADXL345_FIFO_CTL_REG, fifo_config); } static int adxl345_attr_set_odr(const struct device *dev, @@ -357,38 +382,13 @@ static DEVICE_API(sensor, adxl345_api_funcs) = { #endif }; -#ifdef CONFIG_ADXL345_TRIGGER -/** - * Configure the INT1 and INT2 interrupt pins. - * @param dev - The device structure. - * @param int1 - INT1 interrupt pins. - * @return 0 in case of success, negative error code otherwise. - */ -static int adxl345_interrupt_config(const struct device *dev, - uint8_t int1) -{ - int ret; - - ret = adxl345_reg_write_byte(dev, ADXL345_INT_ENABLE_REG, int1); - if (ret) { - return ret; - } - - uint8_t samples; - - ret = adxl345_reg_read_byte(dev, ADXL345_INT_MAP_REG, &samples); - ret = adxl345_reg_read_byte(dev, ADXL345_INT_ENABLE_REG, &samples); - - return 0; -} -#endif - static int adxl345_init(const struct device *dev) { struct adxl345_dev_data *data = dev->data; const struct adxl345_dev_config *cfg = dev->config; enum adxl345_fifo_mode fifo_mode; uint8_t dev_id; + uint8_t int_en; uint8_t regval; int rc; @@ -429,15 +429,6 @@ static int adxl345_init(const struct device *dev) return -EIO; } - rc = adxl345_configure_fifo(dev, - IS_ENABLED(CONFIG_ADXL345_STREAM) ? ADXL345_FIFO_STREAMED : - ADXL345_FIFO_BYPASSED, - ADXL345_INT2, - cfg->fifo_config.fifo_samples); - if (rc) { - return rc; - } - rc = adxl345_reg_write_mask(dev, ADXL345_RATE_REG, ADXL345_ODR_MSK, ADXL345_ODR_MODE(cfg->odr)); if (rc) { @@ -445,24 +436,37 @@ static int adxl345_init(const struct device *dev) return rc; } - fifo_mode = data->fifo_config.fifo_mode; - -#ifdef CONFIG_ADXL345_TRIGGER - rc = adxl345_init_interrupt(dev); - if (rc < 0) { - LOG_ERR("Failed to initialize interrupt!"); - return -EIO; - } - - rc = adxl345_interrupt_config(dev, ADXL345_INT_MAP_WATERMARK_MSK); - if (rc) { - return rc; + fifo_mode = ADXL345_FIFO_BYPASSED; + int_en = 0x00; +#if defined(CONFIG_ADXL345_TRIGGER) || defined(CONFIG_ADXL345_STREAM) + if (adxl345_init_interrupt(dev)) { + LOG_INF("No IRQ lines specified, fallback to FIFO BYPASSED"); + fifo_mode = ADXL345_FIFO_BYPASSED; + } else { + LOG_INF("Set FIFO STREAMED mode"); + fifo_mode = ADXL345_FIFO_STREAMED; + + /* + * Currently, map all interrupts to the (same) gpio line + * configured in the device tree. This is usually sufficient, + * also since not every hardware will have both gpio lines + * soldered. Anyway, for individual interrupt mapping, set up + * DTB bindings. + */ + uint8_t int_mask = UCHAR_MAX; + + rc = adxl345_reg_assign_bits(dev, ADXL345_INT_MAP_REG, int_mask, + (cfg->drdy_pad == 2)); + if (rc) { + return rc; + } } - rc = adxl345_interrupt_config(dev, ADXL345_INT_MAP_ACT_MSK); +#endif + rc = adxl345_configure_fifo(dev, fifo_mode, ADXL345_INT_UNSET, + ADXL345_FIFO_CTL_SAMPLES_MSK); if (rc) { return rc; } -#endif if (fifo_mode == ADXL345_FIFO_BYPASSED) { return adxl345_set_measure_en(dev, true); diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 76016e6e2db52..e0a0f09996650 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -128,11 +128,25 @@ static const uint8_t adxl345_range_init[] = { #define ADXL345_POWER_CTL_MODE_MSK BIT(3) /* ADXL345_FIFO_CTL */ -#define ADXL345_FIFO_CTL_MODE_MSK GENMASK(7, 6) -#define ADXL345_FIFO_CTL_MODE_MODE(x) (((x) & 0x3) << 6) -#define ADXL345_FIFO_CTL_TRIGGER_MSK BIT(5) -#define ADXL345_FIFO_CTL_TRIGGER_MODE(x) (((x) & 0x1) << 5) -#define ADXL345_FIFO_CTL_SAMPLES_MODE(x) ((x) & 0x1F) +#define ADXL345_FIFO_CTL_MODE_MSK GENMASK(7, 6) +#define ADXL345_FIFO_CTL_MODE_BYPASSED 0x0 +#define ADXL345_FIFO_CTL_MODE_OLD_SAVED 0x40 +#define ADXL345_FIFO_CTL_MODE_STREAMED 0x80 +#define ADXL345_FIFO_CTL_MODE_TRIGGERED 0xc0 + +enum adxl345_fifo_mode { + ADXL345_FIFO_BYPASSED, + ADXL345_FIFO_OLD_SAVED, + ADXL345_FIFO_STREAMED, + ADXL345_FIFO_TRIGGERED, +}; + +static const uint8_t adxl345_fifo_ctl_mode_init[] = { + [ADXL345_FIFO_BYPASSED] = ADXL345_FIFO_CTL_MODE_BYPASSED, + [ADXL345_FIFO_OLD_SAVED] = ADXL345_FIFO_CTL_MODE_OLD_SAVED, + [ADXL345_FIFO_STREAMED] = ADXL345_FIFO_CTL_MODE_STREAMED, + [ADXL345_FIFO_TRIGGERED] = ADXL345_FIFO_CTL_MODE_TRIGGERED, +}; #define ADXL345_ODR_MSK GENMASK(3, 0) #define ADXL345_ODR_MODE(x) FIELD_GET(ADXL345_ODR_MSK, x) @@ -149,16 +163,14 @@ enum adxl345_odr { ADXL345_ODR_400HZ = ADXL345_DT_ODR_400, }; +#define ADXL345_FIFO_CTL_TRIGGER_INT1 0x0 +#define ADXL345_FIFO_CTL_TRIGGER_INT2 BIT(5) +#define ADXL345_FIFO_CTL_TRIGGER_UNSET 0x0 + enum adxl345_fifo_trigger { ADXL345_INT1, - ADXL345_INT2 -}; - -enum adxl345_fifo_mode { - ADXL345_FIFO_BYPASSED, - ADXL345_FIFO_OLD_SAVED, - ADXL345_FIFO_STREAMED, - ADXL345_FIFO_TRIGGERED + ADXL345_INT2, + ADXL345_INT_UNSET, }; struct adxl345_fifo_config { @@ -307,9 +319,9 @@ int adxl345_get_decoder(const struct device *dev, const struct sensor_decoder_ap void adxl345_accel_convert(struct sensor_value *val, int16_t sample); #endif /* CONFIG_SENSOR_ASYNC_API */ -#ifdef CONFIG_ADXL345_STREAM int adxl345_configure_fifo(const struct device *dev, enum adxl345_fifo_mode mode, - enum adxl345_fifo_trigger trigger, uint16_t fifo_samples); + enum adxl345_fifo_trigger trigger, uint8_t fifo_samples); +#ifdef CONFIG_ADXL345_STREAM size_t adxl345_get_packet_size(const struct adxl345_dev_config *cfg); #endif /* CONFIG_ADXL345_STREAM */ #endif /* ZEPHYR_DRIVERS_SENSOR_ADX345_ADX345_H_ */ diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 5740872242a1f..ab3edb769456e 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -68,9 +68,9 @@ static void adxl345_fifo_flush_rtio(const struct device *dev) struct adxl345_dev_data *data = dev->data; uint8_t fifo_config; - fifo_config = (ADXL345_FIFO_CTL_TRIGGER_MODE(data->fifo_config.fifo_trigger) | - ADXL345_FIFO_CTL_MODE_MODE(ADXL345_FIFO_BYPASSED) | - ADXL345_FIFO_CTL_SAMPLES_MODE(data->fifo_config.fifo_samples)); + fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | + adxl345_fifo_ctl_mode_init[ADXL345_FIFO_BYPASSED] | + data->fifo_config.fifo_samples; struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); const uint8_t reg_addr_w2[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; @@ -78,9 +78,9 @@ static void adxl345_fifo_flush_rtio(const struct device *dev) rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, reg_addr_w2, 2, NULL); - fifo_config = (ADXL345_FIFO_CTL_TRIGGER_MODE(data->fifo_config.fifo_trigger) | - ADXL345_FIFO_CTL_MODE_MODE(data->fifo_config.fifo_mode) | - ADXL345_FIFO_CTL_SAMPLES_MODE(data->fifo_config.fifo_samples)); + fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | + adxl345_fifo_ctl_mode_init[data->fifo_config.fifo_mode] | + data->fifo_config.fifo_samples; write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); const uint8_t reg_addr_w3[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; From 6ccabb048db1ba7c17e1175646d64501001b8293 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 19:44:15 +0200 Subject: [PATCH 25/42] sensor: adxl345: remove unused field fifo_config from the const config 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 --- drivers/sensor/adi/adxl345/adxl345.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index e0a0f09996650..edcf33fac2cee 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -264,7 +264,6 @@ struct adxl345_dev_config { adxl345_bus_is_ready_fn bus_is_ready; adxl345_reg_access_fn reg_access; enum adxl345_odr odr; - struct adxl345_fifo_config fifo_config; uint8_t bus_type; #ifdef CONFIG_ADXL345_TRIGGER struct gpio_dt_spec gpio_int1; From 4f3204ad190325ef72f02d3d4212b2bb015c255f Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 20:08:37 +0200 Subject: [PATCH 26/42] sensor: adxl345: remove unnecessary loop check This event loop is unused and was likely copied from similar accelerometer drivers. Remove dead code. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index c5eb8793c92c5..0b5ff72dac550 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -282,17 +282,12 @@ int adxl345_read_sample(const struct device *dev, struct adxl345_sample *sample) { int16_t raw_x, raw_y, raw_z; - uint8_t axis_data[6], status1; struct adxl345_dev_data *data = dev->data; + uint8_t axis_data[6]; + int rc; - if (!IS_ENABLED(CONFIG_ADXL345_TRIGGER)) { - do { - adxl345_get_status(dev, &status1); - } while (!(ADXL345_STATUS_DATA_RDY(status1))); - } - - int rc = adxl345_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, - axis_data, ADXL345_FIFO_SAMPLE_SIZE); + rc = adxl345_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, + axis_data, ADXL345_FIFO_SAMPLE_SIZE); if (rc < 0) { LOG_ERR("Samples read failed with rc=%d\n", rc); return rc; From a64c4864b99fe7ac4292af707b15b176daaa6a66 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Sat, 26 Jul 2025 22:59:08 +0200 Subject: [PATCH 27/42] sensor: adxl345: simplify INT register field defines 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 --- drivers/sensor/adi/adxl345/adxl345.h | 24 +++++++------------- drivers/sensor/adi/adxl345/adxl345_decoder.c | 2 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 12 ++++++---- drivers/sensor/adi/adxl345/adxl345_trigger.c | 10 ++++---- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index edcf33fac2cee..c8233dbb303d1 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -101,22 +101,14 @@ static const uint8_t adxl345_range_init[] = { #define ADXL345_STATUS_ACTIVITY(x) (((x) >> 4) & 0x1) /* ADXL345_INT_MAP */ -#define ADXL345_INT_MAP_OVERRUN_MSK BIT(0) -#define ADXL345_INT_MAP_OVERRUN_MODE(x) (((x) & 0x1) << 0) -#define ADXL345_INT_MAP_WATERMARK_MSK BIT(1) -#define ADXL345_INT_MAP_WATERMARK_MODE(x) (((x) & 0x1) << 1) -#define ADXL345_INT_MAP_FREE_FALL_MSK BIT(2) -#define ADXL345_INT_MAP_FREE_FALL_MODE(x) (((x) & 0x1) << 2) -#define ADXL345_INT_MAP_INACT_MSK BIT(3) -#define ADXL345_INT_MAP_INACT_MODE(x) (((x) & 0x1) << 3) -#define ADXL345_INT_MAP_ACT_MSK BIT(4) -#define ADXL345_INT_MAP_ACT_MODE(x) (((x) & 0x1) << 4) -#define ADXL345_INT_MAP_DOUBLE_TAP_MSK BIT(5) -#define ADXL345_INT_MAP_DOUBLE_TAP_MODE(x) (((x) & 0x1) << 5) -#define ADXL345_INT_MAP_SINGLE_TAP_MSK BIT(6) -#define ADXL345_INT_MAP_SINGLE_TAP_MODE(x) (((x) & 0x1) << 6) -#define ADXL345_INT_MAP_DATA_RDY_MSK BIT(7) -#define ADXL345_INT_MAP_DATA_RDY_MODE(x) (((x) & 0x1) << 7) +#define ADXL345_INT_OVERRUN BIT(0) +#define ADXL345_INT_WATERMARK BIT(1) +#define ADXL345_INT_FREE_FALL BIT(2) +#define ADXL345_INT_INACT BIT(3) +#define ADXL345_INT_ACT BIT(4) +#define ADXL345_INT_DOUBLE_TAP BIT(5) +#define ADXL345_INT_SINGLE_TAP BIT(6) +#define ADXL345_INT_DATA_RDY BIT(7) /* POWER_CTL */ #define ADXL345_POWER_CTL_WAKEUP_4HZ BIT(0) diff --git a/drivers/sensor/adi/adxl345/adxl345_decoder.c b/drivers/sensor/adi/adxl345/adxl345_decoder.c index fbbd8fb6e8df6..5553125e2de80 100644 --- a/drivers/sensor/adi/adxl345/adxl345_decoder.c +++ b/drivers/sensor/adi/adxl345/adxl345_decoder.c @@ -277,7 +277,7 @@ static bool adxl345_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigg switch (trigger) { case SENSOR_TRIG_FIFO_WATERMARK: - return FIELD_GET(ADXL345_INT_MAP_WATERMARK_MSK, data->int_status); + return FIELD_GET(ADXL345_INT_WATERMARK, data->int_status); default: return false; } diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index ab3edb769456e..e7053f7efb3d7 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -16,7 +16,7 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode const struct sensor_read_config *cfg = (const struct sensor_read_config *) iodev_sqe->sqe.iodev->data; struct adxl345_dev_data *data = (struct adxl345_dev_data *)dev->data; - uint8_t int_value = (uint8_t)~ADXL345_INT_MAP_WATERMARK_MSK; + uint8_t int_value = (uint8_t)~ADXL345_INT_WATERMARK; uint8_t fifo_watermark_irq = 0; int rc; @@ -26,13 +26,18 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode for (size_t i = 0; i < cfg->count; i++) { if (cfg->triggers[i].trigger == SENSOR_TRIG_FIFO_WATERMARK) { - int_value = ADXL345_INT_MAP_WATERMARK_MSK; + int_value = ADXL345_INT_WATERMARK; fifo_watermark_irq = 1; } } uint8_t status; if (fifo_watermark_irq != data->fifo_watermark_irq) { data->fifo_watermark_irq = fifo_watermark_irq; + rc = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, + ADXL345_INT_WATERMARK, int_value); + if (rc < 0) { + return; + } /* Flush the FIFO by disabling it. Save current mode for after the reset. */ enum adxl345_fifo_mode current_fifo_mode = data->fifo_config.fifo_mode; @@ -268,8 +273,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq bool fifo_full_irq = false; - if ((fifo_wmark_cfg != NULL) - && FIELD_GET(ADXL345_INT_MAP_WATERMARK_MSK, status1)) { + if (fifo_wmark_cfg && FIELD_GET(ADXL345_INT_WATERMARK, status1)) { fifo_full_irq = true; } diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index 20873f70b77de..3456e7bac9aad 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -154,14 +154,14 @@ int adxl345_trigger_set(const struct device *dev, * are served by reading data-register: two clients can't be * served simultaneously. */ - int_mask = ADXL345_INT_MAP_DATA_RDY_MSK | - ADXL345_INT_MAP_OVERRUN_MSK | - ADXL345_INT_MAP_WATERMARK_MSK; + int_mask = ADXL345_INT_DATA_RDY | + ADXL345_INT_OVERRUN | + ADXL345_INT_WATERMARK; break; case SENSOR_TRIG_MOTION: drv_data->act_handler = handler; drv_data->act_trigger = trig; - int_mask = ADXL345_INT_MAP_ACT_MSK; + int_mask = ADXL345_INT_ACT; ret = adxl345_reg_write_byte(dev, ADXL345_ACT_INACT_CTL_REG, ADXL345_ACT_AC_DC | ADXL345_ACT_X_EN | ADXL345_ACT_Y_EN | ADXL345_ACT_Z_EN); @@ -175,7 +175,7 @@ int adxl345_trigger_set(const struct device *dev, } if (handler) { - int_en = ADXL345_INT_MAP_DATA_RDY_MSK; + int_en = ADXL345_INT_DATA_RDY; } else { int_en = 0U; } From 2c2df726e62eae754c4f6d880e223b902a237baf Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 17:55:14 +0200 Subject: [PATCH 28/42] sensor: adxl345: simplify event handler registration 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 --- drivers/sensor/adi/adxl345/adxl345.h | 7 +- drivers/sensor/adi/adxl345/adxl345_trigger.c | 146 ++++++++++++------- 2 files changed, 97 insertions(+), 56 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index c8233dbb303d1..d79ab355f9422 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -185,12 +185,14 @@ struct adxl345_dev_data { struct gpio_callback int1_cb; struct gpio_callback int2_cb; - sensor_trigger_handler_t th_handler; - const struct sensor_trigger *th_trigger; sensor_trigger_handler_t drdy_handler; const struct sensor_trigger *drdy_trigger; sensor_trigger_handler_t act_handler; const struct sensor_trigger *act_trigger; + sensor_trigger_handler_t wm_handler; + const struct sensor_trigger *wm_trigger; + sensor_trigger_handler_t overrun_handler; + const struct sensor_trigger *overrun_trigger; const struct device *dev; #if defined(CONFIG_ADXL345_TRIGGER_OWN_THREAD) @@ -266,6 +268,7 @@ struct adxl345_dev_config { int adxl345_set_gpios_en(const struct device *dev, bool enable); int adxl345_set_measure_en(const struct device *dev, bool en); +int adxl345_flush_fifo(const struct device *dev); void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); void adxl345_stream_irq_handler(const struct device *dev); diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index 3456e7bac9aad..987792312ee4d 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -51,19 +51,51 @@ static void adxl345_thread_cb(const struct device *dev) uint8_t status; int ret; - /* Clear the status */ - if (adxl345_get_status(dev, &status) < 0) { - return; + ret = adxl345_get_status(dev, &status); + __ASSERT(ret == 0, "Interrupt configuration failed"); + + if (FIELD_GET(ADXL345_INT_DATA_RDY, status)) { + if (drv_data->drdy_handler) { + /* + * A handler needs to flush FIFO, i.e. fetch and get + * samples to get new events + */ + drv_data->drdy_handler(dev, drv_data->drdy_trigger); + } } - if ((drv_data->drdy_handler != NULL) && - ADXL345_STATUS_DATA_RDY(status)) { - drv_data->drdy_handler(dev, drv_data->drdy_trigger); + if (FIELD_GET(ADXL345_INT_WATERMARK, status)) { + if (drv_data->wm_handler) { + /* + * A handler needs to implement fetch, then get FIFO + * entries according to configured watermark in order + * to obtain new sensor events + */ + drv_data->wm_handler(dev, drv_data->wm_trigger); + } } - if ((drv_data->act_handler != NULL) && - ADXL345_STATUS_ACTIVITY(status)) { - drv_data->act_handler(dev, drv_data->act_trigger); + /* handle FIFO: overrun */ + if (FIELD_GET(ADXL345_INT_OVERRUN, status)) { + if (drv_data->overrun_handler) { + /* + * A handler may handle read outs, the fallback flushes + * the fifo and interrupt status register + */ + drv_data->overrun_handler(dev, drv_data->overrun_trigger); + } + + /* + * If overrun handling is enabled, reset status register and + * fifo here, if not handled before in any way + */ + adxl345_flush_fifo(dev); + } + + if (drv_data->act_trigger && FIELD_GET(ADXL345_INT_ACT, status)) { + if (drv_data->act_handler) { + drv_data->act_handler(dev, drv_data->act_trigger); + } } ret = adxl345_set_gpios_en(dev, true); @@ -135,37 +167,71 @@ int adxl345_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { + const struct adxl345_dev_config *cfg = dev->config; struct adxl345_dev_data *drv_data = dev->data; - struct adxl345_sample sample; - uint8_t int_mask, int_en; - uint8_t samples_count; int ret; + if (!cfg->gpio_int1.port && !cfg->gpio_int2.port) { + /* might be in FIFO BYPASS mode */ + goto done; + } + + /* generally turn off interrupts */ ret = adxl345_set_gpios_en(dev, false); if (ret) { - return ret; + goto done; + } + + if (!handler) { + goto done; } switch (trig->type) { case SENSOR_TRIG_DATA_READY: drv_data->drdy_handler = handler; drv_data->drdy_trigger = trig; - /** Enabling DRDY means not using Watermark interrupt as both - * are served by reading data-register: two clients can't be - * served simultaneously. - */ - int_mask = ADXL345_INT_DATA_RDY | - ADXL345_INT_OVERRUN | - ADXL345_INT_WATERMARK; + + ret = adxl345_reg_assign_bits(dev, ADXL345_INT_ENABLE_REG, + ADXL345_INT_DATA_RDY, + true); + if (ret) { + return ret; + } + break; + case SENSOR_TRIG_FIFO_WATERMARK: + drv_data->wm_handler = handler; + drv_data->wm_trigger = trig; + ret = adxl345_reg_assign_bits(dev, ADXL345_INT_ENABLE_REG, + ADXL345_INT_WATERMARK, + true); + if (ret) { + return ret; + } + break; + case SENSOR_TRIG_FIFO_FULL: + drv_data->overrun_handler = handler; + drv_data->overrun_trigger = trig; + ret = adxl345_reg_assign_bits(dev, ADXL345_INT_ENABLE_REG, + ADXL345_INT_OVERRUN, + true); + if (ret) { + return ret; + } break; case SENSOR_TRIG_MOTION: drv_data->act_handler = handler; drv_data->act_trigger = trig; - int_mask = ADXL345_INT_ACT; ret = adxl345_reg_write_byte(dev, ADXL345_ACT_INACT_CTL_REG, ADXL345_ACT_AC_DC | ADXL345_ACT_X_EN | ADXL345_ACT_Y_EN | ADXL345_ACT_Z_EN); - if (ret < 0) { + if (ret) { + return ret; + } + + ret = adxl345_reg_assign_bits(dev, ADXL345_INT_ENABLE_REG, + ADXL345_INT_ACT, + true); + if (ret) { return ret; } break; @@ -174,41 +240,13 @@ int adxl345_trigger_set(const struct device *dev, return -ENOTSUP; } - if (handler) { - int_en = ADXL345_INT_DATA_RDY; - } else { - int_en = 0U; - } - -#ifdef CONFIG_ADXL345_STREAM - (void)adxl345_configure_fifo(dev, ADXL345_FIFO_BYPASSED, ADXL345_INT2, 0); -#endif - - ret = adxl345_reg_write_mask(dev, ADXL345_INT_ENABLE_REG, int_mask, 0); - if (ret < 0) { - return ret; - } - - /* Clear status and read sample-set to clear interrupt flag */ - (void)adxl345_read_sample(dev, &sample); - - ret = adxl345_reg_read_byte(dev, ADXL345_FIFO_STATUS_REG, &samples_count); - if (ret < 0) { - LOG_ERR("Failed to read FIFO status rc = %d\n", ret); - return ret; - } - +done: ret = adxl345_set_gpios_en(dev, true); if (ret) { return ret; } - ret = adxl345_reg_write_mask(dev, ADXL345_INT_ENABLE_REG, int_mask, int_en); - if (ret < 0) { - return ret; - } - - return 0; + return adxl345_flush_fifo(dev); } int adxl345_init_interrupt(const struct device *dev) @@ -270,7 +308,7 @@ int adxl345_init_interrupt(const struct device *dev) if (cfg->gpio_int2.port) { ret = gpio_pin_configure_dt(&cfg->gpio_int2, GPIO_INPUT); - if (ret < 0) { + if (ret) { return ret; } @@ -278,7 +316,7 @@ int adxl345_init_interrupt(const struct device *dev) BIT(cfg->gpio_int2.pin)); ret = gpio_add_callback(cfg->gpio_int2.port, &drv_data->int2_cb); - if (ret < 0) { + if (ret) { LOG_ERR("Failed to set INT_2 gpio callback!"); return -EIO; } From ccea5a0d1c1b699bf3541312fa3f18fe64e6947b Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Sun, 27 Jul 2025 16:32:45 +0200 Subject: [PATCH 29/42] sensor: adxl345: fix fetch and get to correctly read the FIFO samples 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 --- drivers/sensor/adi/adxl345/adxl345.c | 115 +++++++++++++++++++-------- drivers/sensor/adi/adxl345/adxl345.h | 32 ++++---- 2 files changed, 98 insertions(+), 49 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 0b5ff72dac550..c51aa7b0b9c25 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -279,11 +279,9 @@ static int adxl345_attr_set(const struct device *dev, } int adxl345_read_sample(const struct device *dev, - struct adxl345_sample *sample) + struct adxl345_sample *sample) { - int16_t raw_x, raw_y, raw_z; - struct adxl345_dev_data *data = dev->data; - uint8_t axis_data[6]; + uint8_t axis_data[ADXL345_FIFO_SAMPLE_SIZE]; int rc; rc = adxl345_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, @@ -293,74 +291,127 @@ int adxl345_read_sample(const struct device *dev, return rc; } - raw_x = axis_data[0] | (axis_data[1] << 8); - raw_y = axis_data[2] | (axis_data[3] << 8); - raw_z = axis_data[4] | (axis_data[5] << 8); + sample->x = axis_data[0] | axis_data[1] << 8; + sample->y = axis_data[2] | axis_data[3] << 8; + sample->z = axis_data[4] | axis_data[5] << 8; - sample->x = raw_x; - sample->y = raw_y; - sample->z = raw_z; +#ifdef CONFIG_ADXL345_TRIGGER + struct adxl345_dev_data *data = dev->data; + sample->is_full_res = data->is_full_res; /* needed for decoder */ sample->selected_range = data->selected_range; - sample->is_full_res = data->is_full_res; +#endif - return 0; + return rc; } -void adxl345_accel_convert(struct sensor_value *val, int16_t sample) +/** + * adxl345_accel_convert - The fallback conversion of raw measurements. + * @out: Converted value for output, containing the initialized fractional. + * @sample: Input raw measurement. + * When working without decoder, neither TRIGGER, nor STREAM is enabled, + * this small converter is used. It assumes full scale resolution and 8g. + */ +void adxl345_accel_convert(struct sensor_value *out, int16_t sample) { - if (sample & BIT(9)) { - sample |= ADXL345_COMPLEMENT; + /* full resolution enabled w/ 8g */ + if (sample & BIT(11)) { + sample |= ADXL345_COMPLEMENT_MASK(12); } - - val->val1 = ((sample * SENSOR_G) / 32) / 1000000; - val->val2 = ((sample * SENSOR_G) / 32) % 1000000; + out->val1 = ((sample * SENSOR_G) / 32) / 1000000; + out->val2 = ((sample * SENSOR_G) / 32) % 1000000; } static int adxl345_sample_fetch(const struct device *dev, enum sensor_channel chan) { struct adxl345_dev_data *data = dev->data; - struct adxl345_sample sample; + uint8_t count; int rc; - rc = adxl345_read_sample(dev, &sample); - if (rc < 0) { - LOG_ERR("Failed to fetch sample rc=%d\n", rc); - return rc; + count = 1; + + /* FIFO BYPASSED is the only mode not using a FIFO buffer */ + if (data->fifo_config.fifo_mode != ADXL345_FIFO_BYPASSED) { + count = adxl345_get_fifo_entries(dev); + if (count < 0) { + return -EIO; + } + } + + __ASSERT_NO_MSG(count <= ARRAY_SIZE(data->sample)); + + for (uint8_t s = 0; s < count; s++) { + rc = adxl345_read_sample(dev, &data->sample[s]); + if (rc < 0) { + LOG_ERR("Failed to fetch sample rc=%d\n", rc); + return rc; + } + +#ifdef CONFIG_ADXL345_STREAM + data->sample[s].is_fifo = 0; +#endif } - data->samples.x = sample.x; - data->samples.y = sample.y; - data->samples.z = sample.z; + + /* new sample available, reset book-keeping */ + data->sample_idx = 0; + data->sample_number = count; return 0; } +/** + * adxl345_channel_get - Read a single element of one or three axis. + * @dev: The sensor device. + * @chan: The axis channel, can be x, y, z or xyz. + * @val: The resulting value after conversion of the raw axis data. Val can be + * a single value or an array of three values, where the index correspondes to + * x, y, z axis entries. + */ static int adxl345_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct adxl345_dev_data *data = dev->data; + int idx; + + if (data->sample_number <= 0) { /* empty */ + val->val1 = 0; + val->val2 = 0; + if (chan == SENSOR_CHAN_ACCEL_XYZ) { + val[1].val1 = 0; + val[1].val2 = 0; + val[2].val1 = 0; + val[2].val2 = 0; + } + return -ENOTSUP; + } + + data->sample_idx = data->sample_idx % data->sample_number; + idx = data->sample_idx; switch (chan) { case SENSOR_CHAN_ACCEL_X: - adxl345_accel_convert(val, data->samples.x); + adxl345_accel_convert(val, data->sample[idx].x); break; case SENSOR_CHAN_ACCEL_Y: - adxl345_accel_convert(val, data->samples.y); + adxl345_accel_convert(val, data->sample[idx].y); break; case SENSOR_CHAN_ACCEL_Z: - adxl345_accel_convert(val, data->samples.z); + adxl345_accel_convert(val, data->sample[idx].z); break; case SENSOR_CHAN_ACCEL_XYZ: - adxl345_accel_convert(val++, data->samples.x); - adxl345_accel_convert(val++, data->samples.y); - adxl345_accel_convert(val, data->samples.z); + adxl345_accel_convert(val++, data->sample[idx].x); + adxl345_accel_convert(val++, data->sample[idx].y); + adxl345_accel_convert(val, data->sample[idx].z); + break; default: return -ENOTSUP; } + data->sample_idx++; + return 0; } diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index d79ab355f9422..a91e8fefe6af8 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -171,12 +171,22 @@ struct adxl345_fifo_config { uint8_t fifo_samples; }; +struct adxl345_sample { +#ifdef CONFIG_ADXL345_STREAM + uint8_t is_fifo: 1; + uint8_t res: 7; +#endif /* CONFIG_ADXL345_STREAM */ + enum adxl345_range selected_range; + bool is_full_res; + int16_t x; + int16_t y; + int16_t z; +} __attribute__((__packed__)); + struct adxl345_dev_data { - struct { - int16_t x; - int16_t y; - int16_t z; - } samples; + struct adxl345_sample sample[ADXL345_MAX_FIFO_SIZE]; + uint8_t sample_number; /* number of samples to read from sensor */ + uint8_t sample_idx; /* index counting up sample_number entries */ struct adxl345_fifo_config fifo_config; bool is_full_res; enum adxl345_range selected_range; @@ -228,18 +238,6 @@ struct adxl345_fifo_data { uint64_t timestamp; } __attribute__((__packed__)); -struct adxl345_sample { -#ifdef CONFIG_ADXL345_STREAM - uint8_t is_fifo: 1; - uint8_t res: 7; -#endif /* CONFIG_ADXL345_STREAM */ - uint8_t selected_range; - bool is_full_res; - int16_t x; - int16_t y; - int16_t z; -}; - union adxl345_bus { #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) struct i2c_dt_spec i2c; From 23189cd85d655632d1a5597e103cb622fe9cab5e Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Mon, 22 Sep 2025 19:56:43 +0200 Subject: [PATCH 30/42] sensor: adxl345: reorganize stream code 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 --- drivers/sensor/adi/adxl345/adxl345_stream.c | 163 +++++++++++--------- 1 file changed, 87 insertions(+), 76 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index e7053f7efb3d7..6172099b115b1 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -11,53 +11,12 @@ LOG_MODULE_DECLARE(ADXL345, CONFIG_SENSOR_LOG_LEVEL); -void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) -{ - const struct sensor_read_config *cfg = - (const struct sensor_read_config *) iodev_sqe->sqe.iodev->data; - struct adxl345_dev_data *data = (struct adxl345_dev_data *)dev->data; - uint8_t int_value = (uint8_t)~ADXL345_INT_WATERMARK; - uint8_t fifo_watermark_irq = 0; - int rc; +static void adxl345_fifo_flush_rtio(const struct device *dev); - if (adxl345_set_gpios_en(dev, false)) { - return; - } +/* auxiliary functions */ - for (size_t i = 0; i < cfg->count; i++) { - if (cfg->triggers[i].trigger == SENSOR_TRIG_FIFO_WATERMARK) { - int_value = ADXL345_INT_WATERMARK; - fifo_watermark_irq = 1; - } - } - uint8_t status; - if (fifo_watermark_irq != data->fifo_watermark_irq) { - data->fifo_watermark_irq = fifo_watermark_irq; - rc = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, - ADXL345_INT_WATERMARK, int_value); - if (rc < 0) { - return; - } - - /* Flush the FIFO by disabling it. Save current mode for after the reset. */ - enum adxl345_fifo_mode current_fifo_mode = data->fifo_config.fifo_mode; - - if (current_fifo_mode == ADXL345_FIFO_BYPASSED) { - current_fifo_mode = ADXL345_FIFO_STREAMED; - } - adxl345_configure_fifo(dev, ADXL345_FIFO_BYPASSED, data->fifo_config.fifo_trigger, - data->fifo_config.fifo_samples); - adxl345_configure_fifo(dev, current_fifo_mode, data->fifo_config.fifo_trigger, - data->fifo_config.fifo_samples); - rc = adxl345_reg_read_byte(dev, ADXL345_FIFO_STATUS_REG, &status); - } - - if (adxl345_set_gpios_en(dev, true)) { - return; - } - data->sqe = iodev_sqe; -} +/* streaming callbacks and calls */ static void adxl345_irq_en_cb(struct rtio *r, const struct rtio_sqe *sqe, int result, void *arg) { @@ -68,38 +27,6 @@ static void adxl345_irq_en_cb(struct rtio *r, const struct rtio_sqe *sqe, int re adxl345_set_gpios_en(dev, true); } -static void adxl345_fifo_flush_rtio(const struct device *dev) -{ - struct adxl345_dev_data *data = dev->data; - uint8_t fifo_config; - - fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | - adxl345_fifo_ctl_mode_init[ADXL345_FIFO_BYPASSED] | - data->fifo_config.fifo_samples; - - struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); - const uint8_t reg_addr_w2[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; - - rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, reg_addr_w2, - 2, NULL); - - fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | - adxl345_fifo_ctl_mode_init[data->fifo_config.fifo_mode] | - data->fifo_config.fifo_samples; - - write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); - const uint8_t reg_addr_w3[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; - - rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, reg_addr_w3, - 2, NULL); - write_fifo_addr->flags |= RTIO_SQE_CHAINED; - - struct rtio_sqe *complete_op = rtio_sqe_acquire(data->rtio_ctx); - - rtio_sqe_prep_callback(complete_op, adxl345_irq_en_cb, (void *)dev, NULL); - rtio_submit(data->rtio_ctx, 0); -} - static void adxl345_fifo_read_cb(struct rtio *rtio_ctx, const struct rtio_sqe *sqe, int result, void *arg) { @@ -359,6 +286,90 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq rtio_submit(data->rtio_ctx, 0); } +static void adxl345_fifo_flush_rtio(const struct device *dev) +{ + struct adxl345_dev_data *data = dev->data; + uint8_t fifo_config; + + fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | + adxl345_fifo_ctl_mode_init[ADXL345_FIFO_BYPASSED] | + data->fifo_config.fifo_samples; + + struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); + const uint8_t reg_addr_w2[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; + + rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, + reg_addr_w2, 2, NULL); + + fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | + adxl345_fifo_ctl_mode_init[data->fifo_config.fifo_mode] | + data->fifo_config.fifo_samples; + + write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); + const uint8_t reg_addr_w3[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; + + rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, + reg_addr_w3, 2, NULL); + write_fifo_addr->flags |= RTIO_SQE_CHAINED; + + struct rtio_sqe *complete_op = rtio_sqe_acquire(data->rtio_ctx); + + rtio_sqe_prep_callback(complete_op, adxl345_irq_en_cb, (void *)dev, NULL); + rtio_submit(data->rtio_ctx, 0); +} + +/* Consumer calls */ + +void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *cfg = + (const struct sensor_read_config *)iodev_sqe->sqe.iodev->data; + struct adxl345_dev_data *data = (struct adxl345_dev_data *)dev->data; + uint8_t int_value = (uint8_t)~ADXL345_INT_WATERMARK; + uint8_t fifo_watermark_irq = 0; + int rc; + + if (adxl345_set_gpios_en(dev, false)) { + return; + } + + for (size_t i = 0; i < cfg->count; i++) { + if (cfg->triggers[i].trigger == SENSOR_TRIG_FIFO_WATERMARK) { + int_value = ADXL345_INT_WATERMARK; + fifo_watermark_irq = 1; + } + } + uint8_t status; + if (fifo_watermark_irq != data->fifo_watermark_irq) { + data->fifo_watermark_irq = fifo_watermark_irq; + rc = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, + ADXL345_INT_WATERMARK, int_value); + if (rc < 0) { + return; + } + + /* Flush the FIFO by disabling it. Save current mode for after the reset. */ + enum adxl345_fifo_mode current_fifo_mode = data->fifo_config.fifo_mode; + + if (current_fifo_mode == ADXL345_FIFO_BYPASSED) { + current_fifo_mode = ADXL345_FIFO_STREAMED; + } + adxl345_configure_fifo(dev, ADXL345_FIFO_BYPASSED, + data->fifo_config.fifo_trigger, + data->fifo_config.fifo_samples); + adxl345_configure_fifo(dev, current_fifo_mode, + data->fifo_config.fifo_trigger, + data->fifo_config.fifo_samples); + rc = adxl345_reg_read_byte(dev, ADXL345_FIFO_STATUS_REG, &status); + } + + if (adxl345_set_gpios_en(dev, true)) { + return; + } + + data->sqe = iodev_sqe; +} + void adxl345_stream_irq_handler(const struct device *dev) { struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; From 334077bc1939b60c19e0c44ed2f7988bd92e92a8 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Mon, 22 Sep 2025 23:20:34 +0200 Subject: [PATCH 31/42] sensor: adxl345: remove pointless variable fifo_total_bytes The fifo_total_bytes driver data variable is only used as a local calculation and can therefore be removed entirely. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345.h | 1 - drivers/sensor/adi/adxl345/adxl345_stream.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index a91e8fefe6af8..19d853f10f8c6 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -223,7 +223,6 @@ struct adxl345_dev_data { struct rtio *r_cb; uint8_t fifo_watermark_irq; uint8_t fifo_samples; - uint16_t fifo_total_bytes; #endif /* CONFIG_ADXL345_STREAM */ }; diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 6172099b115b1..a3fffdedbf983 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -37,7 +37,6 @@ static void adxl345_fifo_read_cb(struct rtio *rtio_ctx, const struct rtio_sqe *s struct rtio_iodev_sqe *iodev_sqe = sqe->userdata; if (data->fifo_samples == 0) { - data->fifo_total_bytes = 0; rtio_iodev_sqe_ok(iodev_sqe, 0); adxl345_set_gpios_en(dev, true); } @@ -143,9 +142,8 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq 1, NULL); write_fifo_addr->flags |= RTIO_SQE_TRANSACTION; rtio_sqe_prep_read(read_fifo_data, data->iodev, RTIO_PRIO_NORM, - read_buf + data->fifo_total_bytes, + (read_buf + i * ADXL345_FIFO_SAMPLE_SIZE), ADXL345_FIFO_SAMPLE_SIZE, current_sqe); - data->fifo_total_bytes += ADXL345_FIFO_SAMPLE_SIZE; if (cfg->bus_type == ADXL345_BUS_I2C) { read_fifo_data->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; } From 4f92ab8bd37f90ca5342eb2f6e4779905dccd4a3 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 23 Sep 2025 00:23:26 +0200 Subject: [PATCH 32/42] sensor: adxl345: use a concise naming for fifo related variables 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 --- drivers/sensor/adi/adxl345/adxl345.c | 6 +++--- drivers/sensor/adi/adxl345/adxl345.h | 6 +++--- drivers/sensor/adi/adxl345/adxl345_stream.c | 18 +++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index c51aa7b0b9c25..db409d5def26b 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -355,7 +355,7 @@ static int adxl345_sample_fetch(const struct device *dev, /* new sample available, reset book-keeping */ data->sample_idx = 0; - data->sample_number = count; + data->fifo_entries = count; return 0; } @@ -375,7 +375,7 @@ static int adxl345_channel_get(const struct device *dev, struct adxl345_dev_data *data = dev->data; int idx; - if (data->sample_number <= 0) { /* empty */ + if (data->fifo_entries <= 0) { /* empty */ val->val1 = 0; val->val2 = 0; if (chan == SENSOR_CHAN_ACCEL_XYZ) { @@ -387,7 +387,7 @@ static int adxl345_channel_get(const struct device *dev, return -ENOTSUP; } - data->sample_idx = data->sample_idx % data->sample_number; + data->sample_idx = data->sample_idx % data->fifo_entries; idx = data->sample_idx; switch (chan) { diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 19d853f10f8c6..ffa69842723b5 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -185,7 +185,7 @@ struct adxl345_sample { struct adxl345_dev_data { struct adxl345_sample sample[ADXL345_MAX_FIFO_SIZE]; - uint8_t sample_number; /* number of samples to read from sensor */ + uint8_t fifo_entries; /* the actual read FIFO entries */ uint8_t sample_idx; /* index counting up sample_number entries */ struct adxl345_fifo_config fifo_config; bool is_full_res; @@ -218,11 +218,10 @@ struct adxl345_dev_data { struct rtio *rtio_ctx; struct rtio_iodev *iodev; uint8_t status1; - uint8_t fifo_ent[1]; + uint8_t reg_fifo_status; /* FIFO status register */ uint64_t timestamp; struct rtio *r_cb; uint8_t fifo_watermark_irq; - uint8_t fifo_samples; #endif /* CONFIG_ADXL345_STREAM */ }; @@ -260,6 +259,7 @@ struct adxl345_dev_config { struct gpio_dt_spec gpio_int1; struct gpio_dt_spec gpio_int2; int8_t drdy_pad; + uint8_t fifo_samples; #endif }; diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index a3fffdedbf983..ce2fd3a6b928c 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -36,7 +36,7 @@ static void adxl345_fifo_read_cb(struct rtio *rtio_ctx, const struct rtio_sqe *s struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; struct rtio_iodev_sqe *iodev_sqe = sqe->userdata; - if (data->fifo_samples == 0) { + if (data->fifo_entries == 0) { rtio_iodev_sqe_ok(iodev_sqe, 0); adxl345_set_gpios_en(dev, true); } @@ -52,9 +52,10 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *current_sqe = data->sqe; - uint16_t fifo_samples = (data->fifo_ent[0]) & ADXL345_FIFO_ENTRIES_MSK; + data->fifo_entries = FIELD_GET(ADXL345_FIFO_ENTRIES_MSK, data->reg_fifo_status); + uint8_t fifo_entries = data->fifo_entries; size_t sample_set_size = ADXL345_FIFO_SAMPLE_SIZE; - uint16_t fifo_bytes = fifo_samples * ADXL345_FIFO_SAMPLE_SIZE; + uint16_t fifo_bytes = fifo_entries * ADXL345_FIFO_SAMPLE_SIZE; data->sqe = NULL; @@ -129,12 +130,11 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq } - data->fifo_samples = fifo_samples; - for (size_t i = 0; i < fifo_samples; i++) { + for (size_t i = 0; i < fifo_entries; i++) { + data->fifo_entries--; struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); struct rtio_sqe *read_fifo_data = rtio_sqe_acquire(data->rtio_ctx); - data->fifo_samples--; const uint8_t reg_addr = ADXL345_REG_READ(ADXL345_REG_DATA_XYZ_REGS) | ADXL345_MULTIBYTE_FLAG; @@ -147,7 +147,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq if (cfg->bus_type == ADXL345_BUS_I2C) { read_fifo_data->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; } - if (i == fifo_samples-1) { + if (i == fifo_entries - 1) { struct rtio_sqe *complete_op = rtio_sqe_acquire(data->rtio_ctx); read_fifo_data->flags |= RTIO_SQE_CHAINED; @@ -272,8 +272,8 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, ®_addr, 1, NULL); write_fifo_addr->flags |= RTIO_SQE_TRANSACTION; - rtio_sqe_prep_read(read_fifo_data, data->iodev, RTIO_PRIO_NORM, data->fifo_ent, 1, - current_sqe); + rtio_sqe_prep_read(read_fifo_data, data->iodev, RTIO_PRIO_NORM, &data->reg_fifo_status, + sizeof(data->reg_fifo_status), current_sqe); read_fifo_data->flags |= RTIO_SQE_CHAINED; if (cfg->bus_type == ADXL345_BUS_I2C) { read_fifo_data->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; From 7730503cca0a1492ee15c69b98afb4025c12b641 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 22 Jul 2025 00:39:45 +0200 Subject: [PATCH 33/42] sensor: adxl345: add watermark configuration through app attribute 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 --- drivers/sensor/adi/adxl345/adxl345.c | 45 ++++++++++++++++++--- drivers/sensor/adi/adxl345/adxl345.h | 1 - drivers/sensor/adi/adxl345/adxl345_stream.c | 20 ++++----- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index db409d5def26b..99e60772587bd 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -263,6 +263,32 @@ static int adxl345_attr_set_odr(const struct device *dev, ADXL345_ODR_MODE(odr)); } +#if !defined(CONFIG_ADXL345_STREAM) +/* + * In RTIO the watermark i.e. FIFO entries, will be used to lay out the memory + * pool for elements to hold. Thus watermark needs to be defined in the + * devicetree. If by attriute setting a greater number of entries will be set, + * it would crash. + */ +static int adxl345_attr_set_watermark(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + struct adxl345_dev_data *data = dev->data; + uint8_t wm = val->val1; + + if (wm < 1 || wm > ADXL345_MAX_FIFO_SIZE) { + return -EINVAL; + } + + data->fifo_config.fifo_samples = wm; + + return adxl345_reg_write_mask(dev, ADXL345_FIFO_CTL_REG, + ADXL345_FIFO_CTL_SAMPLES_MSK, wm); +} +#endif + static int adxl345_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, @@ -273,6 +299,10 @@ static int adxl345_attr_set(const struct device *dev, return adxl345_attr_set_odr(dev, chan, attr, val); case SENSOR_ATTR_UPPER_THRESH: return adxl345_reg_write_byte(dev, ADXL345_THRESH_ACT_REG, val->val1); +#if !defined(CONFIG_ADXL345_STREAM) + case SENSOR_ATTR_MAX: + return adxl345_attr_set_watermark(dev, chan, attr, val); +#endif default: return -ENOTSUP; } @@ -435,6 +465,7 @@ static int adxl345_init(const struct device *dev) enum adxl345_fifo_mode fifo_mode; uint8_t dev_id; uint8_t int_en; + uint8_t fifo_samples; uint8_t regval; int rc; @@ -483,6 +514,7 @@ static int adxl345_init(const struct device *dev) } fifo_mode = ADXL345_FIFO_BYPASSED; + fifo_samples = 0; int_en = 0x00; #if defined(CONFIG_ADXL345_TRIGGER) || defined(CONFIG_ADXL345_STREAM) if (adxl345_init_interrupt(dev)) { @@ -491,6 +523,7 @@ static int adxl345_init(const struct device *dev) } else { LOG_INF("Set FIFO STREAMED mode"); fifo_mode = ADXL345_FIFO_STREAMED; + fifo_samples = cfg->fifo_samples; /* * Currently, map all interrupts to the (same) gpio line @@ -508,8 +541,7 @@ static int adxl345_init(const struct device *dev) } } #endif - rc = adxl345_configure_fifo(dev, fifo_mode, ADXL345_INT_UNSET, - ADXL345_FIFO_CTL_SAMPLES_MSK); + rc = adxl345_configure_fifo(dev, fifo_mode, ADXL345_INT_UNSET, fifo_samples); if (rc) { return rc; } @@ -525,7 +557,8 @@ static int adxl345_init(const struct device *dev) #define ADXL345_CFG_IRQ(inst) \ .gpio_int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, {0}), \ .gpio_int2 = GPIO_DT_SPEC_INST_GET_OR(inst, int2_gpios, {0}), \ - .drdy_pad = DT_INST_PROP_OR(inst, drdy_pin, -1), + .drdy_pad = DT_INST_PROP_OR(inst, drdy_pin, -1), \ + .fifo_samples = DT_INST_PROP_OR(inst, fifo_watermark, 1), #else #define ADXL345_CFG_IRQ(inst) #endif /* CONFIG_ADXL345_TRIGGER */ @@ -562,9 +595,9 @@ static int adxl345_init(const struct device *dev) COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \ (ADXL345_RTIO_I2C_DEFINE(inst)), \ ()) \ - RTIO_DEFINE(adxl345_rtio_ctx_##inst, \ - 2 * DT_INST_PROP(inst, fifo_watermark) + 2, \ - 2 * DT_INST_PROP(inst, fifo_watermark) + 2); + RTIO_DEFINE(adxl345_rtio_ctx_##inst, \ + 4 * ADXL345_MAX_FIFO_SIZE, \ + 4 * ADXL345_MAX_FIFO_SIZE); #define ADXL345_CONFIG(inst) \ .odr = DT_INST_PROP_OR(inst, odr, ADXL345_RATE_25HZ), diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index ffa69842723b5..fa39685d0652f 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -221,7 +221,6 @@ struct adxl345_dev_data { uint8_t reg_fifo_status; /* FIFO status register */ uint64_t timestamp; struct rtio *r_cb; - uint8_t fifo_watermark_irq; #endif /* CONFIG_ADXL345_STREAM */ }; diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index ce2fd3a6b928c..8a7d3b076ee52 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -323,8 +323,7 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode const struct sensor_read_config *cfg = (const struct sensor_read_config *)iodev_sqe->sqe.iodev->data; struct adxl345_dev_data *data = (struct adxl345_dev_data *)dev->data; - uint8_t int_value = (uint8_t)~ADXL345_INT_WATERMARK; - uint8_t fifo_watermark_irq = 0; + uint8_t status; int rc; if (adxl345_set_gpios_en(dev, false)) { @@ -333,17 +332,12 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode for (size_t i = 0; i < cfg->count; i++) { if (cfg->triggers[i].trigger == SENSOR_TRIG_FIFO_WATERMARK) { - int_value = ADXL345_INT_WATERMARK; - fifo_watermark_irq = 1; - } - } - uint8_t status; - if (fifo_watermark_irq != data->fifo_watermark_irq) { - data->fifo_watermark_irq = fifo_watermark_irq; - rc = adxl345_reg_write_mask(dev, ADXL345_INT_MAP_REG, - ADXL345_INT_WATERMARK, int_value); - if (rc < 0) { - return; + rc = adxl345_reg_assign_bits(dev, ADXL345_INT_ENABLE_REG, + ADXL345_INT_WATERMARK, true); + if (rc) { + LOG_WRN("adxl345_reg_assign_bits() failed"); + return; + } } /* Flush the FIFO by disabling it. Save current mode for after the reset. */ From 6a4d044ab1fed3c19cd84857f5a4c9f24ac49e3f Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 23 Sep 2025 18:18:39 +0200 Subject: [PATCH 34/42] sensor: adxl345: rename status1 to reg_int_source 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 --- drivers/sensor/adi/adxl345/adxl345.h | 2 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index fa39685d0652f..8c77014af094e 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -217,7 +217,7 @@ struct adxl345_dev_data { struct rtio_iodev_sqe *sqe; struct rtio *rtio_ctx; struct rtio_iodev *iodev; - uint8_t status1; + uint8_t reg_int_source; /* interrupt status register */ uint8_t reg_fifo_status; /* FIFO status register */ uint64_t timestamp; struct rtio *r_cb; diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 8a7d3b076ee52..27bdf2fb40c54 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -86,7 +86,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq hdr->is_fifo = 1; hdr->timestamp = data->timestamp; - hdr->int_status = data->status1; + hdr->int_status = data->reg_int_source; hdr->is_full_res = data->is_full_res; hdr->selected_range = data->selected_range; hdr->accel_odr = data->odr; @@ -169,7 +169,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *current_sqe = data->sqe; struct sensor_read_config *read_config; - uint8_t status1 = data->status1; + uint8_t status1 = data->reg_int_source; if (data->sqe == NULL) { return; @@ -386,9 +386,12 @@ void adxl345_stream_irq_handler(const struct device *dev) struct rtio_sqe *check_status_reg = rtio_sqe_acquire(data->rtio_ctx); uint8_t reg = ADXL345_REG_READ(ADXL345_INT_SOURCE_REG); - rtio_sqe_prep_tiny_write(write_status_addr, data->iodev, RTIO_PRIO_NORM, ®, 1, NULL); + rtio_sqe_prep_tiny_write(write_status_addr, data->iodev, + RTIO_PRIO_NORM, ®, sizeof(reg), NULL); write_status_addr->flags |= RTIO_SQE_TRANSACTION; - rtio_sqe_prep_read(read_status_reg, data->iodev, RTIO_PRIO_NORM, &data->status1, 1, NULL); + rtio_sqe_prep_read(read_status_reg, data->iodev, RTIO_PRIO_NORM, + &data->reg_int_source, sizeof(data->reg_int_source), + NULL); read_status_reg->flags |= RTIO_SQE_CHAINED; if (cfg->bus_type == ADXL345_BUS_I2C) { From e3e53db3452d47ca00ef1c9c0142ca0bf390c8c4 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 23 Sep 2025 22:37:26 +0200 Subject: [PATCH 35/42] sensor: adxl345: streamline error handling 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 --- drivers/sensor/adi/adxl345/adxl345_stream.c | 60 +++++++++++++-------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 27bdf2fb40c54..d58b841a67b88 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -15,6 +15,17 @@ static void adxl345_fifo_flush_rtio(const struct device *dev); /* auxiliary functions */ +static void adxl345_sqe_done(const struct device *dev, + struct rtio_iodev_sqe *iodev_sqe, int res) +{ + if (res < 0) { + LOG_WRN("res == %d < 0)", res); + rtio_iodev_sqe_err(iodev_sqe, res); + } else { + rtio_iodev_sqe_ok(iodev_sqe, res); + } + adxl345_set_gpios_en(dev, true); +} /* streaming callbacks and calls */ @@ -36,11 +47,7 @@ static void adxl345_fifo_read_cb(struct rtio *rtio_ctx, const struct rtio_sqe *s struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; struct rtio_iodev_sqe *iodev_sqe = sqe->userdata; - if (data->fifo_entries == 0) { - rtio_iodev_sqe_ok(iodev_sqe, 0); - adxl345_set_gpios_en(dev, true); - } - + adxl345_sqe_done(dev, iodev_sqe, data->fifo_entries); } static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sqe *sqe, @@ -74,9 +81,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq if (rtio_sqe_rx_buf(current_sqe, min_read_size, ideal_read_size, &buf, &buf_len) != 0) { LOG_ERR("Failed to get buffer"); - rtio_iodev_sqe_err(current_sqe, -ENOMEM); - adxl345_set_gpios_en(dev, true); - return; + goto err; } LOG_DBG("Requesting buffer [%u, %u] got %u", (unsigned int)min_read_size, (unsigned int)ideal_read_size, buf_len); @@ -125,8 +130,7 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq /* Bail/cancel attempt to read sensor on any error */ if (res != 0) { - rtio_iodev_sqe_err(current_sqe, res); - return; + goto err; } @@ -157,6 +161,11 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq rtio_submit(data->rtio_ctx, 0); ARG_UNUSED(rtio_cqe_consume(data->rtio_ctx)); } + + return; +err: + LOG_WRN("Failed."); + adxl345_sqe_done(dev, current_sqe, -ENOMEM); } static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sqe, @@ -178,11 +187,11 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq read_config = (struct sensor_read_config *)data->sqe->sqe.iodev->data; if (read_config == NULL) { - return; + goto err; } if (read_config->is_streaming == false) { - return; + goto err; } adxl345_set_gpios_en(dev, false); @@ -203,8 +212,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq } if (!fifo_full_irq) { - adxl345_set_gpios_en(dev, true); - return; + goto err; } /* Flush completions */ @@ -224,8 +232,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq /* Bail/cancel attempt to read sensor on any error */ if (res != 0) { - rtio_iodev_sqe_err(current_sqe, res); - return; + goto err; } enum sensor_stream_data_opt data_opt; @@ -242,9 +249,7 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq data->sqe = NULL; if (rtio_sqe_rx_buf(current_sqe, sizeof(struct adxl345_fifo_data), sizeof(struct adxl345_fifo_data), &buf, &buf_len) != 0) { - rtio_iodev_sqe_err(current_sqe, -ENOMEM); - adxl345_set_gpios_en(dev, true); - return; + goto err; } struct adxl345_fifo_data *rx_data = (struct adxl345_fifo_data *)buf; @@ -254,14 +259,13 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq rx_data->timestamp = data->timestamp; rx_data->int_status = status1; rx_data->fifo_byte_count = 0; - rtio_iodev_sqe_ok(current_sqe, 0); if (data_opt == SENSOR_STREAM_DATA_DROP) { /* Flush the FIFO by disabling it. Save current mode for after the reset. */ adxl345_fifo_flush_rtio(dev); } - adxl345_set_gpios_en(dev, true); + adxl345_sqe_done(dev, current_sqe, 0); return; } @@ -282,6 +286,11 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq current_sqe); rtio_submit(data->rtio_ctx, 0); + + return; +err: + LOG_WRN("Failed."); + adxl345_sqe_done(dev, current_sqe, -ENOMEM); } static void adxl345_fifo_flush_rtio(const struct device *dev) @@ -366,6 +375,7 @@ void adxl345_stream_irq_handler(const struct device *dev) { struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; + struct rtio_iodev_sqe *current_sqe = data->sqe; uint64_t cycles; int rc; @@ -376,8 +386,7 @@ void adxl345_stream_irq_handler(const struct device *dev) rc = sensor_clock_get_cycles(&cycles); if (rc != 0) { LOG_ERR("Failed to get sensor clock cycles"); - rtio_iodev_sqe_err(data->sqe, rc); - return; + goto err; } data->timestamp = sensor_clock_cycles_to_ns(cycles); @@ -399,4 +408,9 @@ void adxl345_stream_irq_handler(const struct device *dev) } rtio_sqe_prep_callback(check_status_reg, adxl345_process_status1_cb, (void *)dev, NULL); rtio_submit(data->rtio_ctx, 0); + + return; +err: + LOG_WRN("Failed."); + adxl345_sqe_done(dev, current_sqe, -ENOMEM); } From 00a8fe7215caf980db3f2090319cc15641615636 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 23 Sep 2025 21:40:45 +0200 Subject: [PATCH 36/42] sensor: adxl345: provide generic bus access API 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 --- drivers/sensor/adi/adxl345/adxl345.c | 150 +++++++++++++++++--- drivers/sensor/adi/adxl345/adxl345.h | 21 ++- drivers/sensor/adi/adxl345/adxl345_stream.c | 125 ++++++++-------- 3 files changed, 216 insertions(+), 80 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 99e60772587bd..125c6c3f730fb 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -87,22 +87,111 @@ int adxl345_reg_write(const struct device *dev, uint8_t addr, uint8_t *data, return adxl345_reg_access(dev, ADXL345_WRITE_CMD, addr, data, len); } -int adxl345_reg_read(const struct device *dev, uint8_t addr, uint8_t *data, - uint8_t len) +int adxl345_raw_reg_read(const struct device *dev, uint8_t addr, + uint8_t *data, uint8_t len) { return adxl345_reg_access(dev, ADXL345_READ_CMD, addr, data, len); } -int adxl345_reg_write_byte(const struct device *dev, uint8_t addr, uint8_t val) +int adxl345_reg_read_byte(const struct device *dev, uint8_t addr, uint8_t *buf) + { - return adxl345_reg_write(dev, addr, &val, 1); -} + struct adxl345_dev_data *data = dev->data; -int adxl345_reg_read_byte(const struct device *dev, uint8_t addr, uint8_t *buf) + /* caching for particular config registers */ + switch (addr) { + case ADXL345_POWER_CTL_REG: + *buf = data->cache_reg_power_ctl; + return 0; + case ADXL345_INT_ENABLE_REG: + *buf = data->cache_reg_int_enable; + return 0; + case ADXL345_INT_MAP_REG: + *buf = data->cache_reg_int_map; + return 0; + case ADXL345_DATA_FORMAT_REG: + *buf = data->cache_reg_data_format; + return 0; + case ADXL345_RATE_REG: + *buf = data->cache_reg_rate; + return 0; + case ADXL345_FIFO_CTL_REG: + *buf = data->cache_reg_fifo_ctl; + return 0; + case ADXL345_THRESH_ACT_REG: + *buf = data->cache_reg_act_thresh; + return 0; + default: +#if defined(CONFIG_ADXL345_STREAM) + LOG_DBG("Fall through reading 0x%02x on RTIO might need a %s", + addr, "callback for evaluation!"); + return adxl345_rtio_reg_read(dev, addr, buf, 1, NULL, NULL); +#else + return adxl345_raw_reg_read(dev, addr, buf, 1); +#endif + } +} +int adxl345_reg_write_byte(const struct device *dev, uint8_t addr, uint8_t val) { - return adxl345_reg_read(dev, addr, buf, 1); + struct adxl345_dev_data *data = dev->data; + + /* caching for particular config registers */ + switch (addr) { + case ADXL345_POWER_CTL_REG: + data->cache_reg_power_ctl = val; + break; + case ADXL345_INT_ENABLE_REG: + data->cache_reg_int_enable = val; + break; + case ADXL345_INT_MAP_REG: + data->cache_reg_int_map = val; + break; + case ADXL345_DATA_FORMAT_REG: + data->cache_reg_data_format = val; + break; + case ADXL345_RATE_REG: + data->cache_reg_rate = val; + break; + case ADXL345_FIFO_CTL_REG: + data->cache_reg_fifo_ctl = val; + break; + case ADXL345_THRESH_ACT_REG: + data->cache_reg_act_thresh = val; + break; + default: + break; + } + +#if defined(CONFIG_ADXL345_STREAM) + const struct adxl345_dev_config *cfg = dev->config; + struct rtio_sqe *write_reg_sqe = rtio_sqe_acquire(data->rtio_ctx); + + rtio_sqe_prep_tiny_write(write_reg_sqe, data->iodev, RTIO_PRIO_NORM, + &addr, sizeof(addr), NULL); + write_reg_sqe->flags |= RTIO_SQE_TRANSACTION; + + /* + * Use a tiny write for register and an additional write for register + * content. It's not possible to pass two byte directly as tiny write, + * since the sqe buffer was defined holding just one byte. + */ + struct rtio_sqe *write_buf_sqe = rtio_sqe_acquire(data->rtio_ctx); + + rtio_sqe_prep_tiny_write(write_buf_sqe, data->iodev, RTIO_PRIO_NORM, + &val, sizeof(val), NULL); + + if (cfg->bus_type == ADXL345_BUS_I2C) { + write_buf_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; + } + + rtio_submit(data->rtio_ctx, 2); /* keep control commands blocking */ + + return 0; +#else + return adxl345_reg_write(dev, addr, &val, 1); +#endif } int adxl345_reg_write_mask(const struct device *dev, @@ -175,8 +264,8 @@ int adxl345_flush_fifo(const struct device *dev) sample_number = adxl345_get_fifo_entries(dev); while (sample_number >= 0) { /* Read FIFO entries + 1 sample lines */ - rc = adxl345_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, - ®val, ADXL345_FIFO_SAMPLE_SIZE); + rc = adxl345_raw_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, + ®val, ADXL345_FIFO_SAMPLE_SIZE); if (rc) { return rc; } @@ -314,8 +403,8 @@ int adxl345_read_sample(const struct device *dev, uint8_t axis_data[ADXL345_FIFO_SAMPLE_SIZE]; int rc; - rc = adxl345_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, - axis_data, ADXL345_FIFO_SAMPLE_SIZE); + rc = adxl345_raw_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, + axis_data, ADXL345_FIFO_SAMPLE_SIZE); if (rc < 0) { LOG_ERR("Samples read failed with rc=%d\n", rc); return rc; @@ -474,19 +563,41 @@ static int adxl345_init(const struct device *dev) return -ENODEV; } - rc = adxl345_reg_read_byte(dev, ADXL345_DEVICE_ID_REG, &dev_id); + rc = adxl345_raw_reg_read(dev, ADXL345_DEVICE_ID_REG, &dev_id, 1); if (rc < 0 || dev_id != ADXL345_PART_ID) { LOG_ERR("Read PART ID failed: 0x%x\n", rc); return -ENODEV; } -#if CONFIG_ADXL345_STREAM - rc = adxl345_reg_write_byte(dev, ADXL345_FIFO_CTL_REG, ADXL345_FIFO_STREAM_MODE); - if (rc < 0) { - LOG_ERR("FIFO enable failed\n"); - return -EIO; + /* + * Preset used config registers and init caches in order to use bit + * changes also for STREAM mode in a more efficient way + */ + rc = adxl345_reg_write_byte(dev, ADXL345_POWER_CTL_REG, 0x00); + if (rc) { + return rc; } -#endif + + rc = adxl345_reg_write_byte(dev, ADXL345_INT_ENABLE_REG, 0x00); + if (rc) { + return rc; + } + + rc = adxl345_reg_write_byte(dev, ADXL345_INT_MAP_REG, 0x00); + if (rc) { + return rc; + } + + rc = adxl345_reg_write_byte(dev, ADXL345_RATE_REG, 0x00); + if (rc) { + return rc; + } + + rc = adxl345_reg_write_byte(dev, ADXL345_FIFO_CTL_REG, ADXL345_FIFO_CTL_MODE_BYPASSED); + if (rc) { + return rc; + } + data->selected_range = ADXL345_RANGE_8G; data->is_full_res = true; @@ -532,9 +643,8 @@ static int adxl345_init(const struct device *dev) * soldered. Anyway, for individual interrupt mapping, set up * DTB bindings. */ - uint8_t int_mask = UCHAR_MAX; - rc = adxl345_reg_assign_bits(dev, ADXL345_INT_MAP_REG, int_mask, + rc = adxl345_reg_assign_bits(dev, ADXL345_INT_MAP_REG, UCHAR_MAX, (cfg->drdy_pad == 2)); if (rc) { return rc; diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 8c77014af094e..2e92655162745 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -35,7 +35,8 @@ #define ADXL345_READ_CMD 0x80 #define ADXL345_MULTIBYTE_FLAG 0x40 -#define ADXL345_REG_READ(x) ((x & 0xFF) | ADXL345_READ_CMD) +#define ADXL345_REG_READ(x) (FIELD_GET(UCHAR_MAX, x) | ADXL345_READ_CMD) +#define ADXL345_REG_READ_MULTIBYTE(x) (ADXL345_REG_READ(x) | ADXL345_MULTIBYTE_FLAG) #define ADXL345_FIFO_SAMPLE_SIZE 6 #define ADXL345_FIFO_ENTRIES_MSK GENMASK(5, 0) /* FIFO status entries */ @@ -184,6 +185,13 @@ struct adxl345_sample { } __attribute__((__packed__)); struct adxl345_dev_data { + uint8_t cache_reg_power_ctl; + uint8_t cache_reg_int_enable; + uint8_t cache_reg_int_map; + uint8_t cache_reg_data_format; + uint8_t cache_reg_rate; + uint8_t cache_reg_fifo_ctl; + uint8_t cache_reg_act_thresh; struct adxl345_sample sample[ADXL345_MAX_FIFO_SIZE]; uint8_t fifo_entries; /* the actual read FIFO entries */ uint8_t sample_idx; /* index counting up sample_number entries */ @@ -295,8 +303,11 @@ int adxl345_reg_access(const struct device *dev, uint8_t cmd, uint8_t addr, int adxl345_reg_write(const struct device *dev, uint8_t addr, uint8_t *data, uint8_t len); -int adxl345_reg_read(const struct device *dev, uint8_t addr, uint8_t *data, - uint8_t len); +#if defined(CONFIG_ADXL345_STREAM) +int adxl345_rtio_reg_read(const struct device *dev, uint8_t reg, + uint8_t *buf, size_t buflen, void *userdata, + rtio_callback_t cb); +#endif int adxl345_reg_write_byte(const struct device *dev, uint8_t addr, uint8_t val); @@ -314,4 +325,8 @@ int adxl345_configure_fifo(const struct device *dev, enum adxl345_fifo_mode mode #ifdef CONFIG_ADXL345_STREAM size_t adxl345_get_packet_size(const struct adxl345_dev_config *cfg); #endif /* CONFIG_ADXL345_STREAM */ + +int adxl345_raw_reg_read(const struct device *dev, uint8_t addr, uint8_t *data, + uint8_t len); + #endif /* ZEPHYR_DRIVERS_SENSOR_ADX345_ADX345_H_ */ diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index d58b841a67b88..1c3c64abba22f 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -15,6 +15,55 @@ static void adxl345_fifo_flush_rtio(const struct device *dev); /* auxiliary functions */ +int adxl345_rtio_reg_read(const struct device *dev, uint8_t reg, + uint8_t *buf, size_t buflen, void *userdata, + rtio_callback_t cb) +{ + struct adxl345_dev_data *data = (struct adxl345_dev_data *)dev->data; + const struct adxl345_dev_config *cfg = dev->config; + uint8_t r = buflen > 1 ? ADXL345_REG_READ_MULTIBYTE(reg) : ADXL345_REG_READ(reg); + struct rtio_sqe *write_sqe = rtio_sqe_acquire(data->rtio_ctx); + + if (!write_sqe) { + LOG_WRN("write_sqe failed"); + goto err; + } + rtio_sqe_prep_tiny_write(write_sqe, data->iodev, RTIO_PRIO_NORM, &r, + sizeof(r), NULL); + write_sqe->flags |= RTIO_SQE_TRANSACTION; + + struct rtio_sqe *read_sqe = rtio_sqe_acquire(data->rtio_ctx); + + if (!read_sqe) { + LOG_WRN("read_sqe failed"); + goto err; + } + + rtio_sqe_prep_read(read_sqe, data->iodev, RTIO_PRIO_NORM, + buf, buflen, userdata); + + if (cfg->bus_type == ADXL345_BUS_I2C) { + read_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; + } + + if (cb) { + read_sqe->flags |= RTIO_SQE_CHAINED; + struct rtio_sqe *check_status_sqe = rtio_sqe_acquire(data->rtio_ctx); + + if (!check_status_sqe) { + LOG_WRN("check_status_sqe failed"); + goto err; + } + rtio_sqe_prep_callback_no_cqe(check_status_sqe, cb, (void *)dev, + userdata); + } + + return rtio_submit(data->rtio_ctx, 0); +err: + LOG_WRN("low on memory"); + return -ENOMEM; +} + static void adxl345_sqe_done(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe, int res) { @@ -57,7 +106,6 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq const struct device *dev = (const struct device *)arg; struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; - const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *current_sqe = data->sqe; data->fifo_entries = FIELD_GET(ADXL345_FIFO_ENTRIES_MSK, data->reg_fifo_status); uint8_t fifo_entries = data->fifo_entries; @@ -136,29 +184,13 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq for (size_t i = 0; i < fifo_entries; i++) { data->fifo_entries--; - struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); - struct rtio_sqe *read_fifo_data = rtio_sqe_acquire(data->rtio_ctx); - - const uint8_t reg_addr = ADXL345_REG_READ(ADXL345_REG_DATA_XYZ_REGS) - | ADXL345_MULTIBYTE_FLAG; - - rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, ®_addr, - 1, NULL); - write_fifo_addr->flags |= RTIO_SQE_TRANSACTION; - rtio_sqe_prep_read(read_fifo_data, data->iodev, RTIO_PRIO_NORM, - (read_buf + i * ADXL345_FIFO_SAMPLE_SIZE), - ADXL345_FIFO_SAMPLE_SIZE, current_sqe); - if (cfg->bus_type == ADXL345_BUS_I2C) { - read_fifo_data->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; - } - if (i == fifo_entries - 1) { - struct rtio_sqe *complete_op = rtio_sqe_acquire(data->rtio_ctx); - - read_fifo_data->flags |= RTIO_SQE_CHAINED; - rtio_sqe_prep_callback(complete_op, adxl345_fifo_read_cb, (void *)dev, - current_sqe); + if (adxl345_rtio_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, + (read_buf + i * ADXL345_FIFO_SAMPLE_SIZE), + ADXL345_FIFO_SAMPLE_SIZE, current_sqe, + (i == fifo_entries - 1) ? adxl345_fifo_read_cb : NULL)) { + LOG_WRN("RTIO reading the XYZ regs failed"); + goto err; } - rtio_submit(data->rtio_ctx, 0); ARG_UNUSED(rtio_cqe_consume(data->rtio_ctx)); } @@ -175,7 +207,6 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq const struct device *dev = (const struct device *)arg; struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; - const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *current_sqe = data->sqe; struct sensor_read_config *read_config; uint8_t status1 = data->reg_int_source; @@ -269,23 +300,12 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq return; } - struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); - struct rtio_sqe *read_fifo_data = rtio_sqe_acquire(data->rtio_ctx); - struct rtio_sqe *complete_op = rtio_sqe_acquire(data->rtio_ctx); - const uint8_t reg_addr = ADXL345_REG_READ(ADXL345_FIFO_STATUS_REG); - - rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, ®_addr, 1, NULL); - write_fifo_addr->flags |= RTIO_SQE_TRANSACTION; - rtio_sqe_prep_read(read_fifo_data, data->iodev, RTIO_PRIO_NORM, &data->reg_fifo_status, - sizeof(data->reg_fifo_status), current_sqe); - read_fifo_data->flags |= RTIO_SQE_CHAINED; - if (cfg->bus_type == ADXL345_BUS_I2C) { - read_fifo_data->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; + if (adxl345_rtio_reg_read(dev, ADXL345_FIFO_STATUS_REG, &data->reg_fifo_status, + sizeof(data->reg_fifo_status), current_sqe, + adxl345_process_fifo_samples_cb)) { + LOG_WRN("Reading the FIFO samples failed"); + goto err; } - rtio_sqe_prep_callback(complete_op, adxl345_process_fifo_samples_cb, (void *)dev, - current_sqe); - - rtio_submit(data->rtio_ctx, 0); return; err: @@ -374,7 +394,6 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode void adxl345_stream_irq_handler(const struct device *dev) { struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; - const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config; struct rtio_iodev_sqe *current_sqe = data->sqe; uint64_t cycles; int rc; @@ -390,24 +409,16 @@ void adxl345_stream_irq_handler(const struct device *dev) } data->timestamp = sensor_clock_cycles_to_ns(cycles); - struct rtio_sqe *write_status_addr = rtio_sqe_acquire(data->rtio_ctx); - struct rtio_sqe *read_status_reg = rtio_sqe_acquire(data->rtio_ctx); - struct rtio_sqe *check_status_reg = rtio_sqe_acquire(data->rtio_ctx); - uint8_t reg = ADXL345_REG_READ(ADXL345_INT_SOURCE_REG); - - rtio_sqe_prep_tiny_write(write_status_addr, data->iodev, - RTIO_PRIO_NORM, ®, sizeof(reg), NULL); - write_status_addr->flags |= RTIO_SQE_TRANSACTION; - rtio_sqe_prep_read(read_status_reg, data->iodev, RTIO_PRIO_NORM, - &data->reg_int_source, sizeof(data->reg_int_source), - NULL); - read_status_reg->flags |= RTIO_SQE_CHAINED; - if (cfg->bus_type == ADXL345_BUS_I2C) { - read_status_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; + if (adxl345_rtio_reg_read(dev, ADXL345_INT_SOURCE_REG, + &data->reg_int_source, + sizeof(data->reg_int_source), + NULL, adxl345_process_status1_cb)) { + LOG_ERR("Processing the FIFO status failed"); + goto err; } - rtio_sqe_prep_callback(check_status_reg, adxl345_process_status1_cb, (void *)dev, NULL); - rtio_submit(data->rtio_ctx, 0); + + adxl345_sqe_done(dev, current_sqe, 0); return; err: From 98ec77b3c4c1f53916eb992cfa49ad04f1556ef0 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 23 Sep 2025 23:08:21 +0200 Subject: [PATCH 37/42] sensor: adxl345: factor out initialization of the stream header 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 --- drivers/sensor/adi/adxl345/adxl345_stream.c | 92 +++++++++++---------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 1c3c64abba22f..e177e177a76e2 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -76,6 +76,52 @@ static void adxl345_sqe_done(const struct device *dev, adxl345_set_gpios_en(dev, true); } +static void adxl345_rtio_init_hdr(struct adxl345_fifo_data *hdr, + struct adxl345_dev_data *data, + uint32_t fifo_byte_count) +{ + hdr->is_fifo = 1; + hdr->timestamp = data->timestamp; + hdr->int_status = data->reg_int_source; + hdr->is_full_res = data->is_full_res; + hdr->selected_range = data->selected_range; + hdr->accel_odr = data->odr; + hdr->sample_set_size = ADXL345_FIFO_SAMPLE_SIZE; + + hdr->fifo_byte_count = fifo_byte_count; +} + +static int adxl345_rtio_init_buffer(struct adxl345_dev_data *data, + uint8_t **read_buf, uint16_t fifo_bytes, + struct rtio_iodev_sqe *current_iodev_sqe) +{ + const size_t min_read_size = sizeof(struct adxl345_fifo_data) + ADXL345_FIFO_SAMPLE_SIZE; + const size_t ideal_read_size = sizeof(struct adxl345_fifo_data) + fifo_bytes; + uint8_t *buf; + uint32_t buf_avail, buf_length; + + if (rtio_sqe_rx_buf(current_iodev_sqe, min_read_size, ideal_read_size, &buf, + &buf_length)) { + LOG_ERR("Failed to get buffer"); + return -EINVAL; + } + buf_avail = buf_length - sizeof(struct adxl345_fifo_data); + uint32_t read_len = MIN(fifo_bytes, buf_avail); + + if (buf_avail < fifo_bytes) { + uint32_t pkts = read_len / ADXL345_FIFO_SAMPLE_SIZE; + + read_len = pkts * ADXL345_FIFO_SAMPLE_SIZE; + } + + __ASSERT_NO_MSG(read_len % ADXL345_FIFO_SAMPLE_SIZE == 0); + adxl345_rtio_init_hdr((struct adxl345_fifo_data *)buf, data, read_len); + + *read_buf = buf + sizeof(struct adxl345_fifo_data); + + return 0; +} + /* streaming callbacks and calls */ static void adxl345_irq_en_cb(struct rtio *r, const struct rtio_sqe *sqe, int result, void *arg) @@ -109,7 +155,6 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq struct rtio_iodev_sqe *current_sqe = data->sqe; data->fifo_entries = FIELD_GET(ADXL345_FIFO_ENTRIES_MSK, data->reg_fifo_status); uint8_t fifo_entries = data->fifo_entries; - size_t sample_set_size = ADXL345_FIFO_SAMPLE_SIZE; uint16_t fifo_bytes = fifo_entries * ADXL345_FIFO_SAMPLE_SIZE; data->sqe = NULL; @@ -121,45 +166,11 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq return; } - const size_t min_read_size = sizeof(struct adxl345_fifo_data) + sample_set_size; - const size_t ideal_read_size = sizeof(struct adxl345_fifo_data) + fifo_bytes; - - uint8_t *buf; - uint32_t buf_len; + uint8_t *read_buf; - if (rtio_sqe_rx_buf(current_sqe, min_read_size, ideal_read_size, &buf, &buf_len) != 0) { - LOG_ERR("Failed to get buffer"); + if (adxl345_rtio_init_buffer(data, &read_buf, fifo_bytes, current_sqe)) { goto err; } - LOG_DBG("Requesting buffer [%u, %u] got %u", (unsigned int)min_read_size, - (unsigned int)ideal_read_size, buf_len); - - /* Read FIFO and call back to rtio with rtio_sqe completion */ - struct adxl345_fifo_data *hdr = (struct adxl345_fifo_data *) buf; - - hdr->is_fifo = 1; - hdr->timestamp = data->timestamp; - hdr->int_status = data->reg_int_source; - hdr->is_full_res = data->is_full_res; - hdr->selected_range = data->selected_range; - hdr->accel_odr = data->odr; - hdr->sample_set_size = sample_set_size; - - uint32_t buf_avail = buf_len; - - buf_avail -= sizeof(*hdr); - - uint32_t read_len = MIN(fifo_bytes, buf_avail); - - if (buf_avail < fifo_bytes) { - uint32_t pkts = read_len / sample_set_size; - - read_len = pkts * sample_set_size; - } - - ((struct adxl345_fifo_data *)buf)->fifo_byte_count = read_len; - - uint8_t *read_buf = buf + sizeof(*hdr); /* Flush completions */ struct rtio_cqe *cqe; @@ -283,13 +294,8 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq goto err; } - struct adxl345_fifo_data *rx_data = (struct adxl345_fifo_data *)buf; - memset(buf, 0, buf_len); - rx_data->is_fifo = 1; - rx_data->timestamp = data->timestamp; - rx_data->int_status = status1; - rx_data->fifo_byte_count = 0; + adxl345_rtio_init_hdr((struct adxl345_fifo_data *)buf, data, 0); if (data_opt == SENSOR_STREAM_DATA_DROP) { /* Flush the FIFO by disabling it. Save current mode for after the reset. */ From d45b662d4849ed5f4f869f93dd300b999c3c7e65 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 23 Sep 2025 23:32:44 +0200 Subject: [PATCH 38/42] sensor: adxl345: factor out consumption of CQEs 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 --- drivers/sensor/adi/adxl345/adxl345_stream.c | 63 +++++++++------------ 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index e177e177a76e2..ca88aaec9c424 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -122,6 +122,25 @@ static int adxl345_rtio_init_buffer(struct adxl345_dev_data *data, return 0; } +static int adxl345_rtio_cqe_consume(struct adxl345_dev_data *data) +{ + struct rtio_cqe *cqe = rtio_cqe_consume(data->rtio_ctx); + int res = 0; + + do { + cqe = rtio_cqe_consume(data->rtio_ctx); + if (cqe) { + if ((cqe->result < 0 && res == 0)) { + LOG_ERR("Bus error: %d", cqe->result); + res = cqe->result; + } + rtio_cqe_release(data->rtio_ctx, cqe); + } + } while (cqe); + + return res; +} + /* streaming callbacks and calls */ static void adxl345_irq_en_cb(struct rtio *r, const struct rtio_sqe *sqe, int result, void *arg) @@ -173,26 +192,10 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq } /* Flush completions */ - struct rtio_cqe *cqe; - int res = 0; - - do { - cqe = rtio_cqe_consume(data->rtio_ctx); - if (cqe != NULL) { - if ((cqe->result < 0 && res == 0)) { - LOG_ERR("Bus error: %d", cqe->result); - res = cqe->result; - } - rtio_cqe_release(data->rtio_ctx, cqe); - } - } while (cqe != NULL); - - /* Bail/cancel attempt to read sensor on any error */ - if (res != 0) { + if (adxl345_rtio_cqe_consume(data)) { goto err; } - for (size_t i = 0; i < fifo_entries; i++) { data->fifo_entries--; if (adxl345_rtio_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, @@ -257,32 +260,18 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq goto err; } - /* Flush completions */ - struct rtio_cqe *cqe; - int res = 0; - - do { - cqe = rtio_cqe_consume(data->rtio_ctx); - if (cqe != NULL) { - if ((cqe->result < 0) && (res == 0)) { - LOG_ERR("Bus error: %d", cqe->result); - res = cqe->result; - } - rtio_cqe_release(data->rtio_ctx, cqe); - } - } while (cqe != NULL); - - /* Bail/cancel attempt to read sensor on any error */ - if (res != 0) { - goto err; - } - enum sensor_stream_data_opt data_opt; if (fifo_wmark_cfg != NULL) { data_opt = fifo_wmark_cfg->opt; } + /* Flush completions, in case cancel out */ + if (adxl345_rtio_cqe_consume(data)) { + LOG_WRN("CQE consume failed"); + goto err; + } + if (data_opt == SENSOR_STREAM_DATA_NOP || data_opt == SENSOR_STREAM_DATA_DROP) { uint8_t *buf; uint32_t buf_len; From d0cd81faddd07b82f4555964bed5ffa15139baf6 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Tue, 23 Sep 2025 23:46:12 +0200 Subject: [PATCH 39/42] sensor: adxl345: move streaming checks to separate function Introduce adxl345_check_streaming() in the stream/RTIO implementation to handle the standard streaming check routines. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345_stream.c | 39 ++++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index ca88aaec9c424..aaa7425e8e94f 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -141,6 +141,30 @@ static int adxl345_rtio_cqe_consume(struct adxl345_dev_data *data) return res; } +static int adxl345_check_streaming(struct adxl345_dev_data *data, + struct sensor_read_config **ptr_read_config) +{ + if (!data->sqe) { + LOG_ERR("data->iodev_sqe was NULL"); + return false; + } + + *ptr_read_config = (struct sensor_read_config *)data->sqe->sqe.iodev->data; + struct sensor_read_config *read_config = *ptr_read_config; + + if (!read_config) { + LOG_WRN("read_config was NULL"); + return false; + } + + if (!read_config->is_streaming) { + LOG_WRN("is_streaming of read_config was false/NULL"); + return false; + } + + return true; +} + /* streaming callbacks and calls */ static void adxl345_irq_en_cb(struct rtio *r, const struct rtio_sqe *sqe, int result, void *arg) @@ -225,22 +249,11 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq struct sensor_read_config *read_config; uint8_t status1 = data->reg_int_source; - if (data->sqe == NULL) { + if (!adxl345_check_streaming(data, &read_config)) { + LOG_WRN("Failed! RTIO not setup for streaming"); return; } - read_config = (struct sensor_read_config *)data->sqe->sqe.iodev->data; - - if (read_config == NULL) { - goto err; - } - - if (read_config->is_streaming == false) { - goto err; - } - - adxl345_set_gpios_en(dev, false); - struct sensor_stream_trigger *fifo_wmark_cfg = NULL; for (int i = 0; i < read_config->count; ++i) { From a2b87701e12a1159086c7f53789adff1295bab9c Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Wed, 24 Sep 2025 00:02:56 +0200 Subject: [PATCH 40/42] sensor: adxl345: rework flushing the fifo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- drivers/sensor/adi/adxl345/adxl345.c | 47 +++++-- drivers/sensor/adi/adxl345/adxl345.h | 5 +- drivers/sensor/adi/adxl345/adxl345_stream.c | 141 +++++++++++-------- drivers/sensor/adi/adxl345/adxl345_trigger.c | 4 +- 4 files changed, 128 insertions(+), 69 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 125c6c3f730fb..c9b5ef2290c05 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -250,11 +250,10 @@ int adxl345_get_status(const struct device *dev, uint8_t *status) return adxl345_reg_read_byte(dev, ADXL345_INT_SOURCE_REG, status); } -int adxl345_flush_fifo(const struct device *dev) +int adxl345_raw_flush_fifo(const struct device *dev) { -#ifdef CONFIG_ADXL345_TRIGGER - int8_t sample_number; - uint8_t regval; +#if defined(CONFIG_ADXL345_TRIGGER) + uint8_t sample_line[ADXL345_FIFO_SAMPLE_SIZE]; int rc; rc = adxl345_set_measure_en(dev, false); @@ -262,15 +261,43 @@ int adxl345_flush_fifo(const struct device *dev) return rc; } - sample_number = adxl345_get_fifo_entries(dev); - while (sample_number >= 0) { /* Read FIFO entries + 1 sample lines */ - rc = adxl345_raw_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, - ®val, ADXL345_FIFO_SAMPLE_SIZE); - if (rc) { + while (true) { + rc = adxl345_get_fifo_entries(dev); + if (rc < 0) { return rc; } - sample_number--; + if (rc == 0) { + break; + } + + /* + * For FIFO_MODE_TRIGGERED (re)setting the FIFO to BYPASSED and back to + * TRIGGERED is enough to reset just the FIFO (as described on p.21 of + * the data sheet). In this case measurement and optionally GPIO lines, + * too, need to be turned off in forehand and turned on again + * afterwards. + * + * When FIFO_MODE_STREAMED is in place, reading out the FIFO elements + * actually resets the FIFO and resets also the particular interrupt + * trigger in INT_SOURCE register e.g. such as watermark, tap events, + * activity, etc. Resetting a STREAMED FIFO is supposed to happen while + * the sensor continues running. Thus measurement is not supposed to be + * turned off except in case of overrun i.e. error. In this case, just + * switching to BYPASSED does not reset any the INT_SOURCE bit flags. + * Therefore the entries must be read. + */ + uint8_t fifo_entries = rc + 1; + + while (fifo_entries > 0) { /* Read FIFO entries + 1 sample lines */ + rc = adxl345_raw_reg_read(dev, ADXL345_REG_DATA_XYZ_REGS, + sample_line, ADXL345_FIFO_SAMPLE_SIZE); + if (rc) { + return rc; + } + + fifo_entries--; + } } #endif /* CONFIG_ADXL345_TRIGGER */ diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 2e92655162745..cd99935c5cf9d 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -272,10 +272,13 @@ struct adxl345_dev_config { int adxl345_set_gpios_en(const struct device *dev, bool enable); int adxl345_set_measure_en(const struct device *dev, bool en); -int adxl345_flush_fifo(const struct device *dev); +int adxl345_raw_flush_fifo(const struct device *dev); +#ifdef CONFIG_ADXL345_STREAM +int adxl345_rtio_flush_fifo(const struct device *dev); void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); void adxl345_stream_irq_handler(const struct device *dev); +#endif #ifdef CONFIG_ADXL345_TRIGGER int adxl345_get_fifo_entries(const struct device *dev); diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index aaa7425e8e94f..6006a21b4c816 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -11,8 +11,6 @@ LOG_MODULE_DECLARE(ADXL345, CONFIG_SENSOR_LOG_LEVEL); -static void adxl345_fifo_flush_rtio(const struct device *dev); - /* auxiliary functions */ int adxl345_rtio_reg_read(const struct device *dev, uint8_t reg, @@ -167,15 +165,6 @@ static int adxl345_check_streaming(struct adxl345_dev_data *data, /* streaming callbacks and calls */ -static void adxl345_irq_en_cb(struct rtio *r, const struct rtio_sqe *sqe, int result, void *arg) -{ - ARG_UNUSED(result); - - const struct device *dev = (const struct device *)arg; - - adxl345_set_gpios_en(dev, true); -} - static void adxl345_fifo_read_cb(struct rtio *rtio_ctx, const struct rtio_sqe *sqe, int result, void *arg) { @@ -300,8 +289,11 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq adxl345_rtio_init_hdr((struct adxl345_fifo_data *)buf, data, 0); if (data_opt == SENSOR_STREAM_DATA_DROP) { - /* Flush the FIFO by disabling it. Save current mode for after the reset. */ - adxl345_fifo_flush_rtio(dev); + /* + * Flush the FIFO by disabling it. Save current mode + * for after the reset. + */ + adxl345_rtio_flush_fifo(dev); } adxl345_sqe_done(dev, current_sqe, 0); @@ -321,50 +313,107 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq adxl345_sqe_done(dev, current_sqe, -ENOMEM); } -static void adxl345_fifo_flush_rtio(const struct device *dev) +/** + * adxl345_rtio_flush_fifo - Reset the FIFO and interrupt status registers. + * @dev The device node. + * + * Consume all FIFO elements, since this not just resets FIFO_STATUS, but also INT_SOURCE entries. + * When using Analog's STREAM FIFO mode, FIFO elements must be consumed. For Analog's + * TRIGGER FIFO mode, it would be sufficient to switch FIFO modes to BYPASS FIFO mode and + * back to Analog's STREAM FIFO mode, since in this mode, the FIFO gets only activated once if the + * trigger bit of the sensor is set by one of the sensor events, i.e. in terms of Analog Devices a + * "trigger event". The INT SOURCE does not need to be reset here, but using the sensor in a + * permanent sensing mode, such as Analog's STREAM FIFO mode requires a reset of the INT_SOURCE + * register, too. Thus, it is required to consume the FIFO elements. + * + * @return 0 for success, or error number. + */ +int adxl345_rtio_flush_fifo(const struct device *dev) { struct adxl345_dev_data *data = dev->data; - uint8_t fifo_config; + struct rtio_iodev_sqe *current_sqe = data->sqe; + int8_t fifo_entries = ADXL345_MAX_FIFO_SIZE; + struct sensor_read_config *read_config = NULL; - fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | - adxl345_fifo_ctl_mode_init[ADXL345_FIFO_BYPASSED] | - data->fifo_config.fifo_samples; + if (!adxl345_check_streaming(data, &read_config)) { + LOG_WRN("adxl345_check_streaming() failed"); + return 0; + } - struct rtio_sqe *write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); - const uint8_t reg_addr_w2[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; + if (adxl345_rtio_cqe_consume(data)) { + LOG_WRN("adxl345_rtio_cqe_consume() failed"); + goto err; + } - rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, - reg_addr_w2, 2, NULL); + if (adxl345_set_measure_en(dev, false)) { + LOG_WRN("adxl345_set_measure_en() failed"); + goto err; + } - fifo_config = ADXL345_FIFO_CTL_TRIGGER_UNSET | - adxl345_fifo_ctl_mode_init[data->fifo_config.fifo_mode] | - data->fifo_config.fifo_samples; + const struct adxl345_dev_config *cfg = dev->config; + uint8_t reg = ADXL345_REG_DATA_XYZ_REGS; + uint8_t reg_addr = ADXL345_REG_READ_MULTIBYTE(reg); + size_t buflen = ADXL345_FIFO_SAMPLE_SIZE; - write_fifo_addr = rtio_sqe_acquire(data->rtio_ctx); - const uint8_t reg_addr_w3[2] = {ADXL345_FIFO_CTL_REG, fifo_config}; + for (size_t i = 0; i < fifo_entries; i++) { + uint8_t dummy[6]; + uint8_t *buf = dummy; + struct rtio_sqe *write_sqe = rtio_sqe_acquire(data->rtio_ctx); - rtio_sqe_prep_tiny_write(write_fifo_addr, data->iodev, RTIO_PRIO_NORM, - reg_addr_w3, 2, NULL); - write_fifo_addr->flags |= RTIO_SQE_CHAINED; + if (!write_sqe) { + LOG_WRN("write_sqe failed"); + goto err; + } + rtio_sqe_prep_tiny_write(write_sqe, data->iodev, + RTIO_PRIO_NORM, ®_addr, + sizeof(reg_addr), NULL); + write_sqe->flags |= RTIO_SQE_TRANSACTION; - struct rtio_sqe *complete_op = rtio_sqe_acquire(data->rtio_ctx); + struct rtio_sqe *read_sqe = rtio_sqe_acquire(data->rtio_ctx); - rtio_sqe_prep_callback(complete_op, adxl345_irq_en_cb, (void *)dev, NULL); - rtio_submit(data->rtio_ctx, 0); + if (!read_sqe) { + LOG_WRN("read_sqe failed"); + goto err; + } + rtio_sqe_prep_read(read_sqe, data->iodev, RTIO_PRIO_NORM, + buf, buflen, + current_sqe); + + if (cfg->bus_type == ADXL345_BUS_I2C) { + read_sqe->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; + } + rtio_submit(data->rtio_ctx, 2); /* cautiously keep blocking */ + ARG_UNUSED(rtio_cqe_consume(data->rtio_ctx)); + } + + if (adxl345_set_measure_en(dev, true)) { + LOG_WRN("adxl345_set_measure_en() failed"); + goto err; + } + + return 0; +err: + LOG_WRN("Failed."); + return -EINVAL; } /* Consumer calls */ +static bool first = true; void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = (const struct sensor_read_config *)iodev_sqe->sqe.iodev->data; struct adxl345_dev_data *data = (struct adxl345_dev_data *)dev->data; - uint8_t status; int rc; - if (adxl345_set_gpios_en(dev, false)) { - return; + data->sqe = iodev_sqe; + + if (first) { + /* Initialize measurement and start with flushed registers */ + adxl345_rtio_flush_fifo(dev); + adxl345_set_gpios_en(dev, true); + first = false; } for (size_t i = 0; i < cfg->count; i++) { @@ -376,27 +425,7 @@ void adxl345_submit_stream(const struct device *dev, struct rtio_iodev_sqe *iode return; } } - - /* Flush the FIFO by disabling it. Save current mode for after the reset. */ - enum adxl345_fifo_mode current_fifo_mode = data->fifo_config.fifo_mode; - - if (current_fifo_mode == ADXL345_FIFO_BYPASSED) { - current_fifo_mode = ADXL345_FIFO_STREAMED; - } - adxl345_configure_fifo(dev, ADXL345_FIFO_BYPASSED, - data->fifo_config.fifo_trigger, - data->fifo_config.fifo_samples); - adxl345_configure_fifo(dev, current_fifo_mode, - data->fifo_config.fifo_trigger, - data->fifo_config.fifo_samples); - rc = adxl345_reg_read_byte(dev, ADXL345_FIFO_STATUS_REG, &status); - } - - if (adxl345_set_gpios_en(dev, true)) { - return; } - - data->sqe = iodev_sqe; } void adxl345_stream_irq_handler(const struct device *dev) diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index 987792312ee4d..b6da324ce9b9f 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -89,7 +89,7 @@ static void adxl345_thread_cb(const struct device *dev) * If overrun handling is enabled, reset status register and * fifo here, if not handled before in any way */ - adxl345_flush_fifo(dev); + adxl345_raw_flush_fifo(dev); } if (drv_data->act_trigger && FIELD_GET(ADXL345_INT_ACT, status)) { @@ -246,7 +246,7 @@ int adxl345_trigger_set(const struct device *dev, return ret; } - return adxl345_flush_fifo(dev); + return adxl345_raw_flush_fifo(dev); } int adxl345_init_interrupt(const struct device *dev) From f6b7a52755d8c195aeb776f26d4c91ce1d075c92 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Wed, 24 Sep 2025 00:12:12 +0200 Subject: [PATCH 41/42] sensor: adxl345: cover watermark and overrun as sensor events Extends the coverage of sensor events to overrun and watermark for the stream/RTIO implementation. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345_stream.c | 36 ++++++++++----------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 6006a21b4c816..340ee17906079 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -236,7 +236,6 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; struct rtio_iodev_sqe *current_sqe = data->sqe; struct sensor_read_config *read_config; - uint8_t status1 = data->reg_int_source; if (!adxl345_check_streaming(data, &read_config)) { LOG_WRN("Failed! RTIO not setup for streaming"); @@ -244,30 +243,29 @@ static void adxl345_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq } struct sensor_stream_trigger *fifo_wmark_cfg = NULL; + struct sensor_stream_trigger *fifo_full_cfg = NULL; + enum sensor_stream_data_opt data_opt = SENSOR_STREAM_DATA_DROP; for (int i = 0; i < read_config->count; ++i) { - if (read_config->triggers[i].trigger == SENSOR_TRIG_FIFO_WATERMARK) { - fifo_wmark_cfg = &read_config->triggers[i]; + switch (read_config->triggers[i].trigger) { + case SENSOR_TRIG_FIFO_WATERMARK: + if (FIELD_GET(ADXL345_INT_WATERMARK, data->reg_int_source)) { + fifo_wmark_cfg = &read_config->triggers[i]; + data_opt = MIN(data_opt, fifo_wmark_cfg->opt); + } + continue; + case SENSOR_TRIG_FIFO_FULL: + if (FIELD_GET(ADXL345_INT_OVERRUN, data->reg_int_source)) { + fifo_full_cfg = &read_config->triggers[i]; + data_opt = MIN(data_opt, fifo_full_cfg->opt); + } continue; + default: + LOG_WRN("SENSOR_* case not covered"); + goto err; } } - bool fifo_full_irq = false; - - if (fifo_wmark_cfg && FIELD_GET(ADXL345_INT_WATERMARK, status1)) { - fifo_full_irq = true; - } - - if (!fifo_full_irq) { - goto err; - } - - enum sensor_stream_data_opt data_opt; - - if (fifo_wmark_cfg != NULL) { - data_opt = fifo_wmark_cfg->opt; - } - /* Flush completions, in case cancel out */ if (adxl345_rtio_cqe_consume(data)) { LOG_WRN("CQE consume failed"); From 29365ff4c8d086436eb3d5714f33dfb80d8e1e26 Mon Sep 17 00:00:00 2001 From: Lothar Rubusch Date: Wed, 24 Sep 2025 00:14:11 +0200 Subject: [PATCH 42/42] sensor: adxl345: distinguish the stream handler from trigger Restrict the RTIO stream handler to the kconfig condition. Signed-off-by: Lothar Rubusch --- drivers/sensor/adi/adxl345/adxl345_stream.c | 6 ++---- drivers/sensor/adi/adxl345/adxl345_trigger.c | 8 ++++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345_stream.c b/drivers/sensor/adi/adxl345/adxl345_stream.c index 340ee17906079..626a0ba0ab677 100644 --- a/drivers/sensor/adi/adxl345/adxl345_stream.c +++ b/drivers/sensor/adi/adxl345/adxl345_stream.c @@ -431,14 +431,12 @@ void adxl345_stream_irq_handler(const struct device *dev) struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data; struct rtio_iodev_sqe *current_sqe = data->sqe; uint64_t cycles; - int rc; - if (data->sqe == NULL) { + if (!current_sqe) { return; } - rc = sensor_clock_get_cycles(&cycles); - if (rc != 0) { + if (sensor_clock_get_cycles(&cycles)) { LOG_ERR("Failed to get sensor clock cycles"); goto err; } diff --git a/drivers/sensor/adi/adxl345/adxl345_trigger.c b/drivers/sensor/adi/adxl345/adxl345_trigger.c index b6da324ce9b9f..afdfe2e3f873e 100644 --- a/drivers/sensor/adi/adxl345/adxl345_trigger.c +++ b/drivers/sensor/adi/adxl345/adxl345_trigger.c @@ -114,6 +114,10 @@ static void adxl345_int1_gpio_callback(const struct device *dev, adxl345_set_int_pad_state(dev, 1, false); +#if defined(CONFIG_ADXL345_STREAM) + adxl345_stream_irq_handler(drv_data->dev); +#endif + #if defined(CONFIG_ADXL345_TRIGGER_OWN_THREAD) k_sem_give(&drv_data->gpio_sem); #elif defined(CONFIG_ADXL345_TRIGGER_GLOBAL_THREAD) @@ -132,6 +136,10 @@ static void adxl345_int2_gpio_callback(const struct device *dev, adxl345_set_int_pad_state(dev, 2, false); +#if defined(CONFIG_ADXL345_STREAM) + adxl345_stream_irq_handler(drv_data->dev); +#endif + #if defined(CONFIG_ADXL345_TRIGGER_OWN_THREAD) k_sem_give(&drv_data->gpio_sem); #elif defined(CONFIG_ADXL345_TRIGGER_GLOBAL_THREAD)