cancel
Showing results for 
Search instead for 
Did you mean: 

Clear SPI Rx buffer using DMA and resume receiving.

TKawa.9
Associate II

Hello.

 

Two NUCLEO-G431RBs are used for SPI communication.

One is used as SPI master and one as SPI slave, and the pins of SCK and MOSI are connected to each other using jumper cables.

 

Communication works fine most of the time.

However, when the other power line is energized, once the clock skips or excessive clock due to EMI occurs, and subsequent data cannot be received accurately. I assume this is due to data remaining in the Rx buffer.

Therefore, I have tried clearing the Rx buffer, but after clearing it, when I resume receiving, the receive callback is not called, so it seems it is not resumed.

Please let me know if you know the cause.

 

// master settings  

  hspi1.Instance = SPI1;

  hspi1.Init.Mode = SPI_MODE_MASTER;

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

  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;

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

  HAL_SPI_Transmit_DMA(&hspi1, spi1Buffer, strlen((char const*) spi1Buffer));

 

// slave settings  

  hspi2.Instance = SPI2;

  hspi2.Init.Mode = SPI_MODE_SLAVE;

  hspi2.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;

  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;

  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

  hspi2.Init.NSS = SPI_NSS_SOFT;

  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

  hspi2.Init.CRCPolynomial = 7;

  hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

  hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

  hdma_spi2_rx.Instance = DMA1_Channel2;

  hdma_spi2_rx.Init.Request = DMA_REQUEST_SPI2_RX;

  hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

  hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;

  hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;

  hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

  hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

  hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;

  hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;

  HAL_SPI_Receive_DMA(&hspi2, spi2Buffer, strlen((char const*) spi2Buffer));

 

  if(strncmp((char *)spi2Buffer, "HR", 2) != 0){

    // Reset will normalize communication, but I don't want to reset.

    // HAL_NVIC_SystemReset();

    HAL_SPI_DMAStop(&hspi2);

    while(HAL_SPI_DeInit(&hspi2) != HAL_OK);

    __HAL_RCC_SPI2_FORCE_RESET();

    __HAL_RCC_DMA1_FORCE_RESET();

    __HAL_RCC_DMA1_RELEASE_RESET();

    __HAL_RCC_SPI2_RELEASE_RESET();

      /* DMA controller clock enable */

    __HAL_RCC_DMAMUX1_CLK_ENABLE();

    __HAL_RCC_DMA1_CLK_ENABLE();

    /* DMA1_Channel2_IRQn interrupt configuration */

    HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 1, 0);

    HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);

   

    HAL_SPI_Init(&hspi2);

    HAL_SPI_Receive_DMA(hspi2, spi2Buffer, strlen((char const*) spi2Buffer));

  }

1 REPLY 1
TDK
Guru

Since you de-initialized DMA, you will need to do the appropriate HAL_DMA_Init call. Or don't do the FORCE_RESET stuff. Either use HAL, or use registers, but trying to do both often leads to issues.

Compare DMA and SPI registers after the first initialization and after your re-initialization to determine quickly what is different.

> strlen((char const*) spi2Buffer)

This is almost assuredly not what you want, as you don't know what the contents of the buffer are. Perhaps you wanted sizeof(spi2Buffer).

If you feel a post has answered your question, please click "Accept as Solution".