How to cancel DMA based SPI transaction on ADuCM4050

HI Everyone

 

We are using the MUSKA SPI interface to communicate with an external Wifi module.

 

We are running the SPI interface at 12.5 Mbits/sec.

 

WE understand from the Wifi module vendor that it is critical that we maintain a steady SCLK signal once a transaction has been started (there should not be any stall in between bytes in the SCLK signal) or it can cause the Wifi module to hang.

 

It seems like the interrupt based transfer on Muska cannot keep up with updating the TX/RX buffers and causes the SCLK signal to stall. That is understandable since Muska only runs at 26 MHz. Even with Continuous Transfer enabled we see stalling in between bytes after 8 bytes have been transferred.

 

To solve the problem, I am trying to use DMA based SPI transfer. So far that works well when we know ahead of time exactly how many bytes we want to include in a transaction. With a DMA based transfer, the SCLK stalls disappear.

But, when we receive data over Wifi, we do not ahead of time know how much data we will be receiving. There is a separate Data Ready flow control data HW signal from the Wifi module which indicates when there is no more data to receive as SPI transaction is going on. We have to monitor that signal to see when to end the SPI transacation.

 

So my plan is the following for receiving Wifi data.

  1. Start a DMA based SPI transaction which is long enough to receive the maximum possible amount of data we can receive in 1 shot. Lets say 1500 bytes.
  2. When the transaction is ongoing, monitor the Data Ready signal to see when there is no more valid data during the current SPI transaction. (Lets for example say, the signal changes after 500 bytes of transfer).
  3. At this point, I would like to some abort the remainder of the DMA based SPI transaction, so I don’t waste time with the rest of the SPI transaction which will not yield any more valid data.

 

There does not seem to be much documentation in the HRM as to how we abort an SPI transaction. I wrote a function which tries to do that:

 

ADI_SPI_RESULT adi_spi_HaltTransaction(ADI_SPI_HANDLE const hDevice)

{

#ifdef ADI_DEBUG

    if (ADI_SPI_VALIDATE_HANDLE(hDevice))

    {

        return ADI_SPI_INVALID_HANDLE;

    }

#endif

        DebugPin1SetHigh();

        NVIC_DisableIRQ(hDevice->pDevInfo->eIRQn);

        NVIC_DisableIRQ((IRQn_Type)(hDevice->pDevInfo->dmaTxIrqNumber));

        NVIC_DisableIRQ((IRQn_Type)(hDevice->pDevInfo->dmaRxIrqNumber));

              

               //hDevice->pSpi->CTL &= (uint16_t)~((uint16_t) BITM_SPI_CTL_SPIEN);               //disable SPI

                   /* Clear possible interrupt sources: XFRDONE and underflow and overflow */ 

        hDevice->pSpi->IEN &= ~(BITM_SPI_IEN_XFRDONE|BITM_SPI_IEN_RXOVR|BITM_SPI_IEN_TXUNDR); 

        hDevice->bTransferComplete  = true;

        hDevice->pSpi->CNT = 0;                     //reset SPI transaction byte count.

       

    

               if( hDevice->bDmaMode==true )

               {

                              //disable SPI DMA

                              hDevice->pSpi->DMA &= (uint16_t)~(BITM_SPI_DMA_EN | BITM_SPI_DMA_RXEN | BITM_SPI_DMA_TXEN);

               }

       

        

        hDevice->pSpi->CTL |= (BITM_SPI_CTL_RFLUSH|BITM_SPI_CTL_TFLUSH);        //flush fifos

        //hDevice->pSpi->CTL &= (uint16_t)~(BITM_SPI_CTL_RFLUSH|BITM_SPI_CTL_TFLUSH);

        hDevice->pSpi->CTL &= (uint16_t)~BITM_SPI_CTL_CON;      //reset continuous mode

 

               //hDevice->pSpi->CTL |= BITM_SPI_CTL_SPIEN;                 //re-enable SPI

       

        /* Everything done, now just clear the STAT register */

        uint16_t nErrorStatus = hDevice->pSpi->STAT;

        hDevice->pSpi->STAT = nErrorStatus;

       

        hDevice->RxRemaining = 0u;

        hDevice->TxRemaining = 0u;

       

        DebugPin1SetLow();

        //DebugDelay1(10000);

                             

              

    return ADI_SPI_SUCCESS;

}

 

This seems to stop the current transaction. But when I start the next DMA based SPI transaction, it appears that the data being sent out on MOSI may still be data from the previous cancelled transaction. And I am getting CLK stalls in between bytes.

 

Is there any guidance on how to abort a DMA based SPI transaction and restart a new fresh one. That would be much appreciated.

 

Thanks,

Hans