cancel
Showing results for 
Search instead for 
Did you mean: 

I have an issue with the HAL_DMA_TransmitReceive() function. I am using full-duplex SPI communication between STM32F030R8T6 as master, and Nucleo-C031C6 as slave. I am only using DMA on the master side. My DMA clock is at 40MHz, SPI clock is at 10MHz.

DDjur.1
Associate II

The problem is I can successfully transmit-receive up to 4 bytes of data. Above that amount, anomalies happen. I need to transfer 20 bytes of data in both directions. Does this have anything to do with RXFIFO and TXFIFO buffers being 4 bytes, or is it something else?

Thanks!

4 REPLIES 4
gbm
Lead III

I guess the problem lies in the slave software but since you are not showing it there is no way to help you. SPI slave in not an easy thing to do on any MCU.

DDjur.1
Associate II

Thank you for your time and the response!

Here are some relevant code snippets:

SLAVE code segments for problem description: 

#define FRAME_SIZE 4

/* Receive data buffer (MOSI line) */

uint8_t rxData[FRAME_SIZE];

/* Transmit data buffer (MISO line) */

uint8_t txData[FRAME_SIZE];

/* txData buffer fill test */

for (int k = 0; k < FRAME_SIZE; k++)

 txData[k] += k;

/* Skipping unimportant lines of code for problem description purposes... */ 

int main(void)

{

  /* Skipping unimportant lines of code for problem description purposes... */ 

  MX_SPI1_Init();

  HAL_SPI_TransmitReceive_IT(&hspi1, (uint8_t *)&txData, (uint8_t *)&rxData, FRAME_SIZE);

  while (1)

  {

  }

}

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

  hspi1.Init.Direction = SPI_DIRECTION_2LINES;

  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

  hspi1.Init.NSS = SPI_NSS_HARD_INPUT;

  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;

  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

  hspi1.Init.CRCPolynomial = 7;

  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

  if (HAL_SPI_Init(&hspi1) != HAL_OK)

  {

    Error_Handler();

  }

}

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)

{

  HAL_SPI_TransmitReceive_IT(&hspi1, (uint8_t *)&txData, (uint8_t *)&rxData, FRAME_SIZE);

  while (SPI1->SR & SPI_SR_BSY) {};

  /* Data update test */

  for(int k = 0; k < FRAME_SIZE; k++)

   txData[k]++;

}

gbm
Lead III
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
  /* Data update test */
  for(int k = 0; k < FRAME_SIZE; k++)
   txData[k]++;
  HAL_SPI_TransmitReceive_IT(&hspi1, (uint8_t *)&txData, (uint8_t *)&rxData, FRAME_SIZE);
}

Try the above. Your original code blocks the interrupt and modifies the data while it should be transmitted.

DDjur.1
Associate II

Thank you for the reply! That is why I did this 'while (SPI1->SR & SPI_SR_BSY) {};' inside my original code. However, I tried your version and anything above 4 bytes does not cause the slave to ever go into the HAL_SPI_TxRxCpltCallback() function. If you have any suggestion as in why that may happen, it would be of great help.

Thanks a lot! 🙂