2

I'm trying to send a variable size array of bytes over SPI using interrupts. The system is composed by two nucleo STM32L432 boards. The sender board works fine, but I'm having issue with the receiver board. Specifically, I noticed that very often some bytes are dropped. Beyond the default initialization provided by CubeMX, I have also the following settings in my init function:

// Trigger RXNE when the FIFO is 1/4 full
LL_SPI_SetRxFIFOThreshold(sw.spi_sw2pc,LL_SPI_RX_FIFO_TH_QUARTER);

// Enable RXNE interrupt
LL_SPI_EnableIT_RXNE(sw.spi_sw2pc);

// Enable SPI
if((SPI3->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
{
    // If disabled, I enable it
    SET_BIT(sw.spi_sw2pc->CR1, SPI_CR1_SPE);
}

The SPI is set to work at 10 Mbit/s. Can it be that the communication speed is too fast?

Following are the IRQ handler and the callback.

IRQ handler

void SPI3_IRQHandler(void)
{
  /* USER CODE BEGIN SPI3_IRQn 0 */
  /* Check RXNE flag value in ISR register */
    if(LL_SPI_IsActiveFlag_RXNE(SPI3))
    {
        /* Call function Slave Reception Callback */
        SW_rx_callback();
    }

  /* USER CODE END SPI3_IRQn 0 */
  /* USER CODE BEGIN SPI3_IRQn 1 */

  /* USER CODE END SPI3_IRQn 1 */
}

Callback

void SW_rx_callback(void)
{
    // RXNE flag is cleared by reading data in DR register

    while(LL_SPI_IsActiveFlag_RXNE(SPI3))
        recv_buffer[recv_buffer_index++] = LL_SPI_ReceiveData8(SPI3);

    if(LL_SPI_GetRxFIFOLevel(SPI3) == LL_SPI_RX_FIFO_EMPTY)
    {
        // If there are no more data
        new_data_arrived = true;
        memset(recv_buffer,'\0',recv_buffer_index);
        recv_buffer_index = 0;
    }

}

Thank you in advance for your help.

4
  • Seems, that the problem is caused by the speed, for test only try slow down communication speed. Do you use also other interrupts in your app with same or higher priority? Commented Jun 7, 2018 at 12:58
  • Setting the communication speed down to the minimum possible improves a lot. BTW, there is one more interrupt but it has a lower priority. Thank you. Commented Jun 7, 2018 at 16:45
  • if you have an logic analyzer, try to trace time spend in processing of interrupt (by setting an unused GPIO on enter interrupt and clear on exit) Commented Jun 7, 2018 at 17:45
  • Thanks for the advice. I will try it out. Commented Jun 7, 2018 at 18:10

1 Answer 1

4

SPI on 10 Mbits mean that you will have 1.25 millions interrupts per second (in case of 8bit transfer) and this is quite enough to process by interrupts especially in combination with HAL.

STM32L4xx is quite fast (80MHz) but in this case it mean that every interrupt call can't take longer than 64 cycles. but calling interrupt take 12 cycles, exit interrupt 10 cycles (it is in ideal state with no wait states on bus) so if your interrupt code will take 42 or more cycles then you can be sure that you miss some bytes.

Here are my suggestions:

  • First try to enable some compiler optimizations, to speed-up the code.
  • Change interrupt routine and remove everything unnecessary from interrupt handler (use SW FIFO and process received data in main loop)
  • But best solution in your case can be to use DMA transfer.
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your suggestions. Concerning the DMA, I was thinking about that. However, the problem is that the amount of data that will be transferred can vary and, based on the technical reference manual, there is nothing like IDLE line interrupt available for the SPI. Furthermore, the amount of data should not exceed 10 bytes. That's why I tried to use interrupts. I will definitely try to use some optimizations. BTW, do you have any idea or suggestion about the possibility to use DMA with a variable length message?
For variable data length try to use circular buffer. This circular buffer will be populated by DMA and your application (in main loop) will read the content. This need more effort to manage this but I think it will work.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.