cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 SPI TXE flag Interrupt problem.

abhisheke
Associate II
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.

5 REPLIES 5
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
Associate II
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
Associate II
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.

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
Up vote any posts that you find helpful, it shows what's working..
abhisheke
Associate II
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.