-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
lsm6dsv16x: add RTIO async and fifo stream #81447
base: main
Are you sure you want to change the base?
lsm6dsv16x: add RTIO async and fifo stream #81447
Conversation
Save gyroscope range set from DT or SENSOR_ATTR in data structure. Signed-off-by: Armando Visconti <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking pretty good to me, I do think the workq could be avoided here with a little effort to do the reads asynchronously, or configure the sensor asynchronously (though I get this is a little bit of a hassle).
The workq does add some code size in trade for convenience.
#define LSM6DSV16X_SPI_RTIO_DEFINE(inst) \ | ||
SPI_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst, \ | ||
DT_DRV_INST(inst), LSM6DSV16X_SPI_OP, 0U); \ | ||
RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 16, 16); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
16 is quite a large number of submissions and completions to keep in the pool Each one is going to be ~32bytes, 16*32 512B of potential space here.
Likely only needs 2 to 4 depending on what kind of transactions you are doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
/* | ||
* Instantiation macros used when a device is on an I2C bus. | ||
*/ | ||
|
||
#define LSM6DSV16X_I2C_RTIO_DEFINE(inst) \ | ||
I2C_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst, DT_DRV_INST(inst));\ | ||
RTIO_DEFINE(lsm6dsv16x_rtio_ctx_##inst, 16, 16); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above, I'd recommend reducing the number of submissions (and completions) in the pool to something like 2 or 4 here. Likely 4 for doing the typical write a register, read a value, do a callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But other sensor drivers are using 8/16. Maybe I could fix it to 4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If they are using 16, this is likely wasteful... I'd try fixing it to 4
read_fifo_status_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; | ||
} | ||
rtio_sqe_prep_callback(check_fifo_status_reg, | ||
lsm6dsv16x_read_fifo_cb, (void *)dev, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not required, but one possibility here is to look at the current request options and sensor config to assign an appropriate callback here avoiding some branching.
Potentially you could directly read the FIFO perhaps because the watermark is set, you can see if the data is requested with it.
Other possibilities to reduce branching are likely here but I get the current example drivers don't do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, this is the only thing I'm not addressing. If it is really requested I'll explore it. :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understandable on the branching front
probably worth ignoring the response of the callback
check_fifo_status_reg->flags |= RTIO_SQE_NO_RESPONSE;
I'm still wondering about callbacks and responses, but today they do result in a completion response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had forgotten @JordanYates added a helper for this,
rtio_sqe_prep_callback_no_cqe()
https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/rtio/rtio.h#L618
0c5e2cb
to
8260eee
Compare
re-pushed with some fix in order to (hopefully) pass CI. Still need to go thru some of the review comments... |
Add attr_get() driver API Signed-off-by: Armando Visconti <[email protected]>
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&config->ctx; | ||
|
||
/* Flush the FIFO by disabling it. */ | ||
lsm6dsv16x_fifo_mode_set(ctx, LSM6DSV16X_BYPASS_MODE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but then shouldn't you reenable it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is done in the next rtio submit which calls lsm6dsv16x_config_fifo()
. Actually I'm quite new on the rtio philosophy, so I might be wrong. Maybe @teburd can comment more properly here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit confusing I agree.
This should enable the triggers/fifo/data collection options as needed by the sensor stream configuration. I guess the question would then be when do we stop collecting and flush the FIFO. There's no explicit control API for this today that I recall offhand.
Collecting until we have no more buffers to fill (we overrun) is pretty simple and automatic. It's what I'd recommend. This works if you cancel the stream submission, or are cycling through multiple buffers (like double/triple/quadruple buffering sensor data). @yperess might have some other ideas here though.
Flushing (disabling/enabling) on each submission regardless doesn't seem like the right thing to do. Data would potentially be lost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, what you are saying is in fact what I have understood earlier looking at following code in the comments:
673 * int main(void) {
674 * struct rtio_sqe *handle;
675 * sensor_stream(&imu_stream, &rtio, NULL, &handle);
676 * k_msleep(1000);
677 * rtio_sqe_cancel(handle);
678 * }
Here seems that sensor_stream is done only once initially, then FIFO streaming is self-sustained by FIFO_TH interrupts, and when you are done you just cancel the rtio_sqe handle. If this is correct, maybe the SENSOR_STREAM_DATA_DROP action really have to re-enable the FIFO, as no more sensor_stream will be re-issued.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually also did the same thing (almost in the same way here) except with I3C with FIFO streaming with I3C RTIO.... I'll get to creating a PR on top of this maybe this week or next... but I still need a review on #79346
8260eee
to
a722de0
Compare
BTW, what hardware are you using? It seems that you already have a rtio-enabled I3C bus driver. |
a722de0
to
e832f6b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some small noteworthy things I took notice of. Hopefully the last round
rtio_sqe_prep_read(read_fifo_dout_reg, iodev, RTIO_PRIO_NORM, | ||
read_buf, buf_avail, lsm6dsv16x->streaming_sqe); | ||
read_fifo_dout_reg->flags = RTIO_SQE_CHAINED; | ||
if (lsm6dsv16x->bus_type == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you mean to use the define here
if (lsm6dsv16x->bus_type == BUS_I2C) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, thx for getting this typo...
rtio_sqe_prep_read(read_fifo_status_reg, iodev, RTIO_PRIO_NORM, | ||
lsm6dsv16x->fifo_status, 2, NULL); | ||
read_fifo_status_reg->flags = RTIO_SQE_CHAINED; | ||
if (lsm6dsv16x->bus_type == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you mean to use the define here
if (lsm6dsv16x->bus_type == BUS_I2C) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
edata->has_temp = 0; | ||
|
||
for (int i = 0; i < num_channels; i++) { | ||
switch (channels[i].chan_type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you want to support SENSOR_CHAN_ALL
?
case SENSOR_CHAN_ALL:
edata->has_accel = 1;
edata->has_gyro = 1;
#if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
edata->has_temp = 1;
#endif
break;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also reviewed the error checking and sqe error reporting
.is_fifo = true, | ||
.accel_fs = lsm6dsv16x->accel_fs, | ||
.gyro_fs = lsm6dsv16x->gyro_fs, | ||
.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the timestamp be recorded when the interrupt occurs rather than when it gets done reading the fifo status
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, like it is done in the rtio simple case. Good catch
EDIT:
Well, actually it is before reading the FIFO. It is done just after reading the FIFO status and getting to know that it is actually a good interrupt. So, I think it is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way of thinking about it is considering if you had an accelerometer running at 1hz and a FIFO threshold of 1 sample, and the sampling is aligned to N second boundaries.
T = 0.0 accelerometer start
T = 0.9 high priority task starts
T = 1.0 accelerometer samples, interrupt fires
T = 1.2 high priority task finishes
T = 1.3 read the FIFO status
The timestamp associated with the sample should not be 1.3, as reading the FIFO status is not strictly tied to the sampling.
out->header.base_timestamp_ns = edata->header.timestamp; | ||
out->readings[count].timestamp_delta = | ||
(xl_count - 1) * accel_period_ns[edata->accel_batch_odr]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm rather confused by this... but I see other drivers do this as well.
If the timestamp is recorded when the fifo is full or the watermark is hit, then that time is the time of the very last sample in the fifo.... but as it is a fifo, the first sample read out will be the oldest sample which the actual time of the sampling would of been quite a bit before the time of the last sampling. base_timestamp_ns
would the time of the first sample recorded and timestamp_delta
is the time difference in the future of when that sampling occured relative to the base_timestamp_ns
In my implementation... I did this where I first count up the total number of frames and then work backwards as to when the first sample timestamp actually occured.
static int lsm6dsv16x_fifo_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
uint32_t *fit, uint16_t max_count, void *data_out)
{
const struct lsm6dsv16x_fifo_data *edata = (const struct lsm6dsv16x_fifo_data *)buffer;
const struct lsm6dsv16x_decoder_header *header = &edata->header;
struct lsm6dsv16x_settings cfg = {
.accel_range = edata->header.accel_fs,
.gyro_range = edata->header.gyro_fs,
};
const uint8_t *buffer_end =
buffer + sizeof(struct lsm6dsv16x_fifo_data) + (edata->fifo_count * 7);
const uint8_t *temp_buffer = buffer;
lsm6dsv16x_fifo_data_out_tag_t tag;
int count = 0;
int accel_frame_count = 0;
int gyro_frame_count = 0;
int total_accel_frames = 0;
int total_gyro_frames = 0;
int rc;
if ((uintptr_t)buffer_end <= *fit || chan_spec.chan_idx != 0) {
return 0;
}
while (temp_buffer < buffer_end) {
memcpy(&tag, &buffer[0], sizeof(tag));
/* frame counters */
switch (tag.tag_sensor) {
case LSM6DSV16X_XL_NC_TAG:
total_accel_frames++;
break;
case LSM6DSV16X_GY_NC_TAG:
total_gyro_frames++;
break;
case LSM6DSV16X_CFG_CHANGE_TAG:
/* TODO: record ODR changes */
break;
default:
break;
}
/* A frame is 7 Bytes */
temp_buffer += 7;
}
/*
* as the timestamp is when the fifo event occured, the base timestamp needs the time of the
* first frame which will be the first frame read out of the FIFO. Back date the timestamp by
* the total number of frames in the FIFO * the period of the ODR.
* TODO: This could have issues of the ODR was changed while streaming.
*/
if (IS_ACCEL(chan_spec.chan_type)) {
((struct sensor_data_header *)data_out)->base_timestamp_ns =
edata->header.timestamp -
(total_accel_frames - 1) * period_ns[edata->accel_odr];
} else if (IS_GYRO(chan_spec.chan_type)) {
((struct sensor_data_header *)data_out)->base_timestamp_ns =
edata->header.timestamp -
(total_gyro_frames - 1) * period_ns[edata->gyro_odr];
}
/* Get the start of the FIFO data */
buffer += sizeof(struct lsm6dsv16x_fifo_data);
while (count < max_count && buffer < buffer_end) {
memcpy(&tag, &buffer[0], sizeof(tag));
/* frame counters */
switch (tag.tag_sensor) {
case LSM6DSV16X_XL_NC_TAG:
accel_frame_count++;
break;
case LSM6DSV16X_GY_NC_TAG:
gyro_frame_count++;
break;
default:
break;
}
if ((uintptr_t)buffer < *fit) {
/* This frame was already decoded, move on to the next frame */
buffer += 7;
continue;
}
switch (tag.tag_sensor) {
case LSM6DSV16X_XL_NC_TAG:
if (IS_ACCEL(chan_spec.chan_type)) {
/* Decode accel */
struct sensor_three_axis_data *data =
(struct sensor_three_axis_data *)data_out;
uint64_t accel_period_ns = period_ns[edata->accel_odr];
rc = lsm6dsv16x_get_shift(SENSOR_CHAN_ACCEL_XYZ, header->accel_fs,
header->gyro_fs, &data->shift);
if (rc != 0) {
return -EINVAL;
}
/* extract raw data from fifo frame */
int16_t accel_x_raw = sys_get_le16(&buffer[1]);
int16_t accel_y_raw = sys_get_le16(&buffer[3]);
int16_t accel_z_raw = sys_get_le16(&buffer[5]);
data->readings[count].timestamp_delta =
(accel_frame_count - 1) * accel_period_ns;
lsm6dsv16x_convert_raw_to_q31(&cfg, SENSOR_CHAN_ACCEL_X,
accel_x_raw,
&data->readings[count].x);
lsm6dsv16x_convert_raw_to_q31(&cfg, SENSOR_CHAN_ACCEL_Y,
accel_y_raw,
&data->readings[count].y);
lsm6dsv16x_convert_raw_to_q31(&cfg, SENSOR_CHAN_ACCEL_Z,
accel_z_raw,
&data->readings[count].z);
count++;
}
break;
case LSM6DSV16X_GY_NC_TAG:
if (IS_GYRO(chan_spec.chan_type)) {
/* Decode gyro */
struct sensor_three_axis_data *data =
(struct sensor_three_axis_data *)data_out;
uint64_t gyro_period_ns = period_ns[edata->gyro_odr];
rc = lsm6dsv16x_get_shift(SENSOR_CHAN_GYRO_XYZ, header->accel_fs,
header->gyro_fs, &data->shift);
if (rc != 0) {
return -EINVAL;
}
/* extract raw data from fifo frame */
int16_t gyro_x_raw = sys_get_le16(&buffer[1]);
int16_t gyro_y_raw = sys_get_le16(&buffer[3]);
int16_t gyro_z_raw = sys_get_le16(&buffer[5]);
data->readings[count].timestamp_delta =
(gyro_frame_count - 1) * gyro_period_ns;
lsm6dsv16x_convert_raw_to_q31(&cfg, SENSOR_CHAN_GYRO_X, gyro_x_raw,
&data->readings[count].x);
lsm6dsv16x_convert_raw_to_q31(&cfg, SENSOR_CHAN_GYRO_Y, gyro_y_raw,
&data->readings[count].y);
lsm6dsv16x_convert_raw_to_q31(&cfg, SENSOR_CHAN_GYRO_Z, gyro_z_raw,
&data->readings[count].z);
count++;
}
break;
#if defined(CONFIG_LSM6DSV16X_ENABLE_TEMP)
case LSM6DSV16X_TEMPERATURE_TAG:
if (chan_spec.chan_type == SENSOR_CHAN_DIE_TEMP) {
/* Decode temperature */
struct sensor_q31_data *data = (struct sensor_q31_data *)data_out;
rc = lsm6dsv16x_get_shift(SENSOR_CHAN_DIE_TEMP, 0, &data->shift);
if (rc != 0) {
return -EINVAL;
}
/* extract raw data from fifo frame */
int16_t temp_raw = sys_get_le16(&buffer[1]);
lsm6dsv16x_convert_raw_to_q31(&cfg, SENSOR_CHAN_DIE_TEMP, temp_raw,
&data->readings[count].temperature);
count++;
}
break;
#endif /* CONFIG_LSM6DSV16X_ENABLE_TEMP */
case LSM6DSV16X_TIMESTAMP_TAG:
/* Decode timestamp */
// uint32_t timestamp = sys_get_le32(&buffer[1]);
/* TODO: Word also contains other metadata that may be useful */
break;
case LSM6DSV16X_FIFO_EMPTY:
default:
break;
}
/* A frame is 7 Bytes */
buffer += 7;
*fit = (uintptr_t)buffer;
}
return count;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave it open for the moment... I'll think more about it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think you are right. I'll count the frames and set base_timestamp_ns accordingly. Thanks for your example code, seems correct.
I'm using a custom silicon that I can't say anything about 🤐 . I also have a i3c-rtio PR that is needing a review as well #80177 |
Yes, I work in ST in Milano in Italy. I saw that you are based in Seattle, which recalls in my mind very good old memories...
That's terrific. I'll take a look at it |
e832f6b
to
5e8a47c
Compare
pin_int.fifo_th = PROPERTY_DISABLE; | ||
|
||
if (enable != 0) { | ||
pin_int.fifo_th = PROPERTY_ENABLE; | ||
|
||
xl_batch = config->accel_batch; | ||
gy_batch = config->gyro_batch; | ||
temp_batch = config->temp_batch; | ||
|
||
fifo_mode = LSM6DSV16X_STREAM_MODE; | ||
fifo_wtm = config->fifo_wtm; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is always forcing the pin_int.fifo_th
interrupt and not checking the enabled triggers for either SENSOR_TRIG_FIFO_WATERMARK
or SENSOR_TRIG_FIFO_FULL
for pin_int.fifo_full
as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, ack
cqe = rtio_cqe_consume(lsm6dsv16x->rtio_ctx); | ||
if (cqe != NULL) { | ||
if ((cqe->result < 0) && (res == 0)) { | ||
LOG_ERR("Bus error: %d", cqe->result); | ||
res = cqe->result; | ||
} | ||
rtio_cqe_release(lsm6dsv16x->rtio_ctx, cqe); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if I run with the fifo_th interrupt, all of sudden I this error after running for less than a minute. I don't know much about the internals of RTIO as to why...
If I run with the fifo_full interrupt which doesn't trigger as often, I don't see it
@teburd do you have any ideas?
[00:00:10.651,000] <err> LSM6DSV16X_RTIO: Bus error: -140
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-ECANCELLED implies an error or intentional cancellation of that submission or one before it in the same chain/transaction. Beyond that its not obvious, I'd add some logging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not doing any intentional cancellation so it must be error... I'll try to do some digging on my own here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@teburd somehow increasing cq_sz
in RTIO_DEFINE(name, sq_sz, cq_sz)
from 4 to 8 makes the error not happen anymore, I'm not quite sure how that is used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cq_sz is the pool of available completions, likely the gpio interrupt for handling the sensor fifo events is being unmasked before clearing out the results of the last gpio interrupt in some manner. One possible source could be caused the callback submissions generating completions and not dealing with those if the flag isn't set to not do that. I get that its maybe surprising behavior on that front, @JordanYates I believe ran into something similar in #76351
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rtio_sqe_prep_callback_no_cqe() is helpful for the first case
https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/rtio/rtio.h#L618
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@XenuIsWatching not able to replicate. Can you give me more details on your tests? (i.e. fifo watermark, batching odr, ...). Also, I'm using I2C, but you are using I3C, so maybe not replicable on my side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I am using I3C here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm using zephyr 3.7 (just with this patched in), fifo watermark is 0x20, batching odr is 960Hz for accel and gyro along with running on I3C w/ IBI interrupts on my own commit (i'll try to get draft commit up soon, it's just that it has so many dependencies on unmerged PRs)
adding check_fifo_status_reg->flags |= RTIO_SQE_NO_RESPONSE;
didn't fix it for me :(, but still having the cqe_sz set to 8 does....
DT_INST_NODE_HAS_PROP(inst, int2_gpios)), \ | ||
(LSM6DSV16X_CFG_IRQ(inst))) | ||
#define LSM6DSV16X_SPI_RTIO_DEFINE(inst) \ | ||
SPI_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst, \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unlikely situation: you want to give lsm6dsv16x_iodev_##inst
different names as someone could have both SPI and I2C defined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I thought about this possibility as well. But ##inst
would come out as different numbers in that case, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I thought about this possibility as well. But
##inst
would come out as different numbers in that case, no?
oh... yes, you are right
/* | ||
* Instantiation macros used when a device is on an I2C bus. | ||
*/ | ||
|
||
#define LSM6DSV16X_I2C_RTIO_DEFINE(inst) \ | ||
I2C_DT_IODEV_DEFINE(lsm6dsv16x_iodev_##inst, DT_DRV_INST(inst));\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unlikely situation: you want to give lsm6dsv16x_iodev_##inst different names as someone could have both SPI and I2C defined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
read_fifo_status_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART; | ||
} | ||
rtio_sqe_prep_callback(check_fifo_status_reg, | ||
lsm6dsv16x_read_fifo_cb, (void *)dev, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understandable on the branching front
probably worth ignoring the response of the callback
check_fifo_status_reg->flags |= RTIO_SQE_NO_RESPONSE;
I'm still wondering about callbacks and responses, but today they do result in a completion response.
5e8a47c
to
f26b08d
Compare
/* disable FIFO as first thing */ | ||
lsm6dsv16x_fifo_mode_set(ctx, LSM6DSV16X_BYPASS_MODE); | ||
|
||
pin_int.fifo_th = PROPERTY_DISABLE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should you also be setting pin_int.fifo_full = PROPERTY_DISABLE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... oooops, correct!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll submit a new commit set on Monday. I'm leaving for the week
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. We should be all set I guess
Add RTIO async and RTIO stream functionalities that enables, among all the other things, the sensor data streaming from FIFO. RTIO stream is using both SENSOR_TRIG_FIFO_WATERMARK and SENSOR_TRIG_FIFO_FULL triggers. The decoder currently only supports following FIFO tags: - LSM6DSV16X_XL_NC_TAG - LSM6DSV16X_GY_NC_TAG - LSM6DSV16X_TEMP_NC_TAG Following FIFO parameters has to be defined in device tree to correctly stream sensor data: - fifo-watermark (defaults to 32) - accel-fifo-batch-rate (defaults to LSM6DSV16X_DT_XL_NOT_BATCHED) - gyro-fifo-batch-rate (defaults to LSM6DSV16X_DT_GY_NOT_BATCHED) - temp-fifo-batch-rate (defaults to LSM6DSV16X_DT_TEMP_NOT_BATCHED) Signed-off-by: Armando Visconti <[email protected]>
f26b08d
to
4b84e7f
Compare
Add RTIO async and RTIO stream functionalities that enables, among all the other things, the sensor data streaming from FIFO. RTIO stream is using both SENSOR_TRIG_FIFO_WATERMARK and SENSOR_TRIG_FIFO_FULL triggers. The decoder currently only supports following FIFO tags:
In DT it is possible to configure following FIFO params:
Since I do not have any boards with a chipset with I2C/SPI rtio supported zephyr driver, I tested this solution using I2C rtio default driver. Waiting for #71961 to be reviewed, as well as a proper solution for STM32 SPI.
Moreover, this PR does not contain any specific sample (in the future I may add one), but I'm using a modified version of
samples/sensor/accel_polling
to test the FIFO streaming.