When running some simple code to test the SPI communication using DMA, the program only works as expected after stopping and restarting the microcontroller.
The first time it runs, instead of sending 10 bytes, it only sends 8, and waits forever for the transmit complete flag to be activated, which is addressed inside the callback function. After restarting the program, it runs continuously, and the flag resets every time data is sent.
main.c:
#define BUFFER_SIZE 10
/* USER CODE BEGIN PV */
uint8_t RX_Buffer[BUFFER_SIZE];
uint8_t TX_Buffer[BUFFER_SIZE] = {60,61,62,63,64,65,66,67,68,69};
volatile int rxtxflag = 0;
volatile int rxtxhalfflag = 0;
/* USER CODE END PV */
int main(void)
{
HAL_Init();
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI5_Init();
while (1)
{
HAL_SPI_TransmitReceive_DMA(&hspi5, TX_Buffer, RX_Buffer, sizeof(TX_Buffer));
while (!(rxtxflag && rxtxhalfflag));
rxtxflag = 0;
rxtxhalfflag = 0;
GPIOH->ODR ^= (1U<<15);
HAL_Delay(1000);
}
}
Callback functions:
void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef * hspi)
{
rxtxhalfflag = 1;
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef * hspi)
{
rxtxflag = 1;
}
SPI initialization:
void MX_SPI5_Init(void)
{
/* USER CODE BEGIN SPI5_Init 0 */
/* USER CODE END SPI5_Init 0 */
/* USER CODE BEGIN SPI5_Init 1 */
/* USER CODE END SPI5_Init 1 */
hspi5.Instance = SPI5;
hspi5.Init.Mode = SPI_MODE_MASTER;
hspi5.Init.Direction = SPI_DIRECTION_2LINES;
hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi5.Init.NSS = SPI_NSS_SOFT;
hspi5.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi5.Init.CRCPolynomial = 0x0;
hspi5.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi5.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi5.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi5.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi5.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
hspi5.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi5.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi5.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi5.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi5.Init.IOSwap = SPI_IO_SWAP_DISABLE;
if (HAL_SPI_Init(&hspi5) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI5_Init 2 */
SPI5->CR1 |= (1<<0); //enable
SPI5->CR1 |= (1<<9); //start
/* USER CODE END SPI5_Init 2 */
}
DMA initialization:
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
/* DMA2_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
}