Skip to main content
IMuly
Associate
Aug 15, 2019 12:38 PM UTC
Solved

SPI receive in interrupt mode lost last 2 bytes (STM32F103RC)

Hello!

I'm testing the communications between SPI1 and SPI3 in STM32F103RC.

SPI1 and SPI3 are using interrupts, dma is off.

When I try to read received bytes I found that rdata[6] = 0 and rdata[7] = 0, but must be 0x7 and 0x8 respectively.

When I use DMA on both sides everything is OK.

And when I use transmit function in blocking mode(i.e HAL_SPI_Transmit()) everything is OK.

Speed_medium means prescaller_16.

HSE = 8MHz

RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

spi_mode0 is CPOL=0, CPHA =0;

nss controlled by hardware.

uint8_t tdata[8] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};

uint8_t rdata[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

er = initSPI(SPI3, type_master, spi_mode0, speed_medium, dma_disable, NULL, tcv, size_8bit, dir_RXTX, firstbit_LSB, crc_disable);

   TEST_ASSERT_MESSAGE(HAL_OK == er, "SPI3 Init failed");

er = initSPI(SPI1, type_slave, spi_mode0, speed_medium, dma_disable, rcv, NULL, size_8bit, dir_RXTX, firstbit_LSB, crc_disable);

TEST_ASSERT_MESSAGE(HAL_OK == er, "SPI1 Init failed");

TEST_ASSERT_MESSAGE(HAL_SPI_Receive_IT(&hspi1, rdata, 8) == HAL_OK, "SPI1 receive failed");

   TEST_ASSERT_MESSAGE(HAL_SPI_Transmit_IT(&hspi3, tdata, 8) == HAL_OK, "SPI3 transmit failed");

   TEST_ASSERT_EQUAL_INT(hspi1.ErrorCode, 0);

   TEST_ASSERT_EQUAL_INT(hspi3.ErrorCode, 0);

I found the solution in driver HAL.

In SPI_TxISR_8BIT I added small delay.

static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi)

{

 *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr);

 hspi->pTxBuffPtr++;

 hspi->TxXferCount--;

 HAL_Delay(1);

 if (hspi->TxXferCount == 0U)

 {

#if (USE_SPI_CRC != 0U)

   if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)

   {

     /* Enable CRC Transmission */

     SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);

   }

#endif /* USE_SPI_CRC */

   SPI_CloseTx_ISR(hspi);

 }

}

Do you think this is a normal solution or is there a more elegant solution?

This topic has been closed for replies.
waclawek.jan
waclawek.janBest answer
Super User
Aug 15, 2019 1:23 PM UTC

Set mutual priorities of the interrupts so that the Rx interrupt service routine (ISR) can nest into ("preempt") the Tx ISR (and don't forget to set NVIC_SetPriorityGrouping() appropriately).

JW

3 replies

waclawek.jan
waclawek.janBest answer
Super User
Aug 15, 2019 1:23 PM UTC

Set mutual priorities of the interrupts so that the Rx interrupt service routine (ISR) can nest into ("preempt") the Tx ISR (and don't forget to set NVIC_SetPriorityGrouping() appropriately).

JW

IMuly
IMulyAuthor
Associate
Aug 15, 2019 3:32 PM UTC

Thank you for your answer!

But there are no separate interrupts in HAL for Rx and Tx. only for global SPI.

35 42 settable SPI1 SPI1 global interrupt 0x0000_00CC

36 43 settable SPI2 SPI2 global interrupt 0x0000_00D0

51 58 settable SPI3 SPI3 global interrupt 0x0000_010C

IMuly
IMulyAuthor
Associate
Aug 15, 2019 4:36 PM UTC

I decrease the priority of SPI3, and increase SPI1.

Everything is working fine.

Thank you again!