2021-11-08 01:39 PM
Hi there.
I'm struggling with the implementation of continuous SPI data transfer in Transmit only master mode with DMA in circular mode and enabled CRC calculation.
In any other configuration I've tried (DMA normal mode or SPI transfer with MCU polling) is CRC correctly added after data except after each data frame (5 bits) except circular mode.
In this case is CRC never generated and on physical SPI layer there is continuously transferring only data packet.
I can see that DMA transfer in circular mode is running correctly as data packet corresponds to continuously changing source data.
SPI clockrate = 50 MHz
SPI frame length = 5 bits
SPI CRC length = 5 bits
SPI inter data idleness = 1 bit
DMA mode = cicular mode
SPI communication with DMA in circular mode (configuration snippets below applied)
SPI communication with DMA in normal mode {CRC is added) STM presentation to the STM32H7 SPI says that combination of DMA circular mode and CRC should be possible LINK
Thanks in advance for any tips!
For debugging purpose I'm using standard HAL_SPI_Transmit_DMA function pointed to the GPIO register
HAL_SPI_Transmit_DMA(&hspi1, &GPIOC->IDR, 1);
SPI1 peripheral initialization function snippet
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_TXONLY;
hspi1.Init.DataSize = SPI_DATASIZE_5BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE;
hspi1.Init.CRCPolynomial = 0x20;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_5BIT;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_01CYCLE;
hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
SPI MSP init function snippet
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PD7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* SPI1 DMA Init */
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA1_Stream0;
hdma_spi1_tx.Init.Request = DMA_REQUEST_SPI1_TX;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
DMA init function snippet
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
2021-11-30 10:17 AM
Hello dear community?
Any suggestions?
Thanks in advance.
2025-01-03 02:00 AM
Hallo,
I have the same problem with a STM32H725.
My approach is a bit different, with the LL drivers, 8 Bit data width, 40 bytes frame length, 16 MHz clock, single transfer nor circular mode.
Every thing works but no CRC is appended.
Did you find a solution?
Has anybody any idea about that issue?
Thanks in advance.
2025-01-07 04:47 PM
I have the same issue as well, STM32H7 using SPI with circular DMA and attempting to use CRC associated with the SPI peripheral.
When diving into the HAL code I noticed this inside HAL_SPI_Transmit_DMA(), HAL_SPI_Receive_DMA() and HAL_SPI_TransmitReceive_DMA() within stm32h7xx_hal_spi.c
/* Set the number of data at current transfer */
if (hspi->hdmatx->Init.Mode == DMA_CIRCULAR)
{
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, 0UL);
}
else
{
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
}
If TSIZE is 0 the CRC will not be calculated. So it looks like ST have disabled the ability to use circular DMA + SPI + CRC