2026-02-24 2:15 AM - edited 2026-02-24 7:45 AM
Hello.
I'm working on product with LSM6DSO IMU.
I have the communication working, but I'm trying to optimize a reading of the FIFO buffer.
In the AN5192 document there is sentence: "The wraparound function from address FIFO_DATA_OUT_Z_H to FIFO_DATA_OUT_TAG is done automatically in the device, in order to allow reading many words with a unique multiple read operation."
How should I understand this exactly? What is meant by the "unique multiple read"?
I tried to read the register first using i2c write-read, and then just do simple reads of 7 bytes in a loop (for number of samples in fifo). It looks like somehow working, but I'm getting wrong data.
Using the write-read for each sample works fine, but it is very inefficient.
for (int i = 0; i < num; i++)
{
if (i == 0)
{
lsm6dso_read_reg(&ctx, LSM6DSO_FIFO_DATA_OUT_TAG,
(uint8_t *)&sample, 7);
}
else
{
lsm6dso_i2c_read_only(&ctx, (uint8_t *)&sample, 7);
}So what is the most efficient way to read multiple FIFO samples?
Do you have ideally some example of the I2C communication (where is possible to see the commands, start/stop bits etc.)?
Thank you
Update:
I tried to make a more optimized way which just do re-start between the reads, still only the first sample is correct:
int lsm6dso_i2c_read_fifo(const stmdev_ctx_t *ctx,
uint8_t *data,
uint16_t num_of_samples)
{
struct i2c_dt_spec *spec = (struct i2c_dt_spec *)ctx->handle;
struct i2c_msg msg[255];
uint8_t reg_addr = LSM6DSO_FIFO_DATA_OUT_TAG;
msg[0].buf = ®_addr;
msg[0].len = 1;
msg[0].flags = I2C_MSG_WRITE;
for (int i = 0; i < num_of_samples; i++)
{
msg[1 + i].buf = data + (i * 7);
msg[1 + i].len = 7;
msg[1 + i].flags = I2C_MSG_RESTART | I2C_MSG_READ;
}
msg[num_of_samples].flags |= I2C_MSG_STOP;
return i2c_transfer(spec->bus, msg, num_of_samples + 1, spec->addr);
}Log output when reading always 3 samples:
[00:20:16.486,755] <dbg> accel: imu_test_fifo_batch_read: Sample 0 bytes: 0c ff ff f4 ff 01 00
[00:20:16.487,335] <dbg> accel: gyro_print_fs_to_mdps_raw: angular rate: x=-70 mdps, y=-840 mdps, z=70 mdps
[00:20:16.487,915] <dbg> accel: imu_test_fifo_batch_read: Sample 1 bytes: 86 00 ec ff 1c 08 0f
[00:20:16.488,433] <dbg> accel: imu_test_fifo_batch_read: Unknown FIFO tag 0x10, skipping sample
[00:20:16.488,952] <dbg> accel: imu_test_fifo_batch_read: Sample 2 bytes: ff f3 ff 02 00 17 8b
[00:20:16.489,501] <dbg> accel: imu_test_fifo_batch_read: Unknown FIFO tag 0x1f, skipping sample
[00:20:17.491,607] <dbg> accel: imu_test_fifo_batch_read: Sample 0 bytes: 0a 00 00 f3 ff 02 00
[00:20:17.492,187] <dbg> accel: gyro_print_fs_to_mdps_raw: angular rate: x=0 mdps, y=-910 mdps, z=140 mdps
[00:20:17.492,767] <dbg> accel: imu_test_fifo_batch_read: Sample 1 bytes: 89 00 e6 ff 19 08 0c
[00:20:17.493,347] <dbg> accel: imu_test_fifo_batch_read: Unknown FIFO tag 0x11, skipping sample
[00:20:17.493,896] <dbg> accel: imu_test_fifo_batch_read: Sample 2 bytes: ff f5 ff 02 00 14 8c
[00:20:17.494,445] <dbg> accel: imu_test_fifo_batch_read: Unknown FIFO tag 0x1f, skipping sample
Solved! Go to Solution.
2026-02-25 3:12 AM
I was finally able to solve it.
The readings of the fifo must NOT be separated by stop/start.
The I2C_MSG_RESTART in Zephyr doesn't just repeat start, but it repeat whole stop/start sequence.
By omitting it, the readings of the fifo works in one chunk, which is MUCH faster (for comparison: reading 36 samples this way takes around 6ms on 400kHz, using lsm6dso_fifo_sensor_tag_get + lsm6dso_fifo_out_raw_get, like in the FIFO example, takes around 24ms, that's 4x slower!).
2026-02-25 3:12 AM
I was finally able to solve it.
The readings of the fifo must NOT be separated by stop/start.
The I2C_MSG_RESTART in Zephyr doesn't just repeat start, but it repeat whole stop/start sequence.
By omitting it, the readings of the fifo works in one chunk, which is MUCH faster (for comparison: reading 36 samples this way takes around 6ms on 400kHz, using lsm6dso_fifo_sensor_tag_get + lsm6dso_fifo_out_raw_get, like in the FIFO example, takes around 24ms, that's 4x slower!).