STM32H753 SPI Slave Tx DMA Problem (Circular Mode)
When using SPI6 in Slave mode with TX DMA in Circular mode, the SPI FIFO is not updated with data from the DMA buffer for the first SPI FIFO size (8 bytes).

Both the SPI Master and SPI Slave were debugged:
The SPI Master transmits one frame.
On the SPI Slave board, after checking the reception using LL_BDMA_IsActiveFlag_TC1(BDMA), the MISO data is updated.
The SPI Master then checks the received data on the SPI Slave side using a breakpoint.
static void MX_SPI6_Init(void)
{
LL_SPI_InitTypeDef SPI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6;
PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_D3PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SPI6);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_3|LL_GPIO_PIN_4|LL_GPIO_PIN_5;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI6 DMA Init */
/* SPI6_TX Init */
LL_BDMA_SetPeriphRequest(BDMA, LL_BDMA_CHANNEL_0, LL_DMAMUX2_REQ_SPI6_TX);
LL_BDMA_SetDataTransferDirection(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_DIRECTION_MEMORY_TO_PERIPH);
LL_BDMA_SetChannelPriorityLevel(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_PRIORITY_VERYHIGH);
LL_BDMA_SetMode(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_MODE_CIRCULAR);
LL_BDMA_SetPeriphIncMode(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_PERIPH_NOINCREMENT);
LL_BDMA_SetMemoryIncMode(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_MEMORY_INCREMENT);
LL_BDMA_SetPeriphSize(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_PDATAALIGN_BYTE);
LL_BDMA_SetMemorySize(BDMA, LL_BDMA_CHANNEL_0, LL_BDMA_MDATAALIGN_BYTE);
/* SPI6_RX Init */
LL_BDMA_SetPeriphRequest(BDMA, LL_BDMA_CHANNEL_1, LL_DMAMUX2_REQ_SPI6_RX);
LL_BDMA_SetDataTransferDirection(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_DIRECTION_PERIPH_TO_MEMORY);
LL_BDMA_SetChannelPriorityLevel(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_PRIORITY_VERYHIGH);
LL_BDMA_SetMode(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_MODE_CIRCULAR);
LL_BDMA_SetPeriphIncMode(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_PERIPH_NOINCREMENT);
LL_BDMA_SetMemoryIncMode(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_MEMORY_INCREMENT);
LL_BDMA_SetPeriphSize(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_PDATAALIGN_BYTE);
LL_BDMA_SetMemorySize(BDMA, LL_BDMA_CHANNEL_1, LL_BDMA_MDATAALIGN_BYTE);
/* SPI6 interrupt Init */
NVIC_SetPriority(SPI6_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),1, 0));
NVIC_EnableIRQ(SPI6_IRQn);
/* SPI6 parameter configuration*/
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_SLAVE;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_HARD_INPUT;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 0x0;
LL_SPI_Init(SPI6, &SPI_InitStruct);
LL_SPI_SetStandard(SPI6, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_SetFIFOThreshold(SPI6, LL_SPI_FIFO_TH_01DATA);
LL_SPI_DisableNSSPulseMgt(SPI6);
}
static inline void spi_init(uint8_t *rx_data, uint8_t *tx_data, uint8_t size) {
LL_BDMA_InitTypeDef bdma_init_struct = {0};
bdma_init_struct.PeriphOrM2MSrcAddress = (uint32_t)&SPI6->RXDR;
bdma_init_struct.MemoryOrM2MDstAddress = (uint32_t)rx_data;
bdma_init_struct.Direction = LL_BDMA_DIRECTION_PERIPH_TO_MEMORY;
bdma_init_struct.Mode = LL_BDMA_MODE_CIRCULAR;
bdma_init_struct.MemoryOrM2MDstIncMode = LL_BDMA_MEMORY_INCREMENT;
bdma_init_struct.NbData = size;
bdma_init_struct.PeriphRequest = LL_DMAMUX2_REQ_SPI6_RX;
LL_BDMA_Init(BDMA, LL_BDMA_CHANNEL_1, &bdma_init_struct);
LL_BDMA_StructInit(&bdma_init_struct);
bdma_init_struct.PeriphOrM2MSrcAddress = (uint32_t)&SPI6->TXDR;
bdma_init_struct.MemoryOrM2MDstAddress = (uint32_t)tx_data;
bdma_init_struct.Direction = LL_BDMA_DIRECTION_MEMORY_TO_PERIPH;
bdma_init_struct.Mode = LL_BDMA_MODE_CIRCULAR;
bdma_init_struct.MemoryOrM2MDstIncMode = LL_BDMA_MEMORY_INCREMENT;
bdma_init_struct.NbData = size;
bdma_init_struct.PeriphRequest = LL_DMAMUX2_REQ_SPI6_TX;
LL_BDMA_Init(BDMA, LL_BDMA_CHANNEL_0, &bdma_init_struct);
LL_BDMA_EnableChannel(BDMA, LL_BDMA_CHANNEL_1);
LL_BDMA_EnableChannel(BDMA, LL_BDMA_CHANNEL_0);
LL_SPI_EnableDMAReq_RX(SPI6);
LL_SPI_EnableDMAReq_TX(SPI6);
LL_SPI_Enable(SPI6);
LL_BDMA_EnableChannel(BDMA, LL_BDMA_CHANNEL_1);
LL_BDMA_EnableChannel(BDMA, LL_BDMA_CHANNEL_0);
}
__attribute__((section(".non_cache"))) uint8_t recvData[17];
__attribute__((section(".non_cache"))) uint8_t sendData[17];
int main(void)
{
MX_SPI6_Init();
spi_init(recvData, sendData, 17);
while(1) {
if (LL_BDMA_IsActiveFlag_TC1(BDMA)) {
LL_BDMA_ClearFlag_TC1(BDMA);
for (i = 0; i < 17; i++) {
sendData[i] = test_idx;
test_idx++;
}
}
}
}
Post edited by ST moderator to apply source code formatting and add the appropriate labels. Please read this post: How to insert source code. It's recommended to use </> button to paste your code.
