2025-10-20 3:44 PM - edited 2025-10-20 3:51 PM
Hello, I have an STM32F777ZIIT which is being used to gather SPI data in receive-only mode on four SPI channels and using DMA to buffer this data. The DMA buffers are 70 half-words long, configured for circular mode, and half the half-full and full interrupts set up. Using hardware timers, the external SPI devices are being triggered to transmit 35 samples every 1ms. This is being done on four SPI channels, with one of them (channel "D") being phase-delayed by 500 microseconds. Note that this is running on bare-metal.
The expected behavior is to see all four channels receive the half-full interrupt after 1ms (D last), then the full interrupt after another 1ms.
In a consistent fashion, I am seeing this pattern in the half full and full ISRs per channel. All four should have the same DMA configuration.
Time (microseconds) | Channel A | Channel B | Channel C | Channel D |
758 | Half | |||
768 | Half | |||
778 | Half | |||
788 | Half | |||
2717 | Full | |||
2727 | Full | |||
2737 | Full | |||
3717 | Half | |||
3727 | Half | |||
3737 | Half | |||
3758 | Full | |||
3768 | Full | |||
3778 | Full | |||
3788 | Full | |||
4758 | Half | |||
4768 | Half | |||
4778 | Half | |||
4968 | Half | |||
5008 | Full | |||
6008 | Half |
This is from some basic interrupt instrumentation in the DMA complete ISRs. None of the channels are performing quite as intended. Interestingly, the total number of ISRs over time does appear correct. (e.g. each channel has 5,000 half full and 5,000 full ISRs in 10 seconds).
Initially I was thinking the SPI data was getting deferred en route to the DMA, but we are losing more than just one 1ms cycle in some cases. Making SPI or DMA highest NVIC priority did not mitigate the issue, but there may still be something to resolve in the interrupt priorities.
Ultimately I am trying to understand how to resolve this behavior and get deterministic correct periods of SPI DMA interactions, and to have the underlying issue identified. I am working now to get more detailed interrupt profiling in case there is some interaction I am missing just in this context. Using SWD to do interrupt profiling (system-wide interrupt execution time) seemed like a good option, but the guides on doing this for interrupts appears to be little sparse.
The source code to start the SPI DMA transfers (and handling ISR callbacks) is as follows:
void init_dma_transfers(void)
{
HAL_SPI_Receive_DMA(&hspi1, buffer_a, 70);
HAL_SPI_Receive_DMA(&hspi2, buffer_b, 70);
HAL_SPI_Receive_DMA(&hspi5, buffer_c, 70);
HAL_SPI_Receive_DMA(&hspi6, buffer_d, 70);
}
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
{
// half complete handler
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
// full complete handler
}
The other relevant source and .ioc file are attached. Thank you for any assistance!
Solved! Go to Solution.
2025-10-20 5:41 PM
Looks like channel D data isn't coming in regularly. Nothing within the chip can delay it like this. In particular, the "Full" interrupt cannot be queued multiple times, like it would have to be in your example if the timing was regular.
2025-10-20 5:41 PM
Looks like channel D data isn't coming in regularly. Nothing within the chip can delay it like this. In particular, the "Full" interrupt cannot be queued multiple times, like it would have to be in your example if the timing was regular.