mirror of https://github.com/ARMmbed/mbed-os.git
MCUXpresso: Update Kinetis SPI SDK drivers
Added dummy data setup API to allow users to configure the dummy data to be transferred. Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>pull/11268/head
parent
4102114a72
commit
33b66ffa60
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi"
|
||||
#endif
|
||||
|
||||
/*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
|
||||
enum _spi_transfer_states_t
|
||||
{
|
||||
|
@ -46,12 +30,6 @@ typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle);
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sends a buffer of data bytes in non-blocking way.
|
||||
|
@ -71,6 +49,14 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
*/
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
||||
|
||||
/*!
|
||||
* @brief Get the waterrmark value for this SPI instance.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @return Watermark value for the SPI instance.
|
||||
*/
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Send a piece of data for SPI.
|
||||
*
|
||||
|
@ -78,6 +64,7 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
* and write the data into it. At the same time, this function updates the values in
|
||||
* master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
@ -89,9 +76,18 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* and write the data to destination address. At the same time, this function updates
|
||||
* the values in master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Common IRQ handler for SPI.
|
||||
*
|
||||
* @param base SPI base pointer.
|
||||
* @param instance SPI instance number.
|
||||
*/
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance);
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
@ -101,21 +97,31 @@ static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
static SPI_Type *const s_spiBases[] = SPI_BASE_PTRS;
|
||||
/*! @brief IRQ name array */
|
||||
static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/*! @brief Clock array name */
|
||||
static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS;
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||
static spi_isr_t s_spiIsr;
|
||||
static spi_isr_t s_spiMasterIsr;
|
||||
static spi_isr_t s_spiSlaveIsr;
|
||||
|
||||
/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
|
||||
volatile uint8_t g_spiDummyData[ARRAY_SIZE(s_spiBases)] = {0};
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* brief Get the instance for SPI module.
|
||||
*
|
||||
* param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_SPI_COUNT; instance++)
|
||||
for (instance = 0; instance < ARRAY_SIZE(s_spiBases); instance++)
|
||||
{
|
||||
if (s_spiBases[instance] == base)
|
||||
{
|
||||
|
@ -123,15 +129,28 @@ uint32_t SPI_GetInstance(SPI_Type *base)
|
|||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_SPI_COUNT);
|
||||
assert(instance < ARRAY_SIZE(s_spiBases));
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Set up the dummy data.
|
||||
*
|
||||
* param base SPI peripheral address.
|
||||
* param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData)
|
||||
{
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
g_spiDummyData[instance] = dummyData;
|
||||
}
|
||||
|
||||
static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
/* Check if 16 bits or 8 bits */
|
||||
|
@ -155,13 +174,13 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
base->DL = *buffer++;
|
||||
}
|
||||
#else
|
||||
base->D = *buffer++;
|
||||
base->D = *buffer++;
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
}
|
||||
/* Send dummy data */
|
||||
else
|
||||
{
|
||||
SPI_WriteData(base, SPI_DUMMYDATA);
|
||||
SPI_WriteData(base, ((uint32_t)g_spiDummyData[instance] << 8 | g_spiDummyData[instance]));
|
||||
}
|
||||
i += bytesPerFrame;
|
||||
}
|
||||
|
@ -169,7 +188,7 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -205,18 +224,68 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get the watermark value of transfer. Please note that the entery width of FIFO is 16 bits. */
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t rxSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
rxSize = (base->C3 & SPI_C3_RNFULLF_MARK_MASK) >> SPI_C3_RNFULLF_MARK_SHIFT;
|
||||
if (rxSize == 0U)
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
ret = 1U;
|
||||
}
|
||||
#else
|
||||
ret = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SPI_SendInitialTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytestoTransfer = handle->bytePerFrame;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
if (handle->watermark > 1)
|
||||
{
|
||||
/* In the first time to send data to FIFO, if transfer size is not larger than
|
||||
* the FIFO size, send all data to FIFO, or send data to make the FIFO full.
|
||||
* Besides, The FIFO's entry width is 16 bits, need to translate it to bytes.
|
||||
*/
|
||||
bytestoTransfer = MIN(handle->txRemainingBytes, (FSL_FEATURE_SPI_FIFO_SIZEn(base) * 2));
|
||||
}
|
||||
#endif
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->txRemainingBytes);
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPTEF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
if (bytes != 0U)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
}
|
||||
|
||||
/* Send data */
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
|
@ -231,11 +300,11 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
}
|
||||
handle->txRemainingBytes -= bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
/* As a slave, send data until SPTEF cleared */
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes > 0))
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes >= bytes))
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
|
||||
|
@ -253,56 +322,96 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
if (base->S & SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
/* The FIFO's entry width is 16 bits, need to translate it to bytes. */
|
||||
uint8_t bytestoTransfer = handle->watermark * 2;
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytes;
|
||||
}
|
||||
handle->txRemainingBytes -= bytes;
|
||||
if (handle->txRemainingBytes < 8U)
|
||||
{
|
||||
bytestoTransfer = handle->txRemainingBytes;
|
||||
}
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->rxRemainingBytes);
|
||||
uint8_t val = 1U;
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPRF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
val = base->S & SPI_S_SPRF_MASK;
|
||||
if (bytes != 0U)
|
||||
if (base->S & SPI_S_SPRF_MASK)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (val)
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
/* While rx fifo not empty and remaining data can also trigger the last interrupt */
|
||||
while ((base->S & SPI_S_RFIFOEF_MASK) == 0U)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
|
||||
/* If the reamining data equals to watermark, leave to last interrupt */
|
||||
if (handle->rxRemainingBytes == (handle->watermark * 2U))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI master configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_MasterInit().
|
||||
* User may use the initialized structure unchanged in SPI_MasterInit(), or modify
|
||||
* some fields of the structure before calling SPI_MasterInit(). After calling this API,
|
||||
* the master is ready to transfer.
|
||||
* Example:
|
||||
code
|
||||
spi_master_config_t config;
|
||||
SPI_MasterGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to master config structure
|
||||
*/
|
||||
void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
||||
{
|
||||
config->enableMaster = true;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableMaster = true;
|
||||
config->enableStopInWaitMode = false;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
config->dataMode = kSPI_8BitMode;
|
||||
|
@ -313,17 +422,37 @@ void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
|||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->baudRate_Bps = 500000U;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with master configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch, or be set with default
|
||||
* values by SPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_master_config_t config = {
|
||||
.baudRate_Bps = 400000,
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
* param srcClock_Hz Source clock frequency.
|
||||
*/
|
||||
void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
|
||||
{
|
||||
assert(config && srcClock_Hz);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -354,6 +483,9 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
/* Set baud rate */
|
||||
SPI_MasterSetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableMaster)
|
||||
{
|
||||
|
@ -361,12 +493,28 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI slave configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_SlaveInit().
|
||||
* Modify some fields of the structure before calling SPI_SlaveInit().
|
||||
* Example:
|
||||
code
|
||||
spi_slave_config_t config;
|
||||
SPI_SlaveGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to slave configuration structure
|
||||
*/
|
||||
void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
||||
{
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->enableStopInWaitMode = false;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -377,14 +525,37 @@ void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
|||
config->txWatermark = kSPI_TxFifoOneHalfEmpty;
|
||||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with slave configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch or be set with
|
||||
* default values by SPI_SlaveGetDefaultConfig().
|
||||
* After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_slave_config_t config = {
|
||||
.polarity = kSPIClockPolarity_ActiveHigh;
|
||||
.phase = kSPIClockPhase_FirstEdge;
|
||||
.direction = kSPIMsbFirst;
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
*/
|
||||
void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -395,9 +566,11 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
|
||||
/* Configure data mode if needed */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode) |
|
||||
SPI_C2_BIDIROE(config->pinMode >> 1U) | SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#else
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_BIDIROE(config->pinMode >> 1U) |
|
||||
SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
|
||||
/* Set watermark */
|
||||
|
@ -409,6 +582,9 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableSlave)
|
||||
{
|
||||
|
@ -416,15 +592,31 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief De-initializes the SPI.
|
||||
*
|
||||
* Calling this API resets the SPI module, gates the SPI clock.
|
||||
* The SPI module can't work unless calling the SPI_MasterInit/SPI_SlaveInit to initialize module.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
*/
|
||||
void SPI_Deinit(SPI_Type *base)
|
||||
{
|
||||
/* Disable SPI module before shutting down */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Gate the clock */
|
||||
CLOCK_DisableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the status flag.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return SPI Status, use status flag to AND #_spi_flags could get the related status.
|
||||
*/
|
||||
uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
@ -441,6 +633,17 @@ uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Enables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -480,6 +683,17 @@ void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Disables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -518,6 +732,13 @@ void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param baudRate_Bps baud rate needed in Hz.
|
||||
* param srcClock_Hz SPI source clock frequency in Hz.
|
||||
*/
|
||||
void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
|
||||
{
|
||||
uint32_t prescaler;
|
||||
|
@ -535,7 +756,7 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
|
||||
/* Set the maximum divisor bit settings for each of the following divisors */
|
||||
bestPrescaler = 7U;
|
||||
bestDivisor = 8U;
|
||||
bestDivisor = 8U;
|
||||
|
||||
/* In all for loops, if min_diff = 0, the exit for loop*/
|
||||
for (prescaler = 0; (prescaler <= 7) && min_diff; prescaler++)
|
||||
|
@ -556,9 +777,9 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
if (min_diff > diff)
|
||||
{
|
||||
/* A better match found */
|
||||
min_diff = diff;
|
||||
min_diff = diff;
|
||||
bestPrescaler = prescaler;
|
||||
bestDivisor = rateDivisor;
|
||||
bestDivisor = rateDivisor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,9 +792,18 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
base->BR = SPI_BR_SPR(bestDivisor) | SPI_BR_SPPR(bestPrescaler);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sends a buffer of data bytes using a blocking method.
|
||||
*
|
||||
* note This function blocks via polling until all bytes have been sent.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param buffer The data bytes to send
|
||||
* param size The number of data bytes to send
|
||||
*/
|
||||
void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -596,6 +826,12 @@ void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*!
|
||||
* brief Enables or disables the FIFO if there is a FIFO.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param enable True means enable FIFO, false means disable FIFO.
|
||||
*/
|
||||
void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
||||
{
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0U)
|
||||
|
@ -612,6 +848,12 @@ void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/*!
|
||||
* brief Writes a data into the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param data needs to be write.
|
||||
*/
|
||||
void SPI_WriteData(SPI_Type *base, uint16_t data)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -622,6 +864,12 @@ void SPI_WriteData(SPI_Type *base, uint16_t data)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets a data from the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return Data in the register.
|
||||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base)
|
||||
{
|
||||
uint16_t val = 0;
|
||||
|
@ -634,6 +882,14 @@ uint16_t SPI_ReadData(SPI_Type *base)
|
|||
return val;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Transfers a block of data using a polling method.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
*/
|
||||
status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(xfer);
|
||||
|
@ -651,10 +907,6 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
|
||||
#endif
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
/* Disable FIFO, as the FIFO may cause data loss if the data size is not integer
|
||||
|
@ -696,6 +948,17 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI master handle.
|
||||
*
|
||||
* This function initializes the SPI master handle which can be used for other SPI master transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
||||
spi_master_handle_t *handle,
|
||||
spi_master_callback_t callback,
|
||||
|
@ -705,35 +968,15 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
|
||||
uint8_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Initialize the handle */
|
||||
s_spiHandle[instance] = handle;
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiIsr = SPI_MasterTransferHandleIRQ;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t txSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
txSize = (base->C3 & SPI_C3_TNEAREF_MARK_MASK) >> SPI_C3_TNEAREF_MARK_SHIFT;
|
||||
if (txSize == 0U)
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
#else
|
||||
handle->watermark = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiMasterIsr = SPI_MasterTransferHandleIRQ;
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* Get the bytes per frame */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -746,6 +989,20 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
EnableIRQ(s_spiIRQ[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Performs a non-blocking SPI interrupt transfer.
|
||||
*
|
||||
* note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -763,47 +1020,76 @@ status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *hand
|
|||
}
|
||||
|
||||
/* Set the handle information */
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txRemainingBytes = xfer->dataSize;
|
||||
handle->rxRemainingBytes = xfer->dataSize;
|
||||
|
||||
/* Set the SPI state to busy */
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register*/
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
/* Enable Interrupt, only enable Rx interrupt, use rx interrupt to driver SPI transfer */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* If the size of the transfer size less than watermark, set watermark to 1 */
|
||||
if (xfer->dataSize < handle->watermark * 2U)
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
|
||||
/* According to watermark size, enable interrupts */
|
||||
if (handle->watermark > 1U)
|
||||
{
|
||||
SPI_EnableFIFO(base, true);
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
while ((base->S & SPI_S_TNEAREF_MASK) != SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
}
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
/* Enable Rx near full interrupt */
|
||||
SPI_EnableInterrupts(base, kSPI_RxFifoNearFullInterruptEnable);
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_EnableFIFO(base, false);
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
}
|
||||
#else
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
#endif
|
||||
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendTransfer(base, handle);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the bytes of the SPI interrupt transferred.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
* param count Transferred bytes of SPI master.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
status_t status = kStatus_Success;
|
||||
|
||||
if (handle->state != kStatus_SPI_Busy)
|
||||
if (handle->state != kSPI_Busy)
|
||||
{
|
||||
status = kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
@ -823,6 +1109,12 @@ status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Aborts an SPI transfer using interrupt.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
*/
|
||||
void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -849,6 +1141,12 @@ void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
|||
handle->txRemainingBytes = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts the handler for the SPI.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -878,6 +1176,17 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI slave handle.
|
||||
*
|
||||
* This function initializes the SPI slave handle which can be used for other SPI slave transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
|
@ -888,9 +1197,15 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
/* Slave create handle share same logic with master create handle, the only difference
|
||||
is the Isr pointer. */
|
||||
SPI_MasterTransferCreateHandle(base, handle, callback, userData);
|
||||
s_spiIsr = SPI_SlaveTransferHandleIRQ;
|
||||
s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts a handler for the SPI slave.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_slave_handle_t structure which stores the transfer state
|
||||
*/
|
||||
void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -920,11 +1235,28 @@ void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance)
|
||||
{
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
s_spiMasterIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_spiSlaveIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
||||
exception return operation might vector to incorrect interrupt */
|
||||
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
||||
__DSB();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SPI0)
|
||||
void SPI0_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[0]);
|
||||
s_spiIsr(SPI0, s_spiHandle[0]);
|
||||
SPI_CommonIRQHandler(SPI0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -932,7 +1264,7 @@ void SPI0_DriverIRQHandler(void)
|
|||
void SPI1_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[1]);
|
||||
s_spiIsr(SPI1, s_spiHandle[1]);
|
||||
SPI_CommonIRQHandler(SPI1, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -940,6 +1272,6 @@ void SPI1_DriverIRQHandler(void)
|
|||
void SPI2_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[2]);
|
||||
s_spiIsr(SPI0, s_spiHandle[2]);
|
||||
SPI_CommonIRQHandler(SPI2, 2);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used tom endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_H_
|
||||
#define _FSL_SPI_H_
|
||||
|
@ -37,15 +15,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI driver version 2.0.1. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief SPI driver version 2.0.4. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
#ifndef SPI_DUMMYDATA
|
||||
|
@ -53,12 +30,15 @@
|
|||
#define SPI_DUMMYDATA (0xFFU)
|
||||
#endif
|
||||
|
||||
/*! @brief Global variable for dummy data value setting. */
|
||||
extern volatile uint8_t g_spiDummyData[];
|
||||
|
||||
/*! @brief Return status for the SPI driver.*/
|
||||
enum _spi_status
|
||||
{
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
};
|
||||
|
||||
/*! @brief SPI clock polarity configuration.*/
|
||||
|
@ -87,16 +67,16 @@ typedef enum _spi_shift_direction
|
|||
/*! @brief SPI slave select output mode options.*/
|
||||
typedef enum _spi_ss_output_mode
|
||||
{
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
} spi_ss_output_mode_t;
|
||||
|
||||
/*! @brief SPI pin mode options.*/
|
||||
typedef enum _spi_pin_mode
|
||||
{
|
||||
kSPI_PinModeNormal = 0x0U, /*!< Pins operate in normal, single-direction mode.*/
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
* Slave: MISO pin is input. */
|
||||
kSPI_PinModeOutput = 0x3U /*!< Bidirectional mode. Master: MOSI pin is output;
|
||||
* Slave: MISO pin is output. */
|
||||
|
@ -113,10 +93,10 @@ typedef enum _spi_data_bitcount_mode
|
|||
enum _spi_interrupt_enable
|
||||
{
|
||||
kSPI_RxFullAndModfInterruptEnable = 0x1U, /*!< Receive buffer full (SPRF) and mode fault (MODF) interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxFifoNearEmptyInterruptEnable = 0x10U, /*!< Transmit FIFO nearly empty interrupt */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
@ -124,44 +104,44 @@ enum _spi_interrupt_enable
|
|||
/*! @brief SPI status flags.*/
|
||||
enum _spi_flags
|
||||
{
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_TxBufferEmptyFlag = SPI_S_SPTEF_MASK, /*!< Transmit buffer empty flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*! @brief SPI FIFO write-1-to-clear interrupt flags.*/
|
||||
typedef enum _spi_w1c_interrupt
|
||||
{
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
} spi_w1c_interrupt_t;
|
||||
|
||||
/*! @brief SPI TX FIFO watermark settings.*/
|
||||
typedef enum _spi_txfifo_watermark
|
||||
{
|
||||
kSPI_TxFifoOneFourthEmpty = 0, /*!< SPI tx watermark at 1/4 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
} spi_txfifo_watermark_t;
|
||||
|
||||
/*! @brief SPI RX FIFO watermark settings.*/
|
||||
typedef enum _spi_rxfifo_watermark
|
||||
{
|
||||
kSPI_RxFifoThreeFourthsFull = 0, /*!< SPI rx watermark at 3/4 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
} spi_rxfifo_watermark_t;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
|
@ -169,8 +149,8 @@ typedef enum _spi_rxfifo_watermark
|
|||
/*! @brief SPI DMA source*/
|
||||
enum _spi_dma_enable_t
|
||||
{
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_DmaAllEnable = (SPI_C2_TXDMAE_MASK | SPI_C2_RXDMAE_MASK) /*!< All DMA request source*/
|
||||
};
|
||||
#endif /* FSL_FEATURE_SPI_HAS_DMA_SUPPORT */
|
||||
|
@ -210,6 +190,7 @@ typedef struct _spi_slave_config
|
|||
spi_txfifo_watermark_t txWatermark; /*!< Tx watermark settings */
|
||||
spi_rxfifo_watermark_t rxWatermark; /*!< Rx watermark settings */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
spi_pin_mode_t pinMode; /*!< SPI pin mode select */
|
||||
} spi_slave_config_t;
|
||||
|
||||
/*! @brief SPI transfer structure */
|
||||
|
@ -478,6 +459,27 @@ static inline uint32_t SPI_GetDataRegisterAddress(SPI_Type *base)
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sets the pin mode for transfer.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param pinMode pin mode for transfer AND #_spi_pin_mode could get the related configuration.
|
||||
*/
|
||||
static inline void SPI_SetPinMode(SPI_Type *base, spi_pin_mode_t pinMode)
|
||||
{
|
||||
/* Clear SPC0 and BIDIROE bit. */
|
||||
base->C2 &= ~(SPI_C2_BIDIROE_MASK | SPI_C2_SPC0_MASK);
|
||||
/* Set pin mode for transfer. */
|
||||
base->C2 |= SPI_C2_BIDIROE(pinMode >> 1U) | SPI_C2_SPC0(pinMode & 1U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
|
@ -544,6 +546,13 @@ void SPI_WriteData(SPI_Type *base, uint16_t data);
|
|||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Set up the dummy data.
|
||||
*
|
||||
* @param base SPI peripheral address.
|
||||
* @param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
|
@ -582,11 +591,7 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer);
|
|||
*
|
||||
* @note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times of the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Users can also call the functional API to
|
||||
* get the last
|
||||
* received data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
@ -636,8 +641,8 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* @param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
|
@ -645,11 +650,7 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
*
|
||||
* @note The API returns immediately after the transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Call the functional API to get the last
|
||||
* several
|
||||
* receive data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi_dma.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi_dma"
|
||||
#endif
|
||||
|
||||
/*<! Structure definition for spi_dma_private_handle_t. The structure is private. */
|
||||
typedef struct _spi_dma_private_handle
|
||||
{
|
||||
|
@ -52,13 +36,6 @@ static spi_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
extern uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief DMA callback function for SPI send transfer.
|
||||
*
|
||||
|
@ -76,25 +53,18 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData);
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
/* Dummy data used to send */
|
||||
static const uint8_t s_dummyData = SPI_DUMMYDATA;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_TxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->txHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -114,13 +84,13 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_RxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->rxHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -137,6 +107,19 @@ static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initialize the SPI master DMA handle.
|
||||
*
|
||||
* This function initializes the SPI master DMA handle which can be used for other SPI master transactional APIs.
|
||||
* Usually, for a specified SPI instance, user need only call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback User callback function called at the end of a transfer.
|
||||
* param userData User data for callback.
|
||||
* param txHandle DMA handle pointer for SPI Tx, the handle shall be static allocated by users.
|
||||
* param rxHandle DMA handle pointer for SPI Rx, the handle shall be static allocated by users.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
||||
spi_dma_handle_t *handle,
|
||||
spi_dma_callback_t callback,
|
||||
|
@ -146,7 +129,10 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
{
|
||||
assert(handle);
|
||||
dma_transfer_config_t config = {0};
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Set spi base to handle */
|
||||
handle->txHandle = txHandle;
|
||||
|
@ -158,7 +144,7 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
handle->state = kSPI_Idle;
|
||||
|
||||
/* Set handle to global state */
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
/* Compute internal state */
|
||||
|
@ -180,27 +166,27 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the non-change attribute for Tx DMA transfer, to improve efficiency */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
config.enableSrcIncrement = true;
|
||||
config.enableSrcIncrement = true;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
/* Set non-change attribute for Rx DMA */
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.enableDestIncrement = true;
|
||||
config.enableSrcIncrement = false;
|
||||
config.enableSrcIncrement = false;
|
||||
DMA_SubmitTransfer(handle->rxHandle, &config, true);
|
||||
|
||||
/* Install callback for Tx dma channel */
|
||||
|
@ -208,6 +194,19 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
DMA_SetCallback(handle->rxHandle, SPI_RxDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Perform a non-blocking SPI transfer using DMA.
|
||||
*
|
||||
* note This interface returned immediately after transfer initiates, users should call
|
||||
* SPI_GetTransferStatus to poll the transfer status to check whether SPI transfer finished.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param xfer Pointer to dma transfer structure.
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -231,16 +230,16 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
SPI_Enable(base, true);
|
||||
|
||||
/* Configure tx transfer DMA */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
config.transferSize = xfer->dataSize;
|
||||
|
@ -248,13 +247,13 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
if (xfer->txData)
|
||||
{
|
||||
config.enableSrcIncrement = true;
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the source increasement and source set to dummyData */
|
||||
config.enableSrcIncrement = false;
|
||||
config.srcAddr = (uint32_t)(&s_dummyData);
|
||||
config.srcAddr = (uint32_t)(&g_spiDummyData[SPI_GetInstance(base)]);
|
||||
}
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
|
@ -270,7 +269,7 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
|
||||
/* Change the state of handle */
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->state = kSPI_Busy;
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Start Rx transfer if needed */
|
||||
if (xfer->rxData)
|
||||
|
@ -288,6 +287,15 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Get the transferred bytes for SPI slave DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param count Transferred bytes.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -313,6 +321,12 @@ status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Abort a SPI transfer using DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
*/
|
||||
void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -327,5 +341,5 @@ void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
|||
/* Set the handle state */
|
||||
handle->txInProgress = false;
|
||||
handle->rxInProgress = false;
|
||||
handle->state = kSPI_Idle;
|
||||
handle->state = kSPI_Idle;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_DMA_H_
|
||||
#define _FSL_SPI_DMA_H_
|
||||
|
@ -38,11 +16,16 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI DMA driver version 2.0.4. */
|
||||
#define FSL_SPI_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
typedef struct _spi_dma_handle spi_dma_handle_t;
|
||||
|
||||
/*! @brief SPI DMA callback called at the end of transfer. */
|
||||
|
@ -55,7 +38,7 @@ struct _spi_dma_handle
|
|||
bool rxInProgress; /*!< Receive transfer finished */
|
||||
dma_handle_t *txHandle; /*!< DMA handler for SPI send */
|
||||
dma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI tranfer */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI transfer */
|
||||
spi_dma_callback_t callback; /*!< Callback for SPI DMA transfer */
|
||||
void *userData; /*!< User Data for SPI DMA callback */
|
||||
uint32_t state; /*!< Internal state of SPI DMA transfer */
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi"
|
||||
#endif
|
||||
|
||||
/*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
|
||||
enum _spi_transfer_states_t
|
||||
{
|
||||
|
@ -46,12 +30,6 @@ typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle);
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sends a buffer of data bytes in non-blocking way.
|
||||
|
@ -71,6 +49,14 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
*/
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
||||
|
||||
/*!
|
||||
* @brief Get the waterrmark value for this SPI instance.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @return Watermark value for the SPI instance.
|
||||
*/
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Send a piece of data for SPI.
|
||||
*
|
||||
|
@ -78,6 +64,7 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
|
|||
* and write the data into it. At the same time, this function updates the values in
|
||||
* master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
@ -89,9 +76,18 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* and write the data to destination address. At the same time, this function updates
|
||||
* the values in master handle structure.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param handle Pointer to SPI master handle structure.
|
||||
*/
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle);
|
||||
|
||||
/*!
|
||||
* @brief Common IRQ handler for SPI.
|
||||
*
|
||||
* @param base SPI base pointer.
|
||||
* @param instance SPI instance number.
|
||||
*/
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance);
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
|
@ -101,21 +97,31 @@ static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
static SPI_Type *const s_spiBases[] = SPI_BASE_PTRS;
|
||||
/*! @brief IRQ name array */
|
||||
static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/*! @brief Clock array name */
|
||||
static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS;
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||
static spi_isr_t s_spiIsr;
|
||||
static spi_isr_t s_spiMasterIsr;
|
||||
static spi_isr_t s_spiSlaveIsr;
|
||||
|
||||
/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
|
||||
volatile uint8_t g_spiDummyData[ARRAY_SIZE(s_spiBases)] = {0};
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* brief Get the instance for SPI module.
|
||||
*
|
||||
* param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base)
|
||||
{
|
||||
uint32_t instance;
|
||||
|
||||
/* Find the instance index from base address mappings. */
|
||||
for (instance = 0; instance < FSL_FEATURE_SOC_SPI_COUNT; instance++)
|
||||
for (instance = 0; instance < ARRAY_SIZE(s_spiBases); instance++)
|
||||
{
|
||||
if (s_spiBases[instance] == base)
|
||||
{
|
||||
|
@ -123,15 +129,28 @@ uint32_t SPI_GetInstance(SPI_Type *base)
|
|||
}
|
||||
}
|
||||
|
||||
assert(instance < FSL_FEATURE_SOC_SPI_COUNT);
|
||||
assert(instance < ARRAY_SIZE(s_spiBases));
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Set up the dummy data.
|
||||
*
|
||||
* param base SPI peripheral address.
|
||||
* param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData)
|
||||
{
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
g_spiDummyData[instance] = dummyData;
|
||||
}
|
||||
|
||||
static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
/* Check if 16 bits or 8 bits */
|
||||
|
@ -155,13 +174,13 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
base->DL = *buffer++;
|
||||
}
|
||||
#else
|
||||
base->D = *buffer++;
|
||||
base->D = *buffer++;
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
}
|
||||
/* Send dummy data */
|
||||
else
|
||||
{
|
||||
SPI_WriteData(base, SPI_DUMMYDATA);
|
||||
SPI_WriteData(base, ((uint32_t)g_spiDummyData[instance] << 8 | g_spiDummyData[instance]));
|
||||
}
|
||||
i += bytesPerFrame;
|
||||
}
|
||||
|
@ -169,7 +188,7 @@ static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
|
||||
static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -205,18 +224,68 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
/* Get the watermark value of transfer. Please note that the entery width of FIFO is 16 bits. */
|
||||
static uint8_t SPI_GetWatermark(SPI_Type *base)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t rxSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
rxSize = (base->C3 & SPI_C3_RNFULLF_MARK_MASK) >> SPI_C3_RNFULLF_MARK_SHIFT;
|
||||
if (rxSize == 0U)
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
ret = 1U;
|
||||
}
|
||||
#else
|
||||
ret = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SPI_SendInitialTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytestoTransfer = handle->bytePerFrame;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
if (handle->watermark > 1)
|
||||
{
|
||||
/* In the first time to send data to FIFO, if transfer size is not larger than
|
||||
* the FIFO size, send all data to FIFO, or send data to make the FIFO full.
|
||||
* Besides, The FIFO's entry width is 16 bits, need to translate it to bytes.
|
||||
*/
|
||||
bytestoTransfer = MIN(handle->txRemainingBytes, (FSL_FEATURE_SPI_FIFO_SIZEn(base) * 2));
|
||||
}
|
||||
#endif
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
|
||||
static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->txRemainingBytes);
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPTEF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
if (bytes != 0U)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
}
|
||||
|
||||
/* Send data */
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
|
@ -235,7 +304,7 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
else
|
||||
{
|
||||
/* As a slave, send data until SPTEF cleared */
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes > 0))
|
||||
while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes >= bytes))
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
|
||||
|
@ -253,56 +322,96 @@ static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
|||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
if (base->S & SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytes);
|
||||
/* The FIFO's entry width is 16 bits, need to translate it to bytes. */
|
||||
uint8_t bytestoTransfer = handle->watermark * 2;
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytes;
|
||||
}
|
||||
handle->txRemainingBytes -= bytes;
|
||||
if (handle->txRemainingBytes < 8U)
|
||||
{
|
||||
bytestoTransfer = handle->txRemainingBytes;
|
||||
}
|
||||
|
||||
SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
|
||||
|
||||
/* Update handle information */
|
||||
if (handle->txData)
|
||||
{
|
||||
handle->txData += bytestoTransfer;
|
||||
}
|
||||
handle->txRemainingBytes -= bytestoTransfer;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
uint8_t bytes = MIN((handle->watermark * 2U), handle->rxRemainingBytes);
|
||||
uint8_t val = 1U;
|
||||
uint8_t bytes = handle->bytePerFrame;
|
||||
|
||||
/* Read S register and ensure SPRF is 1, otherwise the write would be ignored. */
|
||||
if (handle->watermark == 1U)
|
||||
{
|
||||
val = base->S & SPI_S_SPRF_MASK;
|
||||
if (bytes != 0U)
|
||||
if (base->S & SPI_S_SPRF_MASK)
|
||||
{
|
||||
bytes = handle->bytePerFrame;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (val)
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
|
||||
/* If use FIFO */
|
||||
else
|
||||
{
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
/* While rx fifo not empty and remaining data can also trigger the last interrupt */
|
||||
while ((base->S & SPI_S_RFIFOEF_MASK) == 0U)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
SPI_ReadNonBlocking(base, handle->rxData, bytes);
|
||||
|
||||
/* Update information in handle */
|
||||
if (handle->rxData)
|
||||
{
|
||||
handle->rxData += bytes;
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
|
||||
/* If the reamining data equals to watermark, leave to last interrupt */
|
||||
if (handle->rxRemainingBytes == (handle->watermark * 2U))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
handle->rxRemainingBytes -= bytes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI master configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_MasterInit().
|
||||
* User may use the initialized structure unchanged in SPI_MasterInit(), or modify
|
||||
* some fields of the structure before calling SPI_MasterInit(). After calling this API,
|
||||
* the master is ready to transfer.
|
||||
* Example:
|
||||
code
|
||||
spi_master_config_t config;
|
||||
SPI_MasterGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to master config structure
|
||||
*/
|
||||
void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
||||
{
|
||||
config->enableMaster = true;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableMaster = true;
|
||||
config->enableStopInWaitMode = false;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
config->dataMode = kSPI_8BitMode;
|
||||
|
@ -313,17 +422,37 @@ void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
|
|||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
config->outputMode = kSPI_SlaveSelectAutomaticOutput;
|
||||
config->baudRate_Bps = 500000U;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with master configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch, or be set with default
|
||||
* values by SPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_master_config_t config = {
|
||||
.baudRate_Bps = 400000,
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
* param srcClock_Hz Source clock frequency.
|
||||
*/
|
||||
void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
|
||||
{
|
||||
assert(config && srcClock_Hz);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -354,6 +483,9 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
/* Set baud rate */
|
||||
SPI_MasterSetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableMaster)
|
||||
{
|
||||
|
@ -361,12 +493,28 @@ void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the SPI slave configuration structure to default values.
|
||||
*
|
||||
* The purpose of this API is to get the configuration structure initialized for use in SPI_SlaveInit().
|
||||
* Modify some fields of the structure before calling SPI_SlaveInit().
|
||||
* Example:
|
||||
code
|
||||
spi_slave_config_t config;
|
||||
SPI_SlaveGetDefaultConfig(&config);
|
||||
endcode
|
||||
*
|
||||
* param config pointer to slave configuration structure
|
||||
*/
|
||||
void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
||||
{
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
/* Initializes the configure structure to zero. */
|
||||
memset(config, 0, sizeof(*config));
|
||||
|
||||
config->enableSlave = true;
|
||||
config->polarity = kSPI_ClockPolarityActiveHigh;
|
||||
config->phase = kSPI_ClockPhaseFirstEdge;
|
||||
config->direction = kSPI_MsbFirst;
|
||||
config->enableStopInWaitMode = false;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -377,14 +525,37 @@ void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
|
|||
config->txWatermark = kSPI_TxFifoOneHalfEmpty;
|
||||
config->rxWatermark = kSPI_RxFifoOneHalfFull;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
config->pinMode = kSPI_PinModeNormal;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI with slave configuration.
|
||||
*
|
||||
* The configuration structure can be filled by user from scratch or be set with
|
||||
* default values by SPI_SlaveGetDefaultConfig().
|
||||
* After calling this API, the slave is ready to transfer.
|
||||
* Example
|
||||
code
|
||||
spi_slave_config_t config = {
|
||||
.polarity = kSPIClockPolarity_ActiveHigh;
|
||||
.phase = kSPIClockPhase_FirstEdge;
|
||||
.direction = kSPIMsbFirst;
|
||||
...
|
||||
};
|
||||
SPI_MasterInit(SPI0, &config);
|
||||
endcode
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param config pointer to master configuration structure
|
||||
*/
|
||||
void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
||||
{
|
||||
assert(config);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Open clock gate for SPI and open interrupt */
|
||||
CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
|
||||
/* Disable SPI before configuration */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
@ -395,9 +566,11 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
|
||||
/* Configure data mode if needed */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode) |
|
||||
SPI_C2_BIDIROE(config->pinMode >> 1U) | SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#else
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode);
|
||||
base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_BIDIROE(config->pinMode >> 1U) |
|
||||
SPI_C2_SPC0(config->pinMode & 1U);
|
||||
#endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
|
||||
|
||||
/* Set watermark */
|
||||
|
@ -409,6 +582,9 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the dummy data, this data will usefull when tx buffer is NULL. */
|
||||
SPI_SetDummyData(base, SPI_DUMMYDATA);
|
||||
|
||||
/* Enable SPI */
|
||||
if (config->enableSlave)
|
||||
{
|
||||
|
@ -416,15 +592,31 @@ void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief De-initializes the SPI.
|
||||
*
|
||||
* Calling this API resets the SPI module, gates the SPI clock.
|
||||
* The SPI module can't work unless calling the SPI_MasterInit/SPI_SlaveInit to initialize module.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
*/
|
||||
void SPI_Deinit(SPI_Type *base)
|
||||
{
|
||||
/* Disable SPI module before shutting down */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Gate the clock */
|
||||
CLOCK_DisableClock(s_spiClock[SPI_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the status flag.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return SPI Status, use status flag to AND #_spi_flags could get the related status.
|
||||
*/
|
||||
uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
@ -441,6 +633,17 @@ uint32_t SPI_GetStatusFlags(SPI_Type *base)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Enables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -480,6 +683,17 @@ void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Disables the interrupt for the SPI.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param mask SPI interrupt source. The parameter can be any combination of the following values:
|
||||
* arg kSPI_RxFullAndModfInterruptEnable
|
||||
* arg kSPI_TxEmptyInterruptEnable
|
||||
* arg kSPI_MatchInterruptEnable
|
||||
* arg kSPI_RxFifoNearFullInterruptEnable
|
||||
* arg kSPI_TxFifoNearEmptyInterruptEnable
|
||||
*/
|
||||
void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
||||
{
|
||||
/* Rx full interrupt */
|
||||
|
@ -518,6 +732,13 @@ void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param baudRate_Bps baud rate needed in Hz.
|
||||
* param srcClock_Hz SPI source clock frequency in Hz.
|
||||
*/
|
||||
void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
|
||||
{
|
||||
uint32_t prescaler;
|
||||
|
@ -535,7 +756,7 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
|
||||
/* Set the maximum divisor bit settings for each of the following divisors */
|
||||
bestPrescaler = 7U;
|
||||
bestDivisor = 8U;
|
||||
bestDivisor = 8U;
|
||||
|
||||
/* In all for loops, if min_diff = 0, the exit for loop*/
|
||||
for (prescaler = 0; (prescaler <= 7) && min_diff; prescaler++)
|
||||
|
@ -556,9 +777,9 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
if (min_diff > diff)
|
||||
{
|
||||
/* A better match found */
|
||||
min_diff = diff;
|
||||
min_diff = diff;
|
||||
bestPrescaler = prescaler;
|
||||
bestDivisor = rateDivisor;
|
||||
bestDivisor = rateDivisor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,9 +792,18 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl
|
|||
base->BR = SPI_BR_SPR(bestDivisor) | SPI_BR_SPPR(bestPrescaler);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Sends a buffer of data bytes using a blocking method.
|
||||
*
|
||||
* note This function blocks via polling until all bytes have been sent.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param buffer The data bytes to send
|
||||
* param size The number of data bytes to send
|
||||
*/
|
||||
void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t i = 0;
|
||||
uint8_t bytesPerFrame = 1U;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
|
||||
|
@ -596,6 +826,12 @@ void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
|
|||
}
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*!
|
||||
* brief Enables or disables the FIFO if there is a FIFO.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param enable True means enable FIFO, false means disable FIFO.
|
||||
*/
|
||||
void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
||||
{
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0U)
|
||||
|
@ -612,6 +848,12 @@ void SPI_EnableFIFO(SPI_Type *base, bool enable)
|
|||
}
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/*!
|
||||
* brief Writes a data into the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param data needs to be write.
|
||||
*/
|
||||
void SPI_WriteData(SPI_Type *base, uint16_t data)
|
||||
{
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -622,6 +864,12 @@ void SPI_WriteData(SPI_Type *base, uint16_t data)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets a data from the SPI data register.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* return Data in the register.
|
||||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base)
|
||||
{
|
||||
uint16_t val = 0;
|
||||
|
@ -634,6 +882,14 @@ uint16_t SPI_ReadData(SPI_Type *base)
|
|||
return val;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Transfers a block of data using a polling method.
|
||||
*
|
||||
* param base SPI base pointer
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
*/
|
||||
status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(xfer);
|
||||
|
@ -651,10 +907,6 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
|
||||
#endif
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register */
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
/* Disable FIFO, as the FIFO may cause data loss if the data size is not integer
|
||||
|
@ -696,6 +948,17 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI master handle.
|
||||
*
|
||||
* This function initializes the SPI master handle which can be used for other SPI master transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
||||
spi_master_handle_t *handle,
|
||||
spi_master_callback_t callback,
|
||||
|
@ -705,35 +968,15 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
|
||||
uint8_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Initialize the handle */
|
||||
s_spiHandle[instance] = handle;
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiIsr = SPI_MasterTransferHandleIRQ;
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
uint8_t txSize = 0U;
|
||||
/* Get the number to be sent if there is FIFO */
|
||||
if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
|
||||
{
|
||||
txSize = (base->C3 & SPI_C3_TNEAREF_MARK_MASK) >> SPI_C3_TNEAREF_MARK_SHIFT;
|
||||
if (txSize == 0U)
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->watermark = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
|
||||
}
|
||||
}
|
||||
/* If no FIFO, just set the watermark to 1 */
|
||||
else
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
#else
|
||||
handle->watermark = 1U;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
handle->callback = callback;
|
||||
handle->userData = userData;
|
||||
s_spiMasterIsr = SPI_MasterTransferHandleIRQ;
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* Get the bytes per frame */
|
||||
#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
|
||||
|
@ -746,6 +989,20 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base,
|
|||
EnableIRQ(s_spiIRQ[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Performs a non-blocking SPI interrupt transfer.
|
||||
*
|
||||
* note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
* param xfer pointer to spi_xfer_config_t structure
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -763,47 +1020,76 @@ status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *hand
|
|||
}
|
||||
|
||||
/* Set the handle information */
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txData = xfer->txData;
|
||||
handle->rxData = xfer->rxData;
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->txRemainingBytes = xfer->dataSize;
|
||||
handle->rxRemainingBytes = xfer->dataSize;
|
||||
|
||||
/* Set the SPI state to busy */
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Disable SPI and then enable it, this is used to clear S register*/
|
||||
base->C1 &= ~SPI_C1_SPE_MASK;
|
||||
base->C1 |= SPI_C1_SPE_MASK;
|
||||
|
||||
/* Enable Interrupt, only enable Rx interrupt, use rx interrupt to driver SPI transfer */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
|
||||
handle->watermark = SPI_GetWatermark(base);
|
||||
|
||||
/* If the size of the transfer size less than watermark, set watermark to 1 */
|
||||
if (xfer->dataSize < handle->watermark * 2U)
|
||||
{
|
||||
handle->watermark = 1U;
|
||||
}
|
||||
|
||||
/* According to watermark size, enable interrupts */
|
||||
if (handle->watermark > 1U)
|
||||
{
|
||||
SPI_EnableFIFO(base, true);
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
while ((base->S & SPI_S_TNEAREF_MASK) != SPI_S_TNEAREF_MASK)
|
||||
{
|
||||
}
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
/* Enable Rx near full interrupt */
|
||||
SPI_EnableInterrupts(base, kSPI_RxFifoNearFullInterruptEnable);
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_EnableFIFO(base, false);
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
}
|
||||
#else
|
||||
while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
|
||||
{
|
||||
}
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendInitialTransfer(base, handle);
|
||||
SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
|
||||
#endif
|
||||
|
||||
/* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
|
||||
SPI_SendTransfer(base, handle);
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Gets the bytes of the SPI interrupt transferred.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
* param count Transferred bytes of SPI master.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
status_t status = kStatus_Success;
|
||||
|
||||
if (handle->state != kStatus_SPI_Busy)
|
||||
if (handle->state != kSPI_Busy)
|
||||
{
|
||||
status = kStatus_NoTransferInProgress;
|
||||
}
|
||||
|
@ -823,6 +1109,12 @@ status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Aborts an SPI transfer using interrupt.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle Pointer to SPI transfer handle, this should be a static variable.
|
||||
*/
|
||||
void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -849,6 +1141,12 @@ void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
|
|||
handle->txRemainingBytes = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts the handler for the SPI.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_master_handle_t structure which stores the transfer state.
|
||||
*/
|
||||
void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -878,6 +1176,17 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initializes the SPI slave handle.
|
||||
*
|
||||
* This function initializes the SPI slave handle which can be used for other SPI slave transactional APIs. Usually,
|
||||
* for a specified SPI instance, call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback Callback function.
|
||||
* param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
|
@ -888,9 +1197,15 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
/* Slave create handle share same logic with master create handle, the only difference
|
||||
is the Isr pointer. */
|
||||
SPI_MasterTransferCreateHandle(base, handle, callback, userData);
|
||||
s_spiIsr = SPI_SlaveTransferHandleIRQ;
|
||||
s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Interrupts a handler for the SPI slave.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle pointer to spi_slave_handle_t structure which stores the transfer state
|
||||
*/
|
||||
void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -920,11 +1235,28 @@ void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
|
|||
}
|
||||
}
|
||||
|
||||
static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance)
|
||||
{
|
||||
if (base->C1 & SPI_C1_MSTR_MASK)
|
||||
{
|
||||
s_spiMasterIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_spiSlaveIsr(base, s_spiHandle[instance]);
|
||||
}
|
||||
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
||||
exception return operation might vector to incorrect interrupt */
|
||||
#if defined __CORTEX_M && (__CORTEX_M == 4U)
|
||||
__DSB();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SPI0)
|
||||
void SPI0_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[0]);
|
||||
s_spiIsr(SPI0, s_spiHandle[0]);
|
||||
SPI_CommonIRQHandler(SPI0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -932,7 +1264,7 @@ void SPI0_DriverIRQHandler(void)
|
|||
void SPI1_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[1]);
|
||||
s_spiIsr(SPI1, s_spiHandle[1]);
|
||||
SPI_CommonIRQHandler(SPI1, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -940,6 +1272,6 @@ void SPI1_DriverIRQHandler(void)
|
|||
void SPI2_DriverIRQHandler(void)
|
||||
{
|
||||
assert(s_spiHandle[2]);
|
||||
s_spiIsr(SPI0, s_spiHandle[2]);
|
||||
SPI_CommonIRQHandler(SPI2, 2);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used tom endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_H_
|
||||
#define _FSL_SPI_H_
|
||||
|
@ -37,15 +15,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI driver version 2.0.1. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief SPI driver version 2.0.4. */
|
||||
#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
#ifndef SPI_DUMMYDATA
|
||||
|
@ -53,12 +30,15 @@
|
|||
#define SPI_DUMMYDATA (0xFFU)
|
||||
#endif
|
||||
|
||||
/*! @brief Global variable for dummy data value setting. */
|
||||
extern volatile uint8_t g_spiDummyData[];
|
||||
|
||||
/*! @brief Return status for the SPI driver.*/
|
||||
enum _spi_status
|
||||
{
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
kStatus_SPI_Busy = MAKE_STATUS(kStatusGroup_SPI, 0), /*!< SPI bus is busy */
|
||||
kStatus_SPI_Idle = MAKE_STATUS(kStatusGroup_SPI, 1), /*!< SPI is idle */
|
||||
kStatus_SPI_Error = MAKE_STATUS(kStatusGroup_SPI, 2) /*!< SPI error */
|
||||
};
|
||||
|
||||
/*! @brief SPI clock polarity configuration.*/
|
||||
|
@ -87,16 +67,16 @@ typedef enum _spi_shift_direction
|
|||
/*! @brief SPI slave select output mode options.*/
|
||||
typedef enum _spi_ss_output_mode
|
||||
{
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
kSPI_SlaveSelectAsGpio = 0x0U, /*!< Slave select pin configured as GPIO. */
|
||||
kSPI_SlaveSelectFaultInput = 0x2U, /*!< Slave select pin configured for fault detection. */
|
||||
kSPI_SlaveSelectAutomaticOutput = 0x3U /*!< Slave select pin configured for automatic SPI output. */
|
||||
} spi_ss_output_mode_t;
|
||||
|
||||
/*! @brief SPI pin mode options.*/
|
||||
typedef enum _spi_pin_mode
|
||||
{
|
||||
kSPI_PinModeNormal = 0x0U, /*!< Pins operate in normal, single-direction mode.*/
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
kSPI_PinModeInput = 0x1U, /*!< Bidirectional mode. Master: MOSI pin is input;
|
||||
* Slave: MISO pin is input. */
|
||||
kSPI_PinModeOutput = 0x3U /*!< Bidirectional mode. Master: MOSI pin is output;
|
||||
* Slave: MISO pin is output. */
|
||||
|
@ -113,10 +93,10 @@ typedef enum _spi_data_bitcount_mode
|
|||
enum _spi_interrupt_enable
|
||||
{
|
||||
kSPI_RxFullAndModfInterruptEnable = 0x1U, /*!< Receive buffer full (SPRF) and mode fault (MODF) interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
kSPI_TxEmptyInterruptEnable = 0x2U, /*!< Transmit buffer empty interrupt */
|
||||
kSPI_MatchInterruptEnable = 0x4U, /*!< Match interrupt */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_RxFifoNearFullInterruptEnable = 0x8U, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxFifoNearEmptyInterruptEnable = 0x10U, /*!< Transmit FIFO nearly empty interrupt */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
@ -124,44 +104,44 @@ enum _spi_interrupt_enable
|
|||
/*! @brief SPI status flags.*/
|
||||
enum _spi_flags
|
||||
{
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_RxBufferFullFlag = SPI_S_SPRF_MASK, /*!< Read buffer full flag */
|
||||
kSPI_MatchFlag = SPI_S_SPMF_MASK, /*!< Match flag */
|
||||
kSPI_TxBufferEmptyFlag = SPI_S_SPTEF_MASK, /*!< Transmit buffer empty flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
kSPI_ModeFaultFlag = SPI_S_MODF_MASK, /*!< Mode fault flag */
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */
|
||||
kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */
|
||||
kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */
|
||||
kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */
|
||||
kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */
|
||||
kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */
|
||||
kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */
|
||||
kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
};
|
||||
|
||||
#if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
|
||||
/*! @brief SPI FIFO write-1-to-clear interrupt flags.*/
|
||||
typedef enum _spi_w1c_interrupt
|
||||
{
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
kSPI_RxFifoFullClearInterrupt = SPI_CI_SPRFCI_MASK, /*!< Receive FIFO full interrupt */
|
||||
kSPI_TxFifoEmptyClearInterrupt = SPI_CI_SPTEFCI_MASK, /*!< Transmit FIFO empty interrupt */
|
||||
kSPI_RxNearFullClearInterrupt = SPI_CI_RNFULLFCI_MASK, /*!< Receive FIFO nearly full interrupt */
|
||||
kSPI_TxNearEmptyClearInterrupt = SPI_CI_TNEAREFCI_MASK /*!< Transmit FIFO nearly empty interrupt */
|
||||
} spi_w1c_interrupt_t;
|
||||
|
||||
/*! @brief SPI TX FIFO watermark settings.*/
|
||||
typedef enum _spi_txfifo_watermark
|
||||
{
|
||||
kSPI_TxFifoOneFourthEmpty = 0, /*!< SPI tx watermark at 1/4 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
kSPI_TxFifoOneHalfEmpty = 1 /*!< SPI tx watermark at 1/2 FIFO size */
|
||||
} spi_txfifo_watermark_t;
|
||||
|
||||
/*! @brief SPI RX FIFO watermark settings.*/
|
||||
typedef enum _spi_rxfifo_watermark
|
||||
{
|
||||
kSPI_RxFifoThreeFourthsFull = 0, /*!< SPI rx watermark at 3/4 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
kSPI_RxFifoOneHalfFull = 1 /*!< SPI rx watermark at 1/2 FIFO size */
|
||||
} spi_rxfifo_watermark_t;
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
|
@ -169,8 +149,8 @@ typedef enum _spi_rxfifo_watermark
|
|||
/*! @brief SPI DMA source*/
|
||||
enum _spi_dma_enable_t
|
||||
{
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_TxDmaEnable = SPI_C2_TXDMAE_MASK, /*!< Tx DMA request source */
|
||||
kSPI_RxDmaEnable = SPI_C2_RXDMAE_MASK, /*!< Rx DMA request source */
|
||||
kSPI_DmaAllEnable = (SPI_C2_TXDMAE_MASK | SPI_C2_RXDMAE_MASK) /*!< All DMA request source*/
|
||||
};
|
||||
#endif /* FSL_FEATURE_SPI_HAS_DMA_SUPPORT */
|
||||
|
@ -210,6 +190,7 @@ typedef struct _spi_slave_config
|
|||
spi_txfifo_watermark_t txWatermark; /*!< Tx watermark settings */
|
||||
spi_rxfifo_watermark_t rxWatermark; /*!< Rx watermark settings */
|
||||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
spi_pin_mode_t pinMode; /*!< SPI pin mode select */
|
||||
} spi_slave_config_t;
|
||||
|
||||
/*! @brief SPI transfer structure */
|
||||
|
@ -478,6 +459,27 @@ static inline uint32_t SPI_GetDataRegisterAddress(SPI_Type *base)
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Sets the pin mode for transfer.
|
||||
*
|
||||
* @param base SPI base pointer
|
||||
* @param pinMode pin mode for transfer AND #_spi_pin_mode could get the related configuration.
|
||||
*/
|
||||
static inline void SPI_SetPinMode(SPI_Type *base, spi_pin_mode_t pinMode)
|
||||
{
|
||||
/* Clear SPC0 and BIDIROE bit. */
|
||||
base->C2 &= ~(SPI_C2_BIDIROE_MASK | SPI_C2_SPC0_MASK);
|
||||
/* Set pin mode for transfer. */
|
||||
base->C2 |= SPI_C2_BIDIROE(pinMode >> 1U) | SPI_C2_SPC0(pinMode & 1U);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Sets the baud rate for SPI transfer. This is only used in master.
|
||||
*
|
||||
|
@ -544,6 +546,13 @@ void SPI_WriteData(SPI_Type *base, uint16_t data);
|
|||
*/
|
||||
uint16_t SPI_ReadData(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief Set up the dummy data.
|
||||
*
|
||||
* @param base SPI peripheral address.
|
||||
* @param dummyData Data to be transferred when tx buffer is NULL.
|
||||
*/
|
||||
void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData);
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
|
@ -582,11 +591,7 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer);
|
|||
*
|
||||
* @note The API immediately returns after transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times of the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Users can also call the functional API to
|
||||
* get the last
|
||||
* received data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
@ -636,8 +641,8 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle);
|
|||
* @param userData User data.
|
||||
*/
|
||||
void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
spi_slave_handle_t *handle,
|
||||
spi_slave_callback_t callback,
|
||||
void *userData);
|
||||
|
||||
/*!
|
||||
|
@ -645,11 +650,7 @@ void SPI_SlaveTransferCreateHandle(SPI_Type *base,
|
|||
*
|
||||
* @note The API returns immediately after the transfer initialization is finished.
|
||||
* Call SPI_GetStatusIRQ() to get the transfer status.
|
||||
* @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times the watermark.
|
||||
* Otherwise,
|
||||
* the last data may be lost because it cannot generate an interrupt request. Call the functional API to get the last
|
||||
* several
|
||||
* receive data.
|
||||
* @note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
|
||||
*
|
||||
* @param base SPI peripheral base address.
|
||||
* @param handle pointer to spi_master_handle_t structure which stores the transfer state
|
||||
|
|
|
@ -1,38 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "fsl_spi_dma.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitons
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/* Component ID definition, used by tools. */
|
||||
#ifndef FSL_COMPONENT_ID
|
||||
#define FSL_COMPONENT_ID "platform.drivers.spi_dma"
|
||||
#endif
|
||||
|
||||
/*<! Structure definition for spi_dma_private_handle_t. The structure is private. */
|
||||
typedef struct _spi_dma_private_handle
|
||||
{
|
||||
|
@ -52,13 +36,6 @@ static spi_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_SPI_COUNT];
|
|||
/*******************************************************************************
|
||||
* Prototypes
|
||||
******************************************************************************/
|
||||
/*!
|
||||
* @brief Get the instance for SPI module.
|
||||
*
|
||||
* @param base SPI base address
|
||||
*/
|
||||
extern uint32_t SPI_GetInstance(SPI_Type *base);
|
||||
|
||||
/*!
|
||||
* @brief DMA callback function for SPI send transfer.
|
||||
*
|
||||
|
@ -76,25 +53,18 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData);
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData);
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
/* Dummy data used to send */
|
||||
static const uint8_t s_dummyData = SPI_DUMMYDATA;
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_TxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->txHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -114,13 +84,13 @@ static void SPI_TxDMACallback(dma_handle_t *handle, void *userData)
|
|||
static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
||||
{
|
||||
spi_dma_private_handle_t *privHandle = (spi_dma_private_handle_t *)userData;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
spi_dma_handle_t *spiHandle = privHandle->handle;
|
||||
SPI_Type *base = privHandle->base;
|
||||
|
||||
/* Disable Tx dma */
|
||||
SPI_EnableDMA(base, kSPI_RxDmaEnable, false);
|
||||
|
||||
/* Stop DMA tranfer */
|
||||
/* Stop DMA transfer */
|
||||
DMA_StopTransfer(spiHandle->rxHandle);
|
||||
|
||||
/* change the state */
|
||||
|
@ -137,6 +107,19 @@ static void SPI_RxDMACallback(dma_handle_t *handle, void *userData)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Initialize the SPI master DMA handle.
|
||||
*
|
||||
* This function initializes the SPI master DMA handle which can be used for other SPI master transactional APIs.
|
||||
* Usually, for a specified SPI instance, user need only call this API once to get the initialized handle.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI handle pointer.
|
||||
* param callback User callback function called at the end of a transfer.
|
||||
* param userData User data for callback.
|
||||
* param txHandle DMA handle pointer for SPI Tx, the handle shall be static allocated by users.
|
||||
* param rxHandle DMA handle pointer for SPI Rx, the handle shall be static allocated by users.
|
||||
*/
|
||||
void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
||||
spi_dma_handle_t *handle,
|
||||
spi_dma_callback_t callback,
|
||||
|
@ -146,7 +129,10 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
{
|
||||
assert(handle);
|
||||
dma_transfer_config_t config = {0};
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
uint32_t instance = SPI_GetInstance(base);
|
||||
|
||||
/* Zero the handle */
|
||||
memset(handle, 0, sizeof(*handle));
|
||||
|
||||
/* Set spi base to handle */
|
||||
handle->txHandle = txHandle;
|
||||
|
@ -158,7 +144,7 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
handle->state = kSPI_Idle;
|
||||
|
||||
/* Set handle to global state */
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].base = base;
|
||||
s_dmaPrivateHandle[instance].handle = handle;
|
||||
|
||||
/* Compute internal state */
|
||||
|
@ -180,27 +166,27 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
#endif /* FSL_FEATURE_SPI_HAS_FIFO */
|
||||
|
||||
/* Set the non-change attribute for Tx DMA transfer, to improve efficiency */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
config.enableSrcIncrement = true;
|
||||
config.enableSrcIncrement = true;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
/* Set non-change attribute for Rx DMA */
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.srcAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = 0U;
|
||||
config.enableDestIncrement = true;
|
||||
config.enableSrcIncrement = false;
|
||||
config.enableSrcIncrement = false;
|
||||
DMA_SubmitTransfer(handle->rxHandle, &config, true);
|
||||
|
||||
/* Install callback for Tx dma channel */
|
||||
|
@ -208,6 +194,19 @@ void SPI_MasterTransferCreateHandleDMA(SPI_Type *base,
|
|||
DMA_SetCallback(handle->rxHandle, SPI_RxDMACallback, &s_dmaPrivateHandle[instance]);
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Perform a non-blocking SPI transfer using DMA.
|
||||
*
|
||||
* note This interface returned immediately after transfer initiates, users should call
|
||||
* SPI_GetTransferStatus to poll the transfer status to check whether SPI transfer finished.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param xfer Pointer to dma transfer structure.
|
||||
* retval kStatus_Success Successfully start a transfer.
|
||||
* retval kStatus_InvalidArgument Input argument is invalid.
|
||||
* retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
|
||||
*/
|
||||
status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_transfer_t *xfer)
|
||||
{
|
||||
assert(handle && xfer);
|
||||
|
@ -231,16 +230,16 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
SPI_Enable(base, true);
|
||||
|
||||
/* Configure tx transfer DMA */
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.destAddr = SPI_GetDataRegisterAddress(base);
|
||||
config.enableDestIncrement = false;
|
||||
if (handle->bytesPerFrame == 1U)
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.srcSize = kDMA_Transfersize8bits;
|
||||
config.destSize = kDMA_Transfersize8bits;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.srcSize = kDMA_Transfersize16bits;
|
||||
config.destSize = kDMA_Transfersize16bits;
|
||||
}
|
||||
config.transferSize = xfer->dataSize;
|
||||
|
@ -248,13 +247,13 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
if (xfer->txData)
|
||||
{
|
||||
config.enableSrcIncrement = true;
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
config.srcAddr = (uint32_t)(xfer->txData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the source increasement and source set to dummyData */
|
||||
config.enableSrcIncrement = false;
|
||||
config.srcAddr = (uint32_t)(&s_dummyData);
|
||||
config.srcAddr = (uint32_t)(&g_spiDummyData[SPI_GetInstance(base)]);
|
||||
}
|
||||
DMA_SubmitTransfer(handle->txHandle, &config, true);
|
||||
|
||||
|
@ -270,7 +269,7 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
|
||||
/* Change the state of handle */
|
||||
handle->transferSize = xfer->dataSize;
|
||||
handle->state = kSPI_Busy;
|
||||
handle->state = kSPI_Busy;
|
||||
|
||||
/* Start Rx transfer if needed */
|
||||
if (xfer->rxData)
|
||||
|
@ -288,6 +287,15 @@ status_t SPI_MasterTransferDMA(SPI_Type *base, spi_dma_handle_t *handle, spi_tra
|
|||
return kStatus_Success;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Get the transferred bytes for SPI slave DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
* param count Transferred bytes.
|
||||
* retval kStatus_SPI_Success Succeed get the transfer count.
|
||||
* retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
|
||||
*/
|
||||
status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle, size_t *count)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -313,6 +321,12 @@ status_t SPI_MasterTransferGetCountDMA(SPI_Type *base, spi_dma_handle_t *handle,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* brief Abort a SPI transfer using DMA.
|
||||
*
|
||||
* param base SPI peripheral base address.
|
||||
* param handle SPI DMA handle pointer.
|
||||
*/
|
||||
void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
@ -327,5 +341,5 @@ void SPI_MasterTransferAbortDMA(SPI_Type *base, spi_dma_handle_t *handle)
|
|||
/* Set the handle state */
|
||||
handle->txInProgress = false;
|
||||
handle->rxInProgress = false;
|
||||
handle->state = kSPI_Idle;
|
||||
handle->state = kSPI_Idle;
|
||||
}
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef _FSL_SPI_DMA_H_
|
||||
#define _FSL_SPI_DMA_H_
|
||||
|
@ -38,11 +16,16 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief SPI DMA driver version 2.0.4. */
|
||||
#define FSL_SPI_DMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
|
||||
/*@}*/
|
||||
|
||||
typedef struct _spi_dma_handle spi_dma_handle_t;
|
||||
|
||||
/*! @brief SPI DMA callback called at the end of transfer. */
|
||||
|
@ -55,7 +38,7 @@ struct _spi_dma_handle
|
|||
bool rxInProgress; /*!< Receive transfer finished */
|
||||
dma_handle_t *txHandle; /*!< DMA handler for SPI send */
|
||||
dma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI tranfer */
|
||||
uint8_t bytesPerFrame; /*!< Bytes in a frame for SPI transfer */
|
||||
spi_dma_callback_t callback; /*!< Callback for SPI DMA transfer */
|
||||
void *userData; /*!< User Data for SPI DMA callback */
|
||||
uint32_t state; /*!< Internal state of SPI DMA transfer */
|
||||
|
|
Loading…
Reference in New Issue