Skip to main content
abhisheke
Associate II
June 4, 2015
Question

STM32F407 SPI TXE flag Interrupt problem.

  • June 4, 2015
  • 5 replies
  • 1435 views
Posted on June 04, 2015 at 11:53

Hi,

I am using the STM32F407 SPI TXE and RXNE interrupts.

The ISR checks if there is data to transmit or if any data is received.

The data to be transmitted is filled outside the ISR and the TXE interrupt and CS is enabled here.

If there is no data to be transmitted, the TXE interrupt is disabled and CS is held low.

But, after the last data is transmitted, the TXE flag still remains HIGH and the execution keeps reentering the ISR over and over.

Furthermore, the RXNE flag is never SET. So no data is received.

I watched the DR register and data seems to be clocked out.

    This topic has been closed for replies.

    5 replies

    waclawek.jan
    Super User
    June 4, 2015
    Posted on June 04, 2015 at 13:39

    > But, after the last data is transmitted, the TXE flag still remains HIGH and the execution keeps reentering the ISR over and over.

    That's how it's supposed to work - it is an indicator of tx (holding) register empty. Disable the interrupt after last byte.

    > Furthermore, the RXNE flag is never SET. So no data is received.

    Don't look at it in the debugger.

    JW

    abhisheke
    abhishekeAuthor
    Associate II
    June 4, 2015
    Posted on June 04, 2015 at 13:55

    Hi Jan,

    Thank you for replying.

    I didn't understand the second part > Don't look at it in the debugger.

    Here's my interrupt routine:-

    void SPI2_IRQHandler(void)

    {

      if(SPI_I2S_GetITStatus(My_SPI, SPI_I2S_IT_TXE) == SET)

      {

        if(TxDiffPtr > 0)

        {

          SPI_I2S_SendData(My_SPI, gu8a_Tx[TxRdPtr]);

          TxRdPtr++;

          TxDiffPtr--;

          if(TxRdPtr >= TX_RX_SIZE)

          {

            TxRdPtr = 0;

          }

        }

        else

        {

          SPI_I2S_ITConfig(My_SPI, SPI_I2S_IT_TXE, DISABLE);

        }

      }

      if(SPI_I2S_GetITStatus(My_SPI, SPI_I2S_IT_RXNE) == SET)

      {

          gu8a_Rx[RxWrPtr] = SPI_I2S_ReceiveData(My_SPI);

          RxWrPtr++;

          RxDiffPtr++;

          if(RxWrPtr >= TX_RX_SIZE)

          {

            RxWrPtr = 0;

          }

          SPI_I2S_ITConfig(My_SPI, SPI_I2S_IT_RXNE, DISABLE);

      }

    }

    abhisheke
    abhishekeAuthor
    Associate II
    June 5, 2015
    Posted on June 05, 2015 at 13:26

    and the routines to send data to the slave and read data from it...

    For sending data:-

     CS_LOW();      //Slave enabled

      for (int i = 0; i < length; i++)

      {

        gu8a_Tx[TxWrPtr] = data[i];

        TxWrPtr++;

        TxDiffPtr++;

        if(TxWrPtr >= TX_RX_SIZE)

        {

          TxWrPtr = 0;

        }

      }

    For receiving data:-

      CS_LOW();

      for (int j = 0; j < length; j++)

      {

        if(RxDiffPtr > 0)

        {

          data[j] =  gu8a_Rx[RxRdPtr];

          RxRdPtr++;

          RxDiffPtr--;

          if(RxRdPtr >= TX_RX_SIZE)

          {

            RxRdPtr = 0;

          }

        }

      }

    I get the interrupts, but no communication though.

    Regards,

    Abhishek.

    Tesla DeLorean
    Guru
    June 5, 2015
    Posted on June 05, 2015 at 18:07

    I didn't understand the second part > Don't look at it in the debugger.

     

    The debugger will change the behaviour of the peripheral if you park a register view over it. So DON'T do that, because it's invasive.

    Check also that you are using volatile keyword for variables changed under interrupt, and the wisdom of using non-atomic operations to manage content.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    abhisheke
    abhishekeAuthor
    Associate II
    June 6, 2015
    Posted on June 06, 2015 at 06:53

    Hi Clive,

    Thank you very much for replying.

    I declared the variables used in interrupt as volatile.

    I probed the SPI clock when SPI_I2S_SendData(My_SPI, gu8a_Tx[TxRdPtr]); is called from interrupt, and clock is generated.

    In order to keep record of read, write and difference pointers, i am using for loop(atomic operation of copying byte one-by-one into buffer) rather than non-atomic operation(memcpy), if that is what you meant.

    To summarize upto now, i get the TXE interrupts, and spi clock is generated when data is transmitted to the slave. But still unable to receive any data. So i suppose that actually the slave is not receiving any data at all.

    Regards,

    Abhishek.