32 Bit SPI Master Transfer on K64 using ksdk v2.0

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

32 Bit SPI Master Transfer on K64 using ksdk v2.0

926 Views
peterprocek
Contributor I

Hi,

 

I'm using a K64 mcu which is communicating with an LTC2449 ADC via SPI. The ADC transfers 32bit frames, but the K64 seems to only have a max transfer of 16 bits per frame. How do I go about configuring the SPI device to transfer 32 bits correctly on the RX/TX lines.

My current scheme is built in freeRTOS, and sampling is done based on a PIT ISR which calls a function to do an DSPI RTOS transfer. Originally I had the master config for the spi device set up for 32 bits per frame, which I later discovered is incorrect as 16 bits is the Max. The goal was to enable the Receive FIFO Drain request and enter a DSPI ISR upon receiving 32bit ADC data and then process it.

 

How do I go about properly configuring a 32 bit transfer. I know it has to do with configuring essentially two 16 bit frames properly. My guess is to enable the continuous selection mode, create a half cycle delay, and send two frames. However, how do I do this when using the RTOS functions. Should I just create my own RTOS safe function that will do two 16 bit sequential transfers? Any help is greatly appreciated!

Labels (1)
0 Kudos
1 Reply

650 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Peter,

I see that you want to transfer 32 bits data in one SPI frame based on K64 in master mode, from hardware perspective, the spi module exactly supports to transfer 32 bits data in one frame by setting/clearing the CONT bit in SPIx_PUSHR for each spi transfer.

You have to change the spi driver manually. This is api functionDSPI_MasterTransferFillUpTxFifo() you have to modify, which is called in spi ISR:

static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle)
{
    uint16_t wordToSend = 0;
    uint8_t dummyData = DSPI_MASTER_DUMMY_DATA;

    /* If bits/frame is greater than one byte */
    if (handle->bitsPerFrame > 8)
    {
        /* Fill the fifo until it is full or until the send word count is 0 or until the difference
        * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth.
        * The reason for checking the difference is to ensure we only send as much as the
        * RX FIFO can receive.
        * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the
        * send data, hence the difference between the remainingReceiveByteCount and
        * remainingSendByteCount must be divided by 2 to convert this difference into a
        * 16-bit (2 byte) value.
        */
        while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) &&
               ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize))
        {
            if (handle->remainingSendByteCount <= 2)
            {
                if (handle->txData)
                {
                    if (handle->remainingSendByteCount == 1)
                    {
                        wordToSend = *(handle->txData);
                    }
                    else
                    {
                        wordToSend = *(handle->txData);
                        ++handle->txData; /* increment to next data byte */
                        wordToSend |= (unsigned)(*(handle->txData)) << 8U;
                    }
                }
                else
                {
                    wordToSend = dummyData;
                }
                handle->remainingSendByteCount = 0;
                base->PUSHR = handle->lastCommand | wordToSend;
            }
            /* For all words except the last word */
            else
            {
                if (handle->txData)
                {
                    wordToSend = *(handle->txData);
                    ++handle->txData; /* increment to next data byte */
                    wordToSend |= (unsigned)(*(handle->txData)) << 8U;
                    ++handle->txData; /* increment to next data byte */
                }
                else
                {
                    wordToSend = dummyData;
                }
                handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */
                base->PUSHR = handle->command | wordToSend;
            }

            /* Try to clear the TFFF; if the TX FIFO is full this will clear */
            DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);

            /* exit loop if send count is zero, else update local variables for next loop */
            if (handle->remainingSendByteCount == 0)
            {
                break;
            }
        } /* End of TX FIFO fill while loop */
    }
    /* Optimized for bits/frame less than or equal to one byte. */
    else
    {
        /* Fill the fifo until it is full or until the send word count is 0 or until the difference
        * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth.
        * The reason for checking the difference is to ensure we only send as much as the
        * RX FIFO can receive.
        */
        while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) &&
               ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize))
        {
            if (handle->txData)
            {
                wordToSend = *(handle->txData);
                ++handle->txData;
            }
            else
            {
                wordToSend = dummyData;
            }

//Rong modified:

   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

if(command->isPcsContinuous)

{

         handle->command|=SPI_PUSHR_CONT(command->isPcsContinuous);

}

else

{

         handle->command&=~SPI_PUSHR_CONT(command->isPcsContinuous);

}

pcsContinous=!command->isPcsContinuous;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            if (handle->remainingSendByteCount == 1)
            {
                base->PUSHR = handle->lastCommand | wordToSend;
            }
            else
            {
                base->PUSHR = handle->command | wordToSend;
            }

            /* Try to clear the TFFF; if the TX FIFO is full this will clear */
            DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);

            --handle->remainingSendByteCount;

            /* exit loop if send count is zero, else update local variables for next loop */
            if (handle->remainingSendByteCount == 0)
            {
                break;
            }
        }
    }
}

With the above code, You can toggle the CONT bit in interleave mode.

I DO NOT test the the code, pls have a try.

Hope it can help you.

BR

XiangJun Rong

0 Kudos