[SPI] Delay between enabling TDRE interrupt and interrupt being called - SAM v71 Xplained

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey all,

 

I'm working on SPI implementation (both master and slave) on SAM v71 and I'm having a delay between enabling TDRE interrupt, sending first byte and TDRE interrupt getting called.

I'm not using XDMAC as my frames are only 20 bytes long.

 

 

 

TDRE interrupt is getting called properly (as soon as data is transferred to shift register) after the delay after interrupt enable, for every other byte in same transfer, but the same thing happens for first byte in every other frame transfer (TDRE interrupt gets disabled in between frame transfers).

 

If I do 

while (spi->instance->SPI_SR & SPI_SR_TDRE_Msk);

after sending first byte, flag in status register is actually being set after just few clock cycles, its just interrupt that is not being called right away.

 

Here is my code for starting Write/Read:

boolean Spi_WriteRead(SpiObject* spi, void* txBuffer, size_t txSize, void* rxBuffer, size_t rxSize)
{
    boolean requestAccepted = FALSE;

    if ((((txBuffer != NULL) && (txSize > 0)) || ((rxBuffer != NULL) && (rxSize > 0))) && (spi->txIsBusy == FALSE))
    {
        spi->txBuffer = txBuffer;
        spi->rxBuffer = rxBuffer;
        spi->txCount = 0;
        spi->rxCount = 0;
        spi->txSize = (spi->txBuffer != NULL ? txSize : 0);
        spi->rxSize = (spi->rxBuffer != NULL ? rxSize : 0);

        spi->txIsBusy = TRUE;

        // flush unread data
        uint16_t dummyData = (spi->instance->SPI_RDR & SPI_RDR_RD_Msk) >> SPI_RDR_RD_Pos;
        (void)dummyData;

        // calculate number of dummy bytes to be sent
        if (spi->rxSize > spi->txSize)
            spi->dummySize = (spi->rxSize - spi->txSize);
        else
            spi->dummySize = 0;

        // start the write here, rest will happen from ISR
        if (spi->txCount < spi->txSize)
        {
            spi->instance->SPI_TDR = *((uint8_t*)spi->txBuffer);
            spi->txCount++;
        }
        else
        {
            spi->instance->SPI_TDR = (uint8_t)DUMMY_VALUE;
            spi->dummySize--;
        }
        
        // enable interrupts
        spi->instance->SPI_IER = SPI_IER_TDRE_Msk | SPI_IER_RDRF_Msk;
    }
	
    return requestAccepted;
}

 

Appreciate any info,

Dino

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Could the procedure calling Spi_WriteRead() be blocking  the SPI interrupt while it is doing other stuff (NVIC priority)?

Are SPI interrupts enabled/disabled in the NVIC between transactions?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for a late update.

 

SPI interrupt priority was set to max at one point, and it had no affect. Interrupts were also disabled between transactions since TDRE was getting called continuously while there was no transactions.

 

I have actually found the problem and it was pretty stupid unfortunately. I made a mistake while changing pin configuration and used wrong port for PIO interrupt for handshake. I have no idea how it worked at all, and with almost the same delay everytime.

 

Dino