DMA buffers switching with SPI and TIMERS via PPI

While collecting 2-byte samples via SPI4 (with a 32 MHz clock) using PPI and timers—one triggering transfers at 400 kHz and another handling an interrupt every 512 samples (counter mode incrementing every SPI transfer end via PPI) to switch the SPI DMA buffer address—erroneous samples occur at buffer boundaries (mostly single, but sometimes multiple). Four buffers of 512 samples each are used.
It appears that either writing samples or switching buffers is not keeping up. However, the time between the 512-sample timer interrupt and the buffer address switch is shorter than the time until the next SPI transfer is triggered.

The program runs with Zephyr and BLE on net core. The sampling timer priority is set to 1, SPI and timer for switching buffers are set to 0 priority. Could Zephyr or other processor interrupts preempt the acquisition process to such an extent? Or is the issue elsewhere?

  • Yes, I tried this also. Unfortunately, the problem still persists. After switching buffers, in the interrupt handler for the sample block, the pointer to the previous part of the buffer is placed into the queue using k_msg_put. The message is then processed by the memory write thread. The number of data buffers and the time between switches are sufficient to prevent data block overlap. However, could pointer transfer errors still occur in this configuration? Where else can I look for the source of the issue?

  • If you're already chaining with SUSPEND and RESUME and still seeing corrupted samples, then it does sound like a buffer ownership race.

    Even if the time between switches is enough, it's possible that the SPI is still writing when the pointer is updated or handed off. I'd suggest making absolutely sure that:

    • You only update the buffer address after SPI has fully suspended.
    • No part of your queue processing thread (or the queue itself) touches the active buffer before the handoff is done.
    • Also worth checking if the DMA buffers are aligned and marked as non-cached 

    If all that looks clean, I would next look into logging when each buffer switch and SPI transfer actually happens (timestamps) to catch any overlaps. 

Related