Skip to content

Commit 0dba8a6

Browse files
committed
bmp581: Add Streaming support
Working only with DRDY Interrupts. FIFO watermark not added yet. Signed-off-by: Luis Ubieda <[email protected]>
1 parent e456684 commit 0dba8a6

File tree

6 files changed

+292
-0
lines changed

6 files changed

+292
-0
lines changed

drivers/sensor/bosch/bmp581/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ zephyr_library_sources(
1313
zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API
1414
bmp581_decoder.c
1515
)
16+
17+
zephyr_library_sources_ifdef(CONFIG_BMP581_STREAM
18+
bmp581_stream.c
19+
)

drivers/sensor/bosch/bmp581/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#
22
# Copyright (c) 2022 Badgerd Technologies B.V and its affiliates
3+
# Copyright (c) 2025 Croxel, Inc.
4+
# Copyright (c) 2025 CogniPilot Foundation
35
#
46
# SPDX-License-Identifier: Apache-2.0
57
#
@@ -10,3 +12,10 @@ config BMP581
1012
select I2C
1113
select I2C_RTIO
1214
default y
15+
16+
config BMP581_STREAM
17+
bool "Streaming mode"
18+
default y
19+
depends on SENSOR_ASYNC_API
20+
depends on GPIO
21+
depends on $(dt_compat_any_has_prop,$(DT_COMPAT_BOSCH_BMP581),int-gpios)

drivers/sensor/bosch/bmp581/bmp581.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "bmp581.h"
99
#include "bmp581_bus.h"
1010
#include "bmp581_decoder.h"
11+
#include "bmp581_stream.h"
1112

1213
#include <math.h>
1314

@@ -584,6 +585,14 @@ static int bmp581_init(const struct device *dev)
584585
return ret;
585586
}
586587

588+
if (IS_ENABLED(CONFIG_BMP581_STREAM)) {
589+
ret = bmp581_stream_init(dev);
590+
if (ret != 0) {
591+
LOG_ERR("Failed to initialize streaming support: %d", ret);
592+
return ret;
593+
}
594+
}
595+
587596
return ret;
588597
}
589598

@@ -671,6 +680,8 @@ static void bmp581_submit(const struct device *dev, struct rtio_iodev_sqe *iodev
671680

672681
if (!cfg->is_streaming) {
673682
bmp581_submit_one_shot(dev, iodev_sqe);
683+
} else if (IS_ENABLED(CONFIG_BMP581_STREAM)) {
684+
bmp581_stream_submit(dev, iodev_sqe);
674685
} else {
675686
LOG_ERR("Streaming not supported");
676687
rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP);
@@ -712,6 +723,7 @@ static DEVICE_API(sensor, bmp581_driver_api) = {
712723
.iodev = &bmp581_bus_##i, \
713724
.type = BMP581_BUS_TYPE_I2C, \
714725
}, \
726+
.int_gpio = GPIO_DT_SPEC_INST_GET_OR(i, int_gpios, {0}), \
715727
}; \
716728
\
717729
SENSOR_DEVICE_DT_INST_DEFINE(i, bmp581_init, NULL, &bmp581_data_##i, &bmp581_config_##i, \

drivers/sensor/bosch/bmp581/bmp581.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151

152152
/* Interrupt configurations */
153153
#define BMP5_INT_MODE_MSK 0x01
154+
#define BMP5_INT_MODE_POS 0
154155

155156
#define BMP5_INT_POL_MSK 0x02
156157
#define BMP5_INT_POL_POS 1
@@ -162,6 +163,7 @@
162163
#define BMP5_INT_EN_POS 3
163164

164165
#define BMP5_INT_DRDY_EN_MSK 0x01
166+
#define BMP5_INT_DRDY_EN_POS 0
165167

166168
#define BMP5_INT_FIFO_FULL_EN_MSK 0x02
167169
#define BMP5_INT_FIFO_FULL_EN_POS 1
@@ -314,14 +316,23 @@ struct bmp581_sample {
314316
struct sensor_value temperature;
315317
};
316318

319+
struct bmp581_stream {
320+
const struct device *dev;
321+
struct gpio_callback cb;
322+
struct rtio_iodev_sqe *iodev_sqe;
323+
atomic_t state;
324+
};
325+
317326
struct bmp581_data {
318327
uint8_t chip_id;
319328
struct bmp581_sample last_sample;
320329
struct bmp581_osr_odr_press_config osr_odr_press_config;
330+
struct bmp581_stream stream;
321331
};
322332

323333
struct bmp581_config {
324334
struct bmp581_bus bus;
335+
struct gpio_dt_spec int_gpio;
325336
};
326337

327338
#endif /* ZEPHYR_DRIVERS_SENSOR_BMP581_BMP581_H_ */
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
/*
2+
* Copyright (c) 2025 Croxel Inc.
3+
* Copyright (c) 2025 CogniPilot Foundation
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/sys/atomic.h>
9+
#include <zephyr/sys/check.h>
10+
#include <zephyr/drivers/gpio.h>
11+
12+
#include "bmp581.h"
13+
#include "bmp581_stream.h"
14+
#include "bmp581_decoder.h"
15+
16+
#include <zephyr/logging/log.h>
17+
LOG_MODULE_REGISTER(BMP581_STREAM, CONFIG_SENSOR_LOG_LEVEL);
18+
19+
enum bmp581_stream_state {
20+
BMP581_STREAM_OFF = 0,
21+
BMP581_STREAM_ON = 1,
22+
BMP581_STREAM_BUSY = 2,
23+
};
24+
25+
static void bmp581_stream_event_complete(struct rtio *ctx, const struct rtio_sqe *sqe, void *arg0)
26+
{
27+
struct rtio_iodev_sqe *iodev_sqe = (struct rtio_iodev_sqe *)arg0;
28+
const struct device *dev = (const struct device *)sqe->userdata;
29+
struct bmp581_data *data = dev->data;
30+
uint8_t *buf;
31+
uint32_t buf_len;
32+
struct rtio_cqe *cqe;
33+
int err = 0;
34+
35+
do {
36+
cqe = rtio_cqe_consume(ctx);
37+
if (cqe == NULL) {
38+
continue;
39+
}
40+
41+
if (err == 0) {
42+
err = cqe->result;
43+
}
44+
rtio_cqe_release(ctx, cqe);
45+
} while (cqe != NULL);
46+
47+
if (err != 0) {
48+
goto bmp581_stream_evt_finish;
49+
}
50+
51+
err = rtio_sqe_rx_buf(iodev_sqe, 0, 0, &buf, &buf_len);
52+
53+
CHECKIF(err != 0 || !buf || buf_len < sizeof(struct bmp581_encoded_data)) {
54+
LOG_ERR("Couldn't get encoded buffer on completion");
55+
err = -EIO;
56+
goto bmp581_stream_evt_finish;
57+
}
58+
59+
err = bmp581_encode(dev, (struct sensor_read_config *)iodev_sqe->sqe.iodev->data,
60+
0x01, buf);
61+
if (err != 0) {
62+
LOG_ERR("Failed to encode frame: %d", err);
63+
goto bmp581_stream_evt_finish;
64+
}
65+
66+
bmp581_stream_evt_finish:
67+
atomic_set(&data->stream.state, BMP581_STREAM_ON);
68+
69+
if (err < 0) {
70+
rtio_iodev_sqe_err(iodev_sqe, err);
71+
} else {
72+
rtio_iodev_sqe_ok(iodev_sqe, 0);
73+
}
74+
}
75+
76+
static void bmp581_event_handler(const struct device *dev)
77+
{
78+
struct bmp581_data *data = dev->data;
79+
const struct bmp581_config *cfg = dev->config;
80+
struct rtio_iodev_sqe *iodev_sqe = data->stream.iodev_sqe;
81+
uint8_t *buf = NULL;
82+
uint32_t buf_len = 0;
83+
int err;
84+
85+
CHECKIF(!data->stream.iodev_sqe || FIELD_GET(RTIO_SQE_CANCELED, iodev_sqe->sqe.flags)) {
86+
87+
uint8_t val = 0;
88+
89+
LOG_WRN("Callback triggered with no streaming submission - Disabling interrupts");
90+
91+
(void)gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_DISABLE);
92+
93+
err = bmp581_prep_reg_write_rtio_async(&cfg->bus, BMP5_REG_INT_SOURCE, &val, 1,
94+
NULL);
95+
if (err >= 0) {
96+
rtio_submit(cfg->bus.rtio.ctx, 0);
97+
}
98+
99+
(void)atomic_set(&data->stream.state, BMP581_STREAM_OFF);
100+
101+
return;
102+
}
103+
104+
CHECKIF(atomic_cas(&data->stream.state, BMP581_STREAM_ON, BMP581_STREAM_BUSY) == false) {
105+
LOG_WRN("Callback triggered while stream is busy. Ignoring request");
106+
return;
107+
}
108+
109+
err = rtio_sqe_rx_buf(iodev_sqe,
110+
sizeof(struct bmp581_encoded_data),
111+
sizeof(struct bmp581_encoded_data),
112+
&buf, &buf_len);
113+
CHECKIF(err != 0 || buf_len < sizeof(struct bmp581_encoded_data)) {
114+
LOG_ERR("Failed to allocate BMP581 encoded buffer: %d", err);
115+
rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
116+
return;
117+
}
118+
119+
struct bmp581_encoded_data *edata = (struct bmp581_encoded_data *)buf;
120+
struct rtio_sqe *read_sqe = NULL;
121+
struct rtio_sqe *cb_sqe;
122+
123+
err = bmp581_prep_reg_read_rtio_async(&cfg->bus, BMP5_REG_TEMP_DATA_XLSB,
124+
edata->payload, sizeof(edata->payload),
125+
&read_sqe);
126+
CHECKIF(err < 0 || !read_sqe) {
127+
rtio_iodev_sqe_err(iodev_sqe, err);
128+
return;
129+
}
130+
read_sqe->flags |= RTIO_SQE_CHAINED;
131+
132+
cb_sqe = rtio_sqe_acquire(cfg->bus.rtio.ctx);
133+
if (cb_sqe == NULL) {
134+
LOG_ERR("Failed to acquire callback SQE");
135+
rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
136+
return;
137+
}
138+
139+
rtio_sqe_prep_callback_no_cqe(cb_sqe, bmp581_stream_event_complete,
140+
iodev_sqe, (void *)dev);
141+
142+
rtio_submit(cfg->bus.rtio.ctx, 0);
143+
}
144+
145+
static void bmp581_gpio_callback(const struct device *port, struct gpio_callback *cb, uint32_t pin)
146+
{
147+
struct bmp581_stream *stream = CONTAINER_OF(cb, struct bmp581_stream, cb);
148+
const struct device *dev = stream->dev;
149+
150+
bmp581_event_handler(dev);
151+
}
152+
153+
void bmp581_stream_submit(const struct device *dev,
154+
struct rtio_iodev_sqe *iodev_sqe)
155+
{
156+
const struct sensor_read_config *read_config = iodev_sqe->sqe.iodev->data;
157+
struct bmp581_data *data = dev->data;
158+
const struct bmp581_config *cfg = dev->config;
159+
int err;
160+
161+
if ((read_config->count != 1) ||
162+
(read_config->triggers[0].trigger != SENSOR_TRIG_DATA_READY)) {
163+
LOG_ERR("Only SENSOR_TRIG_DATA_READY is supported");
164+
rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP);
165+
return;
166+
}
167+
168+
data->stream.iodev_sqe = iodev_sqe;
169+
170+
if (atomic_cas(&data->stream.state, BMP581_STREAM_OFF, BMP581_STREAM_ON)) {
171+
/* Enable DRDY interrupt */
172+
struct rtio_sqe *int_src_sqe;
173+
uint8_t val = 0;
174+
175+
val = BMP5_SET_BITSLICE(val, BMP5_INT_DRDY_EN, 1);
176+
177+
err = bmp581_prep_reg_write_rtio_async(&cfg->bus, BMP5_REG_INT_SOURCE, &val, 1,
178+
&int_src_sqe);
179+
if (err < 0) {
180+
rtio_iodev_sqe_err(iodev_sqe, err);
181+
return;
182+
}
183+
int_src_sqe->flags |= RTIO_SQE_CHAINED;
184+
185+
val = BMP5_SET_BITSLICE(val, BMP5_INT_MODE, BMP5_INT_MODE_PULSED);
186+
val = BMP5_SET_BITSLICE(val, BMP5_INT_POL, BMP5_INT_POL_ACTIVE_HIGH);
187+
val = BMP5_SET_BITSLICE(val, BMP5_INT_OD, BMP5_INT_OD_PUSHPULL);
188+
val = BMP5_SET_BITSLICE(val, BMP5_INT_EN, 1);
189+
190+
err = bmp581_prep_reg_write_rtio_async(&cfg->bus, BMP5_REG_INT_CONFIG, &val, 1,
191+
NULL);
192+
if (err < 0) {
193+
rtio_iodev_sqe_err(iodev_sqe, err);
194+
return;
195+
}
196+
197+
(void)rtio_submit(cfg->bus.rtio.ctx, 0);
198+
199+
err = gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
200+
if (err < 0) {
201+
rtio_iodev_sqe_err(iodev_sqe, err);
202+
}
203+
}
204+
}
205+
206+
int bmp581_stream_init(const struct device *dev)
207+
{
208+
struct bmp581_data *data = dev->data;
209+
const struct bmp581_config *cfg = dev->config;
210+
int err;
211+
212+
data->stream.dev = dev;
213+
atomic_set(&data->stream.state, BMP581_STREAM_OFF);
214+
215+
if (!device_is_ready(cfg->int_gpio.port)) {
216+
LOG_ERR("DRDY GPIO device is not ready");
217+
return -ENODEV;
218+
}
219+
220+
err = gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT);
221+
if (err < 0) {
222+
return err;
223+
}
224+
225+
gpio_init_callback(&data->stream.cb, bmp581_gpio_callback, BIT(cfg->int_gpio.pin));
226+
227+
err = gpio_add_callback(cfg->int_gpio.port, &data->stream.cb);
228+
if (err < 0) {
229+
return err;
230+
}
231+
232+
err = gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_DISABLE);
233+
if (err < 0) {
234+
return err;
235+
}
236+
237+
return 0;
238+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) 2025 Croxel Inc.
3+
* Copyright (c) 2025 CogniPilot Foundation
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#ifndef ZEPHYR_DRIVERS_SENSOR_BMP581_STREAM_H_
9+
#define ZEPHYR_DRIVERS_SENSOR_BMP581_STREAM_H_
10+
11+
#include <zephyr/device.h>
12+
#include <zephyr/rtio/rtio.h>
13+
14+
int bmp581_stream_init(const struct device *dev);
15+
16+
void bmp581_stream_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe);
17+
18+
#endif /* ZEPHYR_DRIVERS_SENSOR_BMP581_STREAM_H_ */

0 commit comments

Comments
 (0)