0
\$\begingroup\$

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);

}
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

The following solved the problem:

__HAL_RCC_SPI5_FORCE_RESET();

__HAL_RCC_SPI5_RELEASE_RESET();

__HAL_RCC_DMA2_FORCE_RESET();

__HAL_RCC_DMA2_RELEASE_RESET();

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.