Guillaume Petitjean
Guillaume Petitjean

Reputation: 2718

STM32H7 SPI communication: FIFO management problem

I've been struggling for quite a while now on my SPI setup.

The setup is as follows:

There is no Slave Select signal to control the slave.

Here is the code for the master. Everything done in polling and I've added some delay to let time to the Slave to work. The following function is called in loop, nothing else is done by the Master (in this simplified version that I used for debug):

uint32_t SPI_EnvoiCommandeTest(void)
{
uint32_t resp;
uint8_t statut;

SPI1->CFG2 |= SPI_CFG2_COMM_0;
SPI1->CFG2 &= ~SPI_CFG2_COMM_1;

SPI1->CR2 = 4;

SPI1->CR1 |= SPI_CR1_SPE;
SPI1->CR1 |= SPI_CR1_CSTART;

SPI1->TXDR = 0x12345678;

while ( (SPI1->SR & SPI_SR_EOT)  == 0 );

if ( (SPI1->SR & SPI_SR_ERR_MASK) != 0 )
{
    return ( SPI1->SR & SPI_SR_ERR_MASK);
}


SPI1->IFCR = 0xFFFFFFFF;


SPI1->CR1 &= ~SPI_CR1_SPE;

Delay(1000); 


SPI1->CFG2 |= SPI_CFG2_COMM_1;
SPI1->CFG2 &= ~SPI_CFG2_COMM_0;


SPI1->CR2 = 5;


SPI1->CR1 |= SPI_CR1_SPE;
SPI1->CR1 |= SPI_CR1_CSTART;

while ( (SPI1->SR & SPI_SR_EOT)  == 0 );
resp = SPI1->RXDR;
statut = *((__IO octet *)&(SPI1->RXDR));
if ( resp != 0x9ABCDEFF)
    while(1);
if ( statut != 0x77)
    while(1);

while ( (SPI1->SR & SPI_SR_EOT)  == 0 );

if ( (SPI1->SR & SPI_SR_ERR_MASK) != 0 )
{
    return ( SPI1->SR & SPI_SR_ERR_MASK);
}


SPI1->IFCR = 0xFFFFFFFF;


SPI1->CR1 &= ~SPI_CR1_SPE;


Delay(1000); 


return 0;
}

For the Slave, the reception is done by the interrupt handler. The main thread is just waiting for a flag to be set (set by SPI_StopReception()) and send 5 bytes of answer.

static void SPI_GenericHandler(SpiId_e SpiId)
{
SPI_TypeDef *Spi = SpiMgt[SpiId].SpiInstance;
uint32_t trigger = Spi->IER & Spi->SR;
uint32_t cmd;
uint8_t stat;

if (trigger & SPI_SR_RXP)
{


        cmd = Spi->RXDR;
        if (cmd != 0x12345678)
            while(1);
        while((Spi->SR & SPI_SR_EOT) == 0);

        if (Spi->SR & SPI_SR_CRCE)
            while(1);
        SPI_StopReception(SpiId);


    }

}
(...)

My problem is the following.

The communication is working fine hundreds of thousands of times and then fails at Slave side: instead of reading bytes 78 56 34 12 from the SPI FIFO, I read for example 34 12 00 00 or 56 34 12 00.

At first glance one would say it is simply the Slave that is too slow and missed some bytes BUT what is weird is that:

It is like there is a problem in the reading of the FIFO.

I've used a logic analyser and didn't identify any electrical issue.

Registers values at slave side, during a faulty reception (more precisely I break in the SPI RXP interrupt handler) are the following. In this occurence, I read 34 12 00 00:

Values of CTSIZE and RXPLVL are not really consistent (at least I don't understand them): since FTHVL=3 (4-data) and TSIZE=4 (same at Master side) , when I get a RXP event, I should have received at least 4 bytes. I don't see how CTSIZE can be 1 , neither why there would be another byte left in the FIFO (RXPLVL=1).

Any idea or suggestion ?

Upvotes: 2

Views: 4891

Answers (1)

Henrique M. Basso
Henrique M. Basso

Reputation: 11

I suggest reducing the sysclock speed below 250 MHz and testing. I am having some SPI communication problems here in my development, directly related to this speed. I believe there is a bug in the micro where it loses SPI packets when the speed is above 250 MHz. My microcontroller is an H750VBT6. I hope this helped. Best regards, Henrique Basso.

Upvotes: 1

Related Questions