macola995
macola995

Reputation: 159

Idea for SPI synchronization

I wonder if there is another way to synchronize SPI communication. In STM examples I find this part of code which works:

void Slave_Synchro(void)
{
    uint8_t txackbyte = SPI_SLAVE_SYNBYTE;
    uint8_t rxackbyte = 0x00;

    do
    {
        if (HAL_SPI_TransmitReceive_IT(&SpiHandle, (uint8_t *)&txackbyte, (uint8_t *)&rxackbyte, 1) != HAL_OK)
        {
            Error_Handler();
        }

        while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY){}
    }
    while (rxackbyte != SPI_MASTER_SYNBYTE);
}

Is there any solution where do while loop isn't used?

Upvotes: 2

Views: 607

Answers (1)

Clifford
Clifford

Reputation: 93446

If the issue with the do-while indefinite wait for sync is that you cannot have a "busy-wait" where you cannot do other wok, then solutions include:

  1. Use an RTOS scheduler and do the busy-wait wait in a separate SPI handler thread from the "other work"
  2. Rather than polling for HAL_SPI_STATE_READY, use the SPI interrupt and check for the synchronisation character in the interrupt handler.
  3. Do the "other work" in the do-while loop (so called "big-loop" or "executive loop" architecture).

In the big-loop solution you might have:

bool synchronised = false ;

while(;;)
{       
    if( !synchronised )
    {
        if( HAL_SPI_GetState(&SpiHandle) == HAL_SPI_STATE_READY )
        {
            if (HAL_SPI_TransmitReceive_IT(&SpiHandle, (uint8_t *)&txackbyte, (uint8_t *)&rxackbyte, 1) != HAL_OK)
            {
                 Error_Handler();
            }
        }

        synchronised == HAL_SPI_GetState(&SpiHandle) == HAL_SPI_STATE_READY &&
                        rxackbyte == SPI_MASTER_SYNBYTE);
    }

    if( synchronised )
    {
        // do SPI work
    }

    // do other work
}

You could tidy that up by creating a function such as:

bool isSlaveSynchronised()
{
    static bool synchronised = false ;

    if( !synchronised )
    {
        if( HAL_SPI_GetState(&SpiHandle) == HAL_SPI_STATE_READY )
        {
            if (HAL_SPI_TransmitReceive_IT(&SpiHandle, (uint8_t *)&txackbyte, (uint8_t *)&rxackbyte, 1) != HAL_OK)
            {
                 Error_Handler();
            }
        }

        synchronised == HAL_SPI_GetState(&SpiHandle) == HAL_SPI_STATE_READY &&
                        rxackbyte == SPI_MASTER_SYNBYTE);
    }

    return synchronised ;
}

Then:

while(;;)
{       
    if( !isSlaveSynchronised() )
    {
        // do SPI work
    }

    // do other work
}

Note here the take home is the general principle, not the precise code. Without knowing the nature of the slave device or the application is is not possible to be specific. Adapt to your needs.

Upvotes: 3

Related Questions