Imu, pdm & ble同时启动时的数据问题, Simultaneous startup data issues

我在用XIAO nRF52840 SENSE。
启用了DMA方式读取104Hz的IMU,41667Hz / 16000Hz的PDM并通过BLE实时发送。

  1. 当PDM不开启时,IMU通过BLE发送,在上位机读取后,IMU都是连续且稳定的。
  2. 当IMU和PDM都开启,BLE未连接时,IMU的数据也是连续且稳定的。
  3. 当IMU和PDM都开启,BLE连接后,IMU数据会有两帧数据都为0值,而且是间歇性的发生。

通过报文打印检查过,在数据异常时,IMU的双缓冲数组的数据都是0,可以排除是解析导致的异常。但是1和2也能说明IMU的读取和解析是正确的。尝试过16KHz和41.667kHz,情况没有变化。 BLE采用了247, 1M,间隔7.5ms。
如果是BLE开启后挤占CPU时间的问题,修改PDM的采样率是不是应该有好转?

有其他朋友遇到过类似的问题么,现在碰到的问题可能是什么原因导致的?

I am using XIAO nRF52840 SENSE.
I want to get IMU data via DMA @ 104Hz, PDM data @16kHz/41.667kHz, and send the data via BLE @ 247,1M, gap = 7.5ms.

  1. when enable IMU, disable PDM, the IMU data can be send via BLE correctly.
  2. when enable both IMU and PDM, the BLE is disconnected, the IMU data are also correct.
  3. when enable both IMU and PDM, and connected BLE and send realtime data. the IMU data will be about 0 in some frame. about 1 frame in 10 frames.
    In the situation, the IMU data from DMA buffer are already 0, so I think it is none business of send data via BLE or parse data.
    I try to change PDM from 41.667kHz to 16kHz, it appears no improvement.

Anyone know why and what happened. What can I do to solve this problem?

Hi there,

SO , it’s been a minute, always good stuff you bring and ask :+1:

Its a contention issue, the BLE (radio is the highest interrupt priority), the DMA is next, the PDM is LAST :grin:
the BLE interuppts causes a delay in returning he DMA start memory location basically, the short connection interval cuases that. The PDM has on ly a two sample buffer so it complicates the DMA and the data gets a ZERO…

Switch to DPPI /PPI :+1:
Do not rely on CPU interrupts to trigger the next IMU DMA transfer. Use hardware PPI/DPPI to connect the IMU data-ready GPIO pin directly to the SPI/I2C START task. This eliminates CPU interrupt latency from the transfer trigger path.
Also Increasing the interval to 15 ms–30 ms while transmitting multiple packets per connection event gives the CPU larger continuous time slices to handle peripheral ISRs and buffer swapping.
Check your dev tree and Kconfig for proper priority in Zephyr and with IMU instead of the PING-PONG double buffer , use a fifo 3 or 4 elements for the Queue so a brief delay in consumption does not result in reading an empty/unpopulated slot.

Give it a go , and let us Know :grin:

HTH
GL :slight_smile: PJ :v:

Thanks PJ.

Another Question:
During the process of reading the IMU via DMA, at a sampling frequency of 104 Hz, over 60 seconds there will be multiple instances of IMU data being out of order. For example, in most of the data az=1.035, but in the out-of-order cases it may be ax=1.035, or it may be misplaced into gx. At this time, the Recursive_pattern read from FIFO_STATUS3 and FIFO_STATUS4 is still 0 or 6. Is this because the way Recursive_pattern is read is incorrect, or because the CPU is occupied during the IMU transfer process, or is there some other reason?

Hi there,

So, Glad to help… I see the FiFo sync problem before.
That axis-swapping behavior (az becoming ax or leaking into gx) indicates a FIFO byte-alignment offset shift rather than CPU ISR latency.

When parsing shifts by 2, 4, or 6 bytes, the DMA read pointer has fallen out of sync with the IMU’s 6-byte/12-byte FIFO word boundaries. Here is why it happens and how to address it:

  1. Non-Integral DMA Read Lengths:
    Each Accel + Gyro packet in the FIFO is 12 bytes (6 bytes for Gyro, 6 bytes for Accel). If a DMA transaction terminates or reads a byte count that is not an exact multiple of 12 bytes, the next DMA transfer begins reading from the middle of a sample frame instead of the start.

  2. Status Register Race Conditions:
    Reading FIFO_STATUS3/4 in a separate SPI/I2C transaction before or after the DMA payload read creates a race condition. If a sample is pushed to FIFO while the command sequence is in flight, the Recursive_pattern returned will not match the head of the DMA buffer.

Fixes to try:

  • Lock DMA Buffer Sizes: Ensure your SPI DMA read size is strictly an integer multiple of 12 bytes (or 6 bytes if using Accel only).
  • Trigger on FIFO Watermark (FTH), :backhand_index_pointing_left: :wink: :face_vomiting: :backhand_index_pointing_right: not DRDY: Configure INT1 to trigger on the FIFO Watermark (FIFO_CTRL1/2) set to a fixed number of complete frames (e.g., 2 frames = 24 bytes), rather than reading on simple data-ready interrupts.
  • Resync on Error: If an unexpected pattern or out-of-bounds delta is detected, toggle FIFO_CTRL5 to Bypass mode and back to Continuous mode to reset the internal FIFO pointers to index 0.

HTH
GL :slight_smile: PJ :v:

vLLM

Why this happens

  1. Non-Multiple Word Reads via DMA:

    • In the LSM6DS3TR-C, each FIFO sample set consists of 6-byte frames per sensor (3 axes $\times$ 2 bytes). A combined Gyro + Accel entry is 12 bytes.

    • If a DMA transfer requests a byte count that is not an exact multiple of the dataset size (or stops midway due to a SPI/I2C transfer interrupt cutoff or bus timeout), the FIFO read pointer remains parked halfway through a sample.

    • On the very next DMA trigger, byte 0 read by the DMA is actually byte 2, 4, or 6 of the previous sample. This instantly shifts az into ax or gx.
      :grin:

观察到您这边调度了多外设的数据交付;
建议您可以从 数据收发和代码架构入手处理相关问题:

1. 推荐使用状态机处理各个业务逻辑.

2. 推荐涉及数据接收/发送时使用ringbuffer( 环形缓冲区)+DMA去承载数据避免丢数据和过度依赖中断

Pretty sure I already told him that. Maybe you don’t’ read english.?
The ring buffer with DMA is the appropriate method, BTW.

HTH
GL :slight_smile: PJ :v: