cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with SPI status flag ''Rx buffer not empty'' at SPI Baudrateprescaler 2

Andreas Fischer
Associate II
Posted on January 04, 2017 at 12:53

I have a Nucleo-F446RE Eval Board with a STM32F446 RET6U. I use the SPI2 peripheral. When I switched from baudrate prescaler 4 to 2 I get problems with the SPI status flag 'Rx buffer not empty': The last flag does not trigger at certain conditions. When a additional delay is generated in the write/read process of a SPI Byte, the flag triggers. Is it possible, that the 'Tx buffer empty' and 'Rx buffer not empty' flags can cause an access conflict at the flag register?

I added pictures to describe the situation more clearly:

The yellow line corresponds to the SPI CLK. The blue line corresponds to a 'Rx buffer not empty' flag trigger action.

Picture 1:

Baudrate prescaler 4 is used. Bytes are written after 'Tx buffer empty' flag triggers. All three 'Rx buffer not empty' flags trigger.

Picture 2:

Baudrate prescaler 2 is used. Bytes are written after 'Rx buffer not empty' flag triggers and data register has been read out. All three 'Rx buffer not empty' flags trigger.

Picture 3:

Baudrate prescaler 2 is used. Bytes are written after 'Tx buffer empty' flag triggers. Only the first and second 'Rx buffer not empty' flags trigger.

Picture 4:

Baudrate prescaler 2 is used. Bytes are written after 'Tx buffer empty' flag triggers. Now additional delays have been added. All three 'Rx buffer not empty' flags trigger.

7 REPLIES 7
Posted on January 04, 2017 at 13:35

> The blue line corresponds to a 'Rx buffer not empty' flag trigger action.

How?

JW

Andreas Fischer
Associate II
Posted on January 04, 2017 at 14:19

I change the status of a µC output pin, if the 'if statement' checks the 'Rx buffer not empty' flag with positive result. The external pin is observed together with the SPI CLK on the oscilloscope. If one 'Rx buffer not empty' flag does not trigger, the SPI read out does not happen. Because the 'Rx buffer not empty' flag clears only with a readout, the Overrun flag triggers then and signalizes an error. Subsequent data will be lost.

Posted on January 04, 2017 at 14:35

Post a minimal but complete compilable code exhibiting the problem.

JW

Posted on January 05, 2017 at 12:46

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6oP&d=%2Fa%2F0X0000000bw1%2FH07GP8e3QL.Dh1G2gQdK0_wFIET9J6zHuDT8mwO1z10&asPdf=false
Posted on January 05, 2017 at 14:39

I don't see the 'I change the status of a µC output pin, if the 'if statement' checks the 'Rx buffer not empty' flag with positive result.' in the above code.

JW

Posted on January 05, 2017 at 15:53

I forgot unintentionally to add the pin set code. I edited the code above in the section /* Wait until RXNE flag is reset */in the function 'SPI_WriteRead'.

Posted on January 05, 2017 at 19:20

Well, I am convinced that code used to produce the given waveforms differed in more than just this.

Nevertheless, the mechanism of failure will be similar to this - I am unrolling the loop as it executes:

while((TxCount > 0U) || (RxCount > 0U))

    {

        /* check TXE flag */

        if((TxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_TXE)))          

TxCount==3, TXE==1

        {

            *(__IO uint8_t *)&SPI_INSTANCE->DR = (*pTxData++);      

start Tx 1st byte

            TxCount--;

         }

         /* Wait until RXNE flag is reset */

         if((RxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_RXNE)))        

RXNE==0, so skipped

{

            (*(uint8_t *)pRxData++) = SPI_INSTANCE->DR;

            RxCount--;

            GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);

            GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);

         }

         /* Check if timeout is reached */                          

at around this time 1st byte Tx/Rx finished; RXNE gets set

         if((CLOCK_GetTime()-tickstart) >=  SPI_TIMEOUT)

         {

             error_code = HAL_TIMEOUT;

             goto error; // stop transmit and receive immediately

         }

   

loop

        /* check TXE flag */

        if((TxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_TXE)))          

TxCount==2, TXE==1

        {

            *(__IO uint8_t *)&SPI_INSTANCE->DR = (*pTxData++);      

start Tx 2nd byte

            TxCount--;

         }

         /* Wait until RXNE flag is reset */

         if((RxCount > 0U) && (SPI_GET_FLAG(SPI_FLAG_RXNE)))        

RXNE==1

           {                                                        

at around this time 2nd byte Tx/Rx finished; Rx overflow

            (*(uint8_t *)pRxData++) = SPI_INSTANCE->DR;

            RxCount--;

            GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);         

first pulse

            GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);

      

[...]