Skip to content

BMP581: Stream: Add FIFO Watermark Support #93166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions drivers/sensor/bosch/bmp581/bmp581.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ static int power_up_check(const struct device *dev)

if (rslt == BMP5_OK) {
/* Check if nvm_rdy status = 1 and nvm_err status = 0 to proceed */
if ((nvm_status & BMP5_INT_NVM_RDY) && (!(nvm_status & BMP5_INT_NVM_ERR))) {
if ((nvm_status & BMP5_INT_NVM_RDY) != 0 && (nvm_status & BMP5_INT_NVM_ERR) == 0) {
rslt = BMP5_OK;
} else {
rslt = -EFAULT;
Expand Down Expand Up @@ -221,7 +221,7 @@ static int validate_chip_id(struct bmp581_data *drv)
return -EINVAL;
}

if ((drv->chip_id == BMP5_CHIP_ID_PRIM) || (drv->chip_id == BMP5_CHIP_ID_SEC)) {
if (drv->chip_id == BMP5_CHIP_ID_PRIM || drv->chip_id == BMP5_CHIP_ID_SEC) {
rslt = BMP5_OK;
} else {
drv->chip_id = 0;
Expand Down Expand Up @@ -375,7 +375,7 @@ static int soft_reset(const struct device *dev)
k_usleep(BMP5_DELAY_US_SOFT_RESET);
ret = get_interrupt_status(&int_status, dev);
if (ret == BMP5_OK) {
if (int_status & BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE) {
if ((int_status & BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE) != 0) {
ret = BMP5_OK;
} else {
ret = -EFAULT;
Expand Down Expand Up @@ -457,7 +457,7 @@ static int set_iir_config(const struct sensor_value *iir, const struct device *d
struct bmp581_config *conf = (struct bmp581_config *)dev->config;
int ret = BMP5_OK;

CHECKIF((iir == NULL) | (dev == NULL)) {
CHECKIF(iir == NULL || dev == NULL) {
return -EINVAL;
}

Expand Down Expand Up @@ -550,10 +550,15 @@ static int bmp581_init(const struct device *dev)
drv->chip_id = 0;
memset(&drv->last_sample, 0, sizeof(drv->last_sample));

soft_reset(dev);
ret = soft_reset(dev);
if (ret != BMP5_OK) {
LOG_ERR("Failed to perform soft-reset: %d", ret);
return ret;
}

ret = bmp581_reg_read_rtio(&conf->bus, BMP5_REG_CHIP_ID, &drv->chip_id, 1);
if (ret != BMP5_OK) {
LOG_ERR("Failed to read chip ID: %d", ret);
return ret;
}

Expand Down Expand Up @@ -630,7 +635,7 @@ static void bmp581_submit_one_shot(const struct device *dev, struct rtio_iodev_s
const struct bmp581_config *conf = dev->config;

err = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len);
CHECKIF((err < 0) || (buf_len < min_buf_len) || !buf) {
CHECKIF(err < 0 || buf_len < min_buf_len || !buf) {
LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len);
rtio_iodev_sqe_err(iodev_sqe, err);
return;
Expand Down Expand Up @@ -702,7 +707,14 @@ static DEVICE_API(sensor, bmp581_driver_api) = {

#define BMP581_INIT(i) \
\
RTIO_DEFINE(bmp581_rtio_ctx_##i, 8, 8); \
BUILD_ASSERT(COND_CODE_1(DT_INST_NODE_HAS_PROP(i, fifo_watermark), \
(DT_INST_PROP(i, fifo_watermark) > 0 && \
DT_INST_PROP(i, fifo_watermark) < 16), \
(true)), \
"fifo-watermark must be between 1 and 15. Please set it in " \
"the device-tree node properties"); \
\
RTIO_DEFINE(bmp581_rtio_ctx_##i, 16, 16); \
I2C_DT_IODEV_DEFINE(bmp581_bus_##i, DT_DRV_INST(i)); \
\
static struct bmp581_data bmp581_data_##i = { \
Expand All @@ -715,6 +727,9 @@ static DEVICE_API(sensor, bmp581_driver_api) = {
.iir_p = DT_INST_PROP(i, press_iir), \
.power_mode = DT_INST_PROP(i, power_mode), \
}, \
.stream = { \
.fifo_thres = DT_INST_PROP_OR(i, fifo_watermark, 0), \
}, \
}; \
\
static const struct bmp581_config bmp581_config_##i = { \
Expand Down
22 changes: 19 additions & 3 deletions drivers/sensor/bosch/bmp581/bmp581.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
#define BMP5_SET_HIGH_BYTE 0xFF00u

/* BIT SLICE GET AND SET FUNCTIONS */
#define BMP5_GET_BITSLICE(regvar, bitname) ((regvar & bitname##_MSK) >> bitname##_POS)
#define BMP5_GET_BITSLICE(regvar, bitname) (((regvar) & (bitname##_MSK)) >> (bitname##_POS))

#define BMP5_SET_BITSLICE(regvar, bitname, val) \
((regvar & ~bitname##_MSK) | ((val << bitname##_POS) & bitname##_MSK))
(((regvar) & ~(bitname##_MSK)) | (((val) << (bitname##_POS)) & (bitname##_MSK)))

#define BMP5_GET_LSB(var) (uint8_t)(var & BMP5_SET_LOW_BYTE)
#define BMP5_GET_MSB(var) (uint8_t)((var & BMP5_SET_HIGH_BYTE) >> 8)
Expand Down Expand Up @@ -120,6 +120,11 @@
#define BMP5_FIFO_MAX_THRESHOLD_P_T_MODE 0x0F
#define BMP5_FIFO_MAX_THRESHOLD_P_MODE 0x1F

#define BMP5_FIFO_FRAME_SEL_OFF 0
#define BMP5_FIFO_FRAME_SEL_TEMP 1
#define BMP5_FIFO_FRAME_SEL_PRESS 2
#define BMP5_FIFO_FRAME_SEL_ALL 3

/* Macro is used to bypass both iir_t and iir_p together */
#define BMP5_IIR_BYPASS 0xC0

Expand Down Expand Up @@ -239,9 +244,12 @@
#define BMP5_FIFO_DEC_SEL_MSK 0x1C
#define BMP5_FIFO_DEC_SEL_POS 2

#define BMP5_FIFO_COUNT_MSK 0x3F
/* This driver only supports both Pressure and Temperature FIFO mode. */
#define BMP5_FIFO_COUNT_MSK BMP5_FIFO_MAX_THRESHOLD_P_T_MODE
#define BMP5_FIFO_COUNT_POS 0

#define BMP5_FIFO_FRAME_SEL_MSK 0x03
#define BMP5_FIFO_FRAME_SEL_POS 0

/* Out-of-range configuration */
#define BMP5_OOR_THR_P_LSB_MSK 0x0000FF
Expand Down Expand Up @@ -316,10 +324,18 @@ struct bmp581_sample {
struct sensor_value temperature;
};

/** Aligned with register bitmask to easily match on data-readout */
enum bmp581_event {
BMP581_EVENT_DRDY = BIT(0),
BMP581_EVENT_FIFO_WM = BIT(2),
};

struct bmp581_stream {
const struct device *dev;
struct gpio_callback cb;
struct rtio_iodev_sqe *iodev_sqe;
enum bmp581_event enabled_mask;
uint8_t fifo_thres;
atomic_t state;
};

Expand Down
109 changes: 70 additions & 39 deletions drivers/sensor/bosch/bmp581/bmp581_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ int bmp581_encode(const struct device *dev,

if (trigger_status) {
edata->header.channels |= bmp581_encode_channel(SENSOR_CHAN_ALL);
edata->header.fifo_count = data->stream.fifo_thres;
} else {
const struct sensor_chan_spec *const channels = read_config->channels;
size_t num_channels = read_config->count;
Expand All @@ -63,7 +64,7 @@ int bmp581_encode(const struct device *dev,
return err;
}

edata->header.events = trigger_status ? BIT(0) : 0;
edata->header.events = trigger_status;
edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);

return 0;
Expand All @@ -86,7 +87,11 @@ static int bmp581_decoder_get_frame_count(const uint8_t *buffer,
return -ENODATA;
}

*frame_count = 1;
if (edata->header.events & BMP581_EVENT_FIFO_WM) {
*frame_count = edata->header.fifo_count;
} else {
*frame_count = 1;
}
return 0;
}

Expand All @@ -105,53 +110,37 @@ static int bmp581_decoder_get_size_info(struct sensor_chan_spec chan_spec,
}
}

static int bmp581_decoder_decode(const uint8_t *buffer,
struct sensor_chan_spec chan_spec,
uint32_t *fit,
uint16_t max_count,
void *data_out)
static int bmp581_convert_raw_to_q31_value(const struct bmp581_encoded_header *header,
struct sensor_chan_spec *chan_spec,
const struct bmp581_frame *frame,
uint32_t *fit,
struct sensor_q31_data *out)
{
const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer;
uint8_t channel_request;

if (*fit != 0) {
return 0;
}

if (max_count == 0 || chan_spec.chan_idx != 0) {
return -EINVAL;
}

channel_request = bmp581_encode_channel(chan_spec.chan_type);
if ((channel_request & edata->header.channels) != channel_request) {
if (((header->events & BMP581_EVENT_FIFO_WM) != 0 && *fit >= header->fifo_count) ||
((header->events & BMP581_EVENT_FIFO_WM) == 0 && *fit != 0)) {
return -ENODATA;
}

struct sensor_q31_data *out = data_out;

out->header.base_timestamp_ns = edata->header.timestamp;
out->header.reading_count = 1;

switch (chan_spec.chan_type) {
switch (chan_spec->chan_type) {
case SENSOR_CHAN_AMBIENT_TEMP: {
/* Temperature is in data[2:0], data[2] is integer part */
uint32_t raw_temp = ((uint32_t)edata->payload[2] << 16) |
((uint16_t)edata->payload[1] << 8) |
edata->payload[0];
uint32_t raw_temp = ((uint32_t)frame[*fit].payload[2] << 16) |
((uint16_t)frame[*fit].payload[1] << 8) |
frame[*fit].payload[0];
int32_t raw_temp_signed = sign_extend(raw_temp, 23);

out->shift = (31 - 16); /* 16 left shifts gives us the value in celsius */
out->readings[0].value = raw_temp_signed;
out->readings[*fit].value = raw_temp_signed;
break;
}
case SENSOR_CHAN_PRESS:
if (!edata->header.press_en) {
case SENSOR_CHAN_PRESS: {
if (!header->press_en) {
return -ENODATA;
}
/* Shift by 10 bits because we'll divide by 1000 to make it kPa */
uint64_t raw_press = (((uint32_t)edata->payload[5] << 16) |
((uint16_t)edata->payload[4] << 8) |
edata->payload[3]);
uint64_t raw_press = (((uint32_t)frame[*fit].payload[5] << 16) |
((uint16_t)frame[*fit].payload[4] << 8) |
frame[*fit].payload[3]);

int64_t raw_press_signed = sign_extend_64(raw_press, 23);

Expand All @@ -163,21 +152,63 @@ static int bmp581_decoder_decode(const uint8_t *buffer,
* converting to kPa. Hence, left-shift 16 spaces.
*/
out->shift = (31 - 6 - 10);
out->readings[0].value = (int32_t)raw_press_signed;
out->readings[*fit].value = (int32_t)raw_press_signed;
break;
}
default:
return -EINVAL;
}

*fit = 1;
return 1;
*fit = (*fit) + 1;
return 0;
}

static int bmp581_decoder_decode(const uint8_t *buffer,
struct sensor_chan_spec chan_spec,
uint32_t *fit,
uint16_t max_count,
void *data_out)
{
const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer;
uint8_t channel_request;

if (max_count == 0 || chan_spec.chan_idx != 0) {
return -EINVAL;
}

channel_request = bmp581_encode_channel(chan_spec.chan_type);
if ((channel_request & edata->header.channels) != channel_request) {
return -ENODATA;
}

struct sensor_q31_data *out = data_out;

out->header.base_timestamp_ns = edata->header.timestamp;

int err;
uint32_t fit_0 = *fit;

do {
err = bmp581_convert_raw_to_q31_value(&edata->header, &chan_spec,
edata->frame, fit, out);
} while (err == 0 && *fit < max_count);

if (*fit == fit_0 || err != 0) {
return err;
}

out->header.reading_count = *fit;
return *fit - fit_0;
}

static bool bmp581_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigger_type trigger)
{
const struct bmp581_encoded_data *edata = (const struct bmp581_encoded_data *)buffer;

if ((trigger == SENSOR_TRIG_DATA_READY) && (edata->header.events != 0)) {
if ((trigger == SENSOR_TRIG_DATA_READY &&
edata->header.events & BMP581_EVENT_DRDY) ||
(trigger == SENSOR_TRIG_FIFO_WATERMARK &&
edata->header.events & BMP581_EVENT_FIFO_WM)) {
return true;
}

Expand Down
42 changes: 38 additions & 4 deletions drivers/sensor/bosch/bmp581/bmp581_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,50 @@
#include <zephyr/drivers/sensor.h>
#include "bmp581.h"

struct bmp581_encoded_data {
struct {
struct bmp581_encoded_header {
uint8_t channels;
uint8_t events;
uint64_t timestamp;
uint8_t press_en;
} header;
uint8_t payload[6]; /* 3 bytes temp + 3 bytes press */
uint8_t fifo_count;
};

struct bmp581_frame {
uint8_t payload[6];
};

struct bmp581_encoded_data {
struct bmp581_encoded_header header;
union {
uint8_t payload[6]; /* 3 bytes temp + 3 bytes press */
struct bmp581_frame frame[0]; /* Used for FIFO frames */
};
};

static inline enum bmp581_event bmp581_encode_events_bitmask(
const struct sensor_stream_trigger *const triggers,
size_t count)
{
enum bmp581_event result = 0;

for (size_t i = 0 ; i < count ; i++) {
switch (triggers[i].trigger) {
case SENSOR_TRIG_DATA_READY:
result |= ((triggers[i].opt == SENSOR_STREAM_DATA_INCLUDE) ?
BMP581_EVENT_DRDY : 0);
break;
case SENSOR_TRIG_FIFO_WATERMARK:
result |= ((triggers[i].opt == SENSOR_STREAM_DATA_INCLUDE) ?
BMP581_EVENT_FIFO_WM : 0);
break;
default:
break;
}
}

return result;
}

int bmp581_encode(const struct device *dev,
const struct sensor_read_config *read_config,
uint8_t trigger_status,
Expand Down
Loading
Loading