Hi Example how to use SPI in kinetis SDK - direct HAL mode

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

Hi Example how to use SPI in kinetis SDK - direct HAL mode

1,587 Views
eliar
Contributor II

Hi

 

I have an SPI external device that communicate through SPI ( registers and so)

I want to operate the KW40Z in SPI master mode where i will be able to  write and read  8 bytes.

I dont need the dspi package that do transfer of data from side to side, just the HAL.

My questions are:

1. is there an example how to do that simple work , because while investigating the subject i see that the SPI device is not linked and its under this define:

FSL_FEATURE_SOC_SPI_COUNT  which is 0.

This define close all the SPI HAL Device.

The current options i see now is to dig into the code of the API , enable the SPI and use the Hal_WriteData and ReadData

And configure the SPI to use as Master for external device.

 

It will be nice if NXP will provide an example project , that is mission is to enable SPI Master and read and write data to the HAL, No interrupts , no fifo , nothing, just read and write directly to the SPI.

 

Thanks,

Eli

Labels (1)
0 Kudos
1 Reply

614 Views
ivadorazinova
NXP Employee
NXP Employee

Hi Eli,

I apologize for my late response.

What we have for KW40Z supported in KSDK 1.3 is dspi demo located under

<ksdk_path>\MKW40Z160xxx4\examples\frdmkw40z\driver_examples\dspi

if you would like to work with SPI, please take a look at another demo, for example for FRDM-KL26Z.

If you need direct access to the HAL, please look at SPI driver, where is access to the HAL layer:

E.g. this function in fsl_spi_master_driver.c uses HAL

static spi_status_t SPI_DRV_MasterStartTransfer(uint32_t instance,

                                                const spi_master_user_config_t * device)

{

    /* instantiate local variable of type spi_master_state_t and point to global state */

    spi_master_state_t * spiState = (spi_master_state_t *)g_spiStatePtr[instance];

    uint32_t calculatedBaudRate;

    SPI_Type *base = g_spiBase[instance];

    /* Check that we're not busy.*/

    if (spiState->isTransferInProgress)

    {

        return kStatus_SPI_Busy;

    }

    /* Configure bus for this device. If NULL is passed, we assume the caller has

    * preconfigured the bus using SPI_DRV_MasterConfigureBus().

    * Do nothing for calculatedBaudRate. If the user wants to know the calculatedBaudRate

    * then they can call this function separately.

    */

    if (device)

    {

        SPI_DRV_MasterConfigureBus(instance, device, &calculatedBaudRate);

    }

    /* In order to flush any remaining data in the shift register, disable then enable the SPI */

    SPI_HAL_Disable(base);

    SPI_HAL_Enable(base);

#if FSL_FEATURE_SPI_16BIT_TRANSFERS

    spi_data_bitcount_mode_t bitCount;

    bitCount = SPI_HAL_Get8or16BitMode(base);

    /* Check the transfer byte count. If bits/frame > 8, meaning 2 bytes if bits/frame > 8, and if

    * the transfer byte count is an odd count we'll have to increase the transfer byte count

    * by one and assert a flag to indicate to the receive function that it will need to handle

    * an extra byte so that it does not inadverently over-write an another byte to the receive

    * buffer. For sending the extra byte, we don't care if we read past the send buffer since we

    * are only reading from it and the absolute last byte (that completes the final 16-bit word)

    * is a don't care byte anyway.

    */

    if ((bitCount == kSpi16BitMode) && (spiState->remainingSendByteCount & 1UL))

    {

        spiState->remainingSendByteCount += 1;

        spiState->remainingReceiveByteCount += 1;

        spiState->extraByte = true;

    }

    else

    {

        spiState->extraByte = false;

    }

#endif

    /* If the byte count is zero, then return immediately.*/

    if (spiState->remainingSendByteCount == 0)

    {

        SPI_DRV_MasterCompleteTransfer(instance);

        return kStatus_SPI_Success;

    }

    /* Save information about the transfer for use by the ISR.*/

    spiState->isTransferInProgress = true;

    spiState->transferredByteCount = 0;

    /* Make sure TX data register (or FIFO) is empty. If not, return appropriate

    * error status. This also causes a read of the status

    * register which is required before writing to the data register below.

    */

    if (SPI_HAL_IsTxBuffEmptyPending(base) != 1)

    {

        return kStatus_SPI_TxBufferNotEmpty;

    }

#if FSL_FEATURE_SPI_16BIT_TRANSFERS

    /* If the module/instance contains a FIFO (and if enabled), proceed with FIFO usage for either

    *  8- or 16-bit transfers, else bypass to non-FIFO usage.

    */

    if ((g_spiFifoSize[instance] != 0) && (SPI_HAL_GetFifoCmd(base)))

    {

        /* First fill the FIFO with data */

        SPI_DRV_MasterFillupTxFifo(instance);

        /* If the remaining RX byte count is less than the RX FIFO watermark, enable

        * the TX FIFO empty interrupt. Once the TX FIFO is empty, we are ensured

        * that the transmission is complete and can then drain the RX FIFO.

        * Else, enable the RX FIFO interrupt based on the watermark. In the IRQ

        * handler, another check will be made to see if the remaining RX byte count

        * is less than the RX FIFO watermark.

        */

        if (spiState->remainingReceiveByteCount < g_spiFifoSize[instance])

        {

            SPI_HAL_SetIntMode(base, kSpiTxEmptyInt, true); /* TX FIFO empty interrupt */

        }

        else

        {

            SPI_HAL_SetFifoIntCmd(base, kSpiRxFifoNearFullInt, true);

        }

    }

    /* Modules that support 16-bit transfers but without FIFO support */

    else

    {

        uint8_t byteToSend = 0;

        /* SPI configured for 16-bit transfers, no FIFO */

        if (bitCount == kSpi16BitMode)

        {

            uint8_t byteToSendLow = 0;

            uint8_t byteToSendHigh = 0;

            if (spiState->sendBuffer)

            {

                byteToSendLow = *(spiState->sendBuffer);

                ++spiState->sendBuffer;

                /* If the extraByte flag is set and these are the last 2 bytes, then skip this */

                if (!((spiState->extraByte) && (spiState->remainingSendByteCount == 2)))

                {

                    byteToSendHigh = *(spiState->sendBuffer);

                    ++spiState->sendBuffer;

                }

            }

            SPI_HAL_WriteDataLow(base, byteToSendLow);

            SPI_HAL_WriteDataHigh(base, byteToSendHigh);

            spiState->remainingSendByteCount -= 2;  /* decrement by 2 */

            spiState->transferredByteCount += 2;  /* increment by 2 */

        }

        /* SPI configured for 8-bit transfers, no FIFO */

        else

        {

            if (spiState->sendBuffer)

            {

                byteToSend = *(spiState->sendBuffer);

                ++spiState->sendBuffer;

            }

            SPI_HAL_WriteDataLow(base, byteToSend);

            --spiState->remainingSendByteCount;

            ++spiState->transferredByteCount;

        }

        /* Only enable the receive interrupt.  This should be ok since SPI is a synchronous

        * protocol, so every RX interrupt we get, we should be ready to send. However, since

        * the SPI has a shift register and data buffer (for transmit and receive), things may not

        * be cycle-to-cycle synchronous. To compensate for this, enabling the RX interrupt only

        * ensures that we do indeed receive data before sending out the next data word. In the

        * ISR we make sure to first check for the RX data buffer full before checking the TX

        * data register empty flag.

        */

        SPI_HAL_SetIntMode(base, kSpiRxFullAndModfInt, true);

    }

#else /* For SPI modules that do not support 16-bit transfers */

    /* Start the transfer by writing the first byte. If a send buffer was provided, the byte

    * comes from there. Otherwise we just send a zero byte. Note that before writing to the

    * data register, the status register must first be read, which was already performed above.

    */

    uint8_t byteToSend = 0;

    if (spiState->sendBuffer)

    {

        byteToSend = *(spiState->sendBuffer);

        ++spiState->sendBuffer;

    }

    SPI_HAL_WriteData(base, byteToSend);

    --spiState->remainingSendByteCount;

    ++spiState->transferredByteCount;

    /* Only enable the receive interrupt.  This should be ok since SPI is a synchronous

    * protocol, so every RX interrupt we get, we should be ready to send. However, since

    * the SPI has a shift register and data buffer (for transmit and receive), things may not

    * be cycle-to-cycle synchronous. To compensate for this, enabling the RX interrupt only

    * ensures that we do indeed receive data before sending out the next data word. In the

    * ISR we make sure to first check for the RX data buffer full before checking the TX

    * data register empty flag.

    */

    SPI_HAL_SetIntMode(base, kSpiRxFullAndModfInt, true);

#endif

    return kStatus_SPI_Success;

}

I hope this helps you.

Best Regards,

Iva

0 Kudos