Difference between DMA normal mode and circular mode - using SPI to sample a fast signal
Dear all. I stumbled across something I don't really understand. I'm trying to detect a signal using SPI1 on STM32f723 as fast as possible and fill a buffer. I configured SPI1 in SPI_DIRECTION_2LINES_RXONLY mode, set prescaler to SPI_BAUDRATEPRESCALER_2 hoping for 54MHz (I'm running 216MHz clock). Then I fed 6.75MHz square signal to the MISO. And when I configured DMA2 in DMA_NORMAL I get consistent values like 0x0f, 0x0f, 0x0f .... etc. However, when I switch to DMA_CIRCULAR i observe some kind of a shift in the data, like I was receiving more 0s than 1s. Is it even possible (I know it's a hack) to use SPI to consistently sample a signal at 54MHz? Maybe all it is able to guarantee is 54MHz during a single byte transfer, but it is adding some small delays between the consecutive bytes? My code:
void spiDmaConfig ()
{
SPIx_SCK_GPIO_CLK_ENABLE ();
SPIx_MISO_GPIO_CLK_ENABLE ();
SPIx_CLK_ENABLE ();
DMAx_CLK_ENABLE ();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = SPIx_SCK_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = SPIx_SCK_AF;
HAL_GPIO_Init (SPIx_SCK_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPIx_MISO_PIN;
GPIO_InitStruct.Alternate = SPIx_MISO_AF;
HAL_GPIO_Init (SPIx_MISO_GPIO_PORT, &GPIO_InitStruct);
/*--------------------------------------------------------------------------*/
DmaHandle.Instance = SPIx_RX_DMA_STREAM;
DmaHandle.Init.Channel = SPIx_RX_DMA_CHANNEL;
DmaHandle.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
DmaHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE;
DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE;
DmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
DmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
DmaHandle.Init.MemInc = DMA_MINC_ENABLE;
DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
DmaHandle.Init.Mode = DMA_NORMAL; // <------- Here I tried CIRCULAR.
DmaHandle.Init.Priority = DMA_PRIORITY_VERY_HIGH;
HAL_DMA_Init (&DmaHandle);
/* Associate the initialized DMA handle to the the SPI handle */
__HAL_LINKDMA (&SpiHandle, hdmarx, DmaHandle);
/*--------------------------------------------------------------------------*/
SpiHandle.Instance = SPIx;
SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
SpiHandle.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH;
SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SpiHandle.Init.CRCPolynomial = 7;
SpiHandle.Init.NSS = SPI_NSS_SOFT;
SpiHandle.Init.Mode = SPI_MODE_MASTER;
if (HAL_SPI_Init (&SpiHandle) != HAL_OK) {
/* Initialization Error */
Error_Handler ();
}
/*--------------------------------------------------------------------------*/
if (HAL_SPI_Receive_DMA (&SpiHandle, aRxBuffer0, BUFFER_SIZE) != HAL_OK) {
/* Transfer error in transmission process */
Error_Handler ();
}
/*--------------------------------------------------------------------------*/
HAL_Delay (200);
Error_Handler (); // Here I've got a breakpoint and I check the aRxBuffer0 contents
}
Thanks.

