diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c index d3b3f0aa5f..a15314c758 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.c @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2019 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 the copyright holder 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_dspi.h" @@ -33,6 +11,12 @@ /******************************************************************************* * Definitions ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi" +#endif + /*! @brief Typedef for master interrupt handler. */ typedef void (*dspi_master_isr_t)(SPI_Type *base, dspi_master_handle_t *handle); @@ -42,13 +26,6 @@ typedef void (*dspi_slave_isr_t)(SPI_Type *base, dspi_slave_handle_t *handle); /******************************************************************************* * Prototypes ******************************************************************************/ -/*! - * @brief Get instance number for DSPI module. - * - * @param base DSPI peripheral base address. - */ -uint32_t DSPI_GetInstance(SPI_Type *base); - /*! * @brief Configures the DSPI peripheral chip select polarity. * @@ -110,11 +87,11 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/ static const uint32_t s_baudratePrescaler[] = {2, 3, 5, 7}; -static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, +static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}; static const uint32_t s_delayPrescaler[] = {1, 3, 5, 7}; -static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, +static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}; /*! @brief Pointers to dspi bases for each instance. */ @@ -138,10 +115,15 @@ static dspi_master_isr_t s_dspiMasterIsr; static dspi_slave_isr_t s_dspiSlaveIsr; /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/ -volatile uint8_t s_dummyData[ARRAY_SIZE(s_dspiBases)] = {0}; +volatile uint8_t g_dspiDummyData[ARRAY_SIZE(s_dspiBases)] = {0}; /********************************************************************************************************************** -* Code -*********************************************************************************************************************/ + * Code + *********************************************************************************************************************/ +/*! + * brief Get instance number for DSPI module. + * + * param base DSPI peripheral base address. + */ uint32_t DSPI_GetInstance(SPI_Type *base) { uint32_t instance; @@ -160,15 +142,64 @@ uint32_t DSPI_GetInstance(SPI_Type *base) return instance; } -void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base) { - uint32_t instance = DSPI_GetInstance(base); - s_dummyData[instance] = dummyData; + uint8_t instance = g_dspiDummyData[DSPI_GetInstance(base)]; + + return instance; } +/*! + * brief Set up the dummy data. + * + * param base DSPI peripheral address. + * param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +{ + uint32_t instance = DSPI_GetInstance(base); + g_dspiDummyData[instance] = dummyData; +} + +/*! + * brief Initializes the DSPI master. + * + * This function initializes the DSPI master configuration. This is an example use case. + * code + * dspi_master_config_t masterConfig; + * masterConfig.whichCtar = kDSPI_Ctar0; + * masterConfig.ctarConfig.baudRate = 500000000U; + * masterConfig.ctarConfig.bitsPerFrame = 8; + * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.whichPcs = kDSPI_Pcs0; + * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; + * masterConfig.enableContinuousSCK = false; + * masterConfig.enableRxFifoOverWrite = false; + * masterConfig.enableModifiedTimingFormat = false; + * masterConfig.samplePoint = kDSPI_SckToSin0Clock; + * DSPI_MasterInit(base, &masterConfig, srcClock_Hz); + * endcode + * + * param base DSPI peripheral address. + * param masterConfig Pointer to the structure dspi_master_config_t. + * param srcClock_Hz Module source input clock in Hertz. + */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz) { - assert(masterConfig); + assert(NULL != masterConfig); uint32_t temp; #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) @@ -179,6 +210,7 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u DSPI_Enable(base, true); DSPI_StopTransfer(base); + DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -187,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -199,48 +229,85 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - assert(masterConfig); + assert(NULL != masterConfig); - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); uint32_t temp = 0; @@ -260,14 +327,14 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); @@ -276,21 +343,41 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); - slaveConfig->whichCtar = kDSPI_Ctar0; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); @@ -320,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -339,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -405,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -429,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -451,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -482,87 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - assert(command); + assert(NULL != command); - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - assert(command); + assert(NULL != command); /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -571,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -587,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -605,45 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -652,15 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -672,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -713,24 +1013,25 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -738,13 +1039,13 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -752,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -765,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -818,26 +1120,27 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); if (rxData != NULL) { - *rxData = wordReceived; + *rxData = (uint8_t)wordReceived; ++rxData; - *rxData = wordReceived >> 8; + *rxData = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -849,31 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); - dspi_command_data_config_t commandStruct; + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -881,62 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); DSPI_StartTransfer(base); /* Fill up the Tx FIFO to trigger the transfer. */ DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -948,13 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -963,41 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - handle->state = kDSPI_Idle; - - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint16_t wordToSend = 0; - uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -1005,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1013,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1029,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1064,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1074,86 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1162,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1190,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1222,65 +1736,76 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); - if (handle->rxData) + if (NULL != handle->rxData) { /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); } - if (handle->txData) + if (NULL != handle->txData) { /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); } DSPI_StartTransfer(base); @@ -1291,17 +1816,27 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1313,24 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); uint16_t transmitData = 0; - uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1348,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1395,26 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1423,69 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; - if (handle->callback) + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1503,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1519,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1592,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1625,12 +2188,17 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif @@ -1638,7 +2206,7 @@ void SPI0_DriverIRQHandler(void) #if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif @@ -1646,7 +2214,7 @@ void SPI1_DriverIRQHandler(void) #if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif @@ -1654,7 +2222,7 @@ void SPI2_DriverIRQHandler(void) #if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif @@ -1662,7 +2230,7 @@ void SPI3_DriverIRQHandler(void) #if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif @@ -1670,7 +2238,7 @@ void SPI4_DriverIRQHandler(void) #if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h index abfc7707d7..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2019 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 the copyright holder 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -43,8 +21,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.2.0. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ #ifndef DSPI_DUMMY_DATA @@ -55,37 +33,37 @@ /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -102,7 +80,7 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! @@ -132,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -216,7 +194,7 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; @@ -241,7 +219,7 @@ enum _dspi_transfer_state /*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ @@ -258,10 +236,10 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum - delay. It also sets the boundary value if out of range.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the - minimum delay. It also sets the boundary value if out of range.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum delay. It also sets the boundary value if out of range.*/ @@ -315,13 +293,13 @@ typedef struct _dspi_slave_config } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -356,12 +334,24 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { @@ -373,7 +363,7 @@ struct _dspi_master_handle volatile bool isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ @@ -527,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -565,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -605,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -685,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -711,7 +707,14 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. @@ -749,8 +752,8 @@ static inline void DSPI_StopTransfer(SPI_Type *base) */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! @@ -762,8 +765,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! @@ -954,11 +957,11 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * buffer master mode and waits till complete to return. * * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total -* 32-bit word + * 32-bit word * as the data to send. * The command portion provides characteristics of the data, such as the optional continuous chip select operation * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the -* desired PCS + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: @@ -973,20 +976,20 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. * @param data The data word (command and data combined) to be sent. */ @@ -1037,7 +1040,7 @@ void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); /*! *@} -*/ + */ /*! * @name Transactional @@ -1086,6 +1089,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * @@ -1179,15 +1211,25 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c index ef0d15174f..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2018 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 the copyright holder 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_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,46 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -101,57 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); - assert(edmaTxDataToIntermediaryHandle); - assert(edmaIntermediaryToTxRegHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); +#if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) + assert(NULL != edmaTxDataToIntermediaryHandle); +#endif + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -160,31 +170,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -192,15 +204,15 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ uint32_t limited_size = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { @@ -211,11 +223,11 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand limited_size = 511u; } - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { if (transfer->dataSize > (limited_size << 1u)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } @@ -223,19 +235,19 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (transfer->dataSize > limited_size) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); @@ -268,47 +280,47 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - handle->command = handle->lastCommand; + handle->command = handle->lastCommand; } else /* For all words except the last word , frame > 8bits */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -318,10 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - handle->command = handle->lastCommand; + handle->command = handle->lastCommand; } else { @@ -331,57 +343,57 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /*dspi has shared dma request*/ - { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -389,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -401,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -411,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -429,68 +442,63 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); - - /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should - write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the - SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ - - EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + (uint32_t)kEDMA_MajorInterruptEnable); + tmpRemainingSendByteCount = handle->remainingSendByteCount; /*Calculate the last data : handle->lastCommand*/ - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -498,175 +506,335 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } } - /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data - * (handle->lastCommand) to handle->Command*/ - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) +/* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO, + * allowing a single write to the command word followed by multiple writes to the transmit word. + * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the + * transmit word into a 32-bit write that pushes both the command word and transmit word into + * the TX FIFO (PUSH TX FIFO Register In Master Mode) + * So, if this feature is supported, we can use use one channel to carry the receive data from + * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer + * to transmit register,and use the scatter/gather function to prepare the last data. + * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data. + */ +#if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET + /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to PUSHR register. + */ + + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + + if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || + ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigB.destAddr = (uint32_t) & (handle->command); - transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigB.srcOffset = 0; - transferConfigB.destOffset = 0; - transferConfigB.minorLoopBytes = 4; - transferConfigB.majorLoopCounts = 1; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } - /*User_Send_Buffer(txData) to intermediary(handle->command)*/ - if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + /*User_Send_Buffer(txData) to PUSHR register. */ + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { if (handle->txData) { - transferConfigB.srcAddr = (uint32_t)(handle->txData); - transferConfigB.srcOffset = 1; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /* For DSPI with separate RX and TX DMA requests, one frame data has been carry + * to handle->command, so need to reduce the pointer of txData. + */ + transferConfigB.srcAddr = + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); + transferConfigB.srcOffset = 1; + } + else + { + /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry + * to PUSHR register, so no need to change the pointer of txData. + */ + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcOffset = 1; + } } else { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigB.srcOffset = 0; } - transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destAddr = (uint32_t)txAddr; transferConfigB.destOffset = 0; transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; + transferConfigB.minorLoopBytes = 1; + + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD); + } + /* If only one word to transmit, only carry the lastcommand. */ + else + { + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL); + } + + /*Start the EDMA channel_A , channel_C. */ + EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); + EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); + + /* Set the channel link. + * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the + * receive register, and then carry transmit data to PUSHER register. + * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link. + */ + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /*Set channel priority*/ + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; + uint8_t t = 0; + + if (channelPriorityLow > channelPriorityHigh) + { + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; + channelPriorityHigh = t; + } + + edma_channel_Preemption_config_t preemption_config_t; + preemption_config_t.enableChannelPreemption = true; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; + + EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + &preemption_config_t); + + preemption_config_t.channelPriority = channelPriorityHigh; + EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to + channelC to carry the next data to PUSHER register.(txData to PUSHER) */ + if (handle->remainingSendByteCount > 0U) + { + EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); + } + } + + DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + + /* Setup control info to PUSHER register. */ + *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U); +#else + + /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should + write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the + SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + if (NULL != handle->txData) + { + transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcOffset = 1; + } + else + { + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; } else { /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; } } else { transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; + transferConfigB.minorLoopBytes = 2; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; } else { /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; } } if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); } } else { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); } /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to handle the last data */ + edma_transfer_config_t transferConfigC; EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + tmpRemainingSendByteCount = handle->remainingSendByteCount; /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data * (handle->lastCommand) to SPI_PUSHR*/ - if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) || + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); } else { transferConfigC.majorLoopCounts = 1; EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, @@ -675,7 +843,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -684,60 +853,64 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link.*/ @@ -745,18 +918,18 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB to prepare the next 32bits data (txData to handle->command) */ - if (handle->remainingSendByteCount > 1) + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); @@ -766,63 +939,147 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } - +#endif DSPI_StartTransfer(base); return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -838,6 +1095,25 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -845,16 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); - assert(edmaTxDataToTxRegHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -864,39 +1140,52 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ uint32_t limited_size = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { @@ -907,11 +1196,11 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle limited_size = 511u; } - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { if (transfer->dataSize > (limited_size << 1u)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } @@ -919,31 +1208,31 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle { if (transfer->dataSize > limited_size) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -954,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -966,14 +1255,15 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ @@ -983,18 +1273,18 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -1002,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -1018,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -1034,92 +1325,92 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destAddr = (uint32_t)txAddr; transferConfigC.destOffset = 0; - if (handle->txData) + if (NULL != handle->txData) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); transferConfigC.srcOffset = 1; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - handle->txBuffIfNull = DSPI_DUMMY_DATA; + handle->txBuffIfNull = dummyData; } else { - handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } } transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; } else { transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; } EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } @@ -1127,39 +1418,39 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1169,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1189,49 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h index 23e29ce298..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K66F/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2018 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 the copyright holder 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -41,14 +19,20 @@ * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! @@ -186,6 +170,21 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI base pointer + * @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * @param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief DSPI master aborts a transfer which is using eDMA. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.c index 4bc67d7ad3..a15314c758 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.c @@ -1,38 +1,22 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* 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. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ #include "fsl_dspi.h" /******************************************************************************* * Definitions ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi" +#endif + /*! @brief Typedef for master interrupt handler. */ typedef void (*dspi_master_isr_t)(SPI_Type *base, dspi_master_handle_t *handle); @@ -42,13 +26,6 @@ typedef void (*dspi_slave_isr_t)(SPI_Type *base, dspi_slave_handle_t *handle); /******************************************************************************* * Prototypes ******************************************************************************/ -/*! - * @brief Get instance number for DSPI module. - * - * @param base DSPI peripheral base address. - */ -uint32_t DSPI_GetInstance(SPI_Type *base); - /*! * @brief Configures the DSPI peripheral chip select polarity. * @@ -65,27 +42,27 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc /*! * @brief Master fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Master finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Slave fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle); /*! * @brief Slave finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle); @@ -100,7 +77,7 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param); /*! * @brief Master prepare the transfer. * Basically it set up dspi_master_handle . - * This is not a public API as it is called from other driver functions. fsl_dspi_edma.c also call this function. + * This is not a public API. */ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -110,11 +87,11 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/ static const uint32_t s_baudratePrescaler[] = {2, 3, 5, 7}; -static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, +static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}; static const uint32_t s_delayPrescaler[] = {1, 3, 5, 7}; -static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, +static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}; /*! @brief Pointers to dspi bases for each instance. */ @@ -129,7 +106,7 @@ static clock_ip_name_t const s_dspiClock[] = DSPI_CLOCKS; #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to dspi handles for each instance. */ -static void *g_dspiHandle[FSL_FEATURE_SOC_DSPI_COUNT]; +static void *g_dspiHandle[ARRAY_SIZE(s_dspiBases)]; /*! @brief Pointer to master IRQ handler for each instance. */ static dspi_master_isr_t s_dspiMasterIsr; @@ -137,15 +114,22 @@ static dspi_master_isr_t s_dspiMasterIsr; /*! @brief Pointer to slave IRQ handler for each instance. */ static dspi_slave_isr_t s_dspiSlaveIsr; +/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/ +volatile uint8_t g_dspiDummyData[ARRAY_SIZE(s_dspiBases)] = {0}; /********************************************************************************************************************** -* Code -*********************************************************************************************************************/ + * Code + *********************************************************************************************************************/ +/*! + * brief Get instance number for DSPI module. + * + * param base DSPI peripheral base address. + */ uint32_t DSPI_GetInstance(SPI_Type *base) { uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DSPI_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dspiBases); instance++) { if (s_dspiBases[instance] == base) { @@ -153,14 +137,69 @@ uint32_t DSPI_GetInstance(SPI_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DSPI_COUNT); + assert(instance < ARRAY_SIZE(s_dspiBases)); return instance; } +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base) +{ + uint8_t instance = g_dspiDummyData[DSPI_GetInstance(base)]; + + return instance; +} + +/*! + * brief Set up the dummy data. + * + * param base DSPI peripheral address. + * param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +{ + uint32_t instance = DSPI_GetInstance(base); + g_dspiDummyData[instance] = dummyData; +} + +/*! + * brief Initializes the DSPI master. + * + * This function initializes the DSPI master configuration. This is an example use case. + * code + * dspi_master_config_t masterConfig; + * masterConfig.whichCtar = kDSPI_Ctar0; + * masterConfig.ctarConfig.baudRate = 500000000U; + * masterConfig.ctarConfig.bitsPerFrame = 8; + * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.whichPcs = kDSPI_Pcs0; + * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; + * masterConfig.enableContinuousSCK = false; + * masterConfig.enableRxFifoOverWrite = false; + * masterConfig.enableModifiedTimingFormat = false; + * masterConfig.samplePoint = kDSPI_SckToSin0Clock; + * DSPI_MasterInit(base, &masterConfig, srcClock_Hz); + * endcode + * + * param base DSPI peripheral address. + * param masterConfig Pointer to the structure dspi_master_config_t. + * param srcClock_Hz Module source input clock in Hertz. + */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz) { - assert(masterConfig); + assert(NULL != masterConfig); uint32_t temp; #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) @@ -171,6 +210,7 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u DSPI_Enable(base, true); DSPI_StopTransfer(base); + DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -179,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -191,47 +229,85 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - assert(masterConfig); + assert(NULL != masterConfig); - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); uint32_t temp = 0; @@ -251,35 +327,57 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); - slaveConfig->whichCtar = kDSPI_Ctar0; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); @@ -309,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -328,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -394,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -418,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -440,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -471,87 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - assert(command); + assert(NULL != command); - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - assert(command); + assert(NULL != command); /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -560,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -576,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -594,45 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -641,15 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -661,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -702,24 +1013,25 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -727,13 +1039,13 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -741,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -754,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -807,26 +1120,27 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); if (rxData != NULL) { - *rxData = wordReceived; + *rxData = (uint8_t)wordReceived; ++rxData; - *rxData = wordReceived >> 8; + *rxData = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -838,31 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); - dspi_command_data_config_t commandStruct; + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -870,62 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); - - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - - DSPI_MasterTransferFillUpTxFifo(base, handle); /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -937,13 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -952,42 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -995,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1003,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1019,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1054,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1064,86 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1152,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1180,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1212,86 +1736,107 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); + + s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; + + /* Enable RX FIFO drain request, the slave only use this interrupt */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + + if (NULL != handle->rxData) + { + /* RX FIFO overflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); + } + if (NULL != handle->txData) + { + /* TX FIFO underflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); + } DSPI_StartTransfer(base); /* Prepare data to transmit */ DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; - - /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); - - if (handle->rxData) - { - /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); - } - if (handle->txData) - { - /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); - } - return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1303,24 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1338,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1385,26 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1413,69 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - if (handle->callback) + handle->state = (uint8_t)kDSPI_Idle; + + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint8_t dummyPattern = DSPI_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1493,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1509,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1582,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1615,52 +2188,57 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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 (FSL_FEATURE_SOC_DSPI_COUNT > 0) +#if defined(SPI0) void SPI0_DriverIRQHandler(void) { - assert(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 1) +#if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 2) +#if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 3) +#if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 4) +#if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 5) +#if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.h index eb730bd13a..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2019 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -37,15 +15,14 @@ * @{ */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.3. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 3)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ #ifndef DSPI_DUMMY_DATA @@ -56,37 +33,37 @@ /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -103,11 +80,12 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is valid + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point @@ -132,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -216,8 +194,9 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; #define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ @@ -240,7 +219,7 @@ enum _dspi_transfer_state /*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ @@ -257,10 +236,10 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum - delay. It also sets the boundary value if out of range.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the - minimum delay. It also sets the boundary value if out of range.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum delay. It also sets the boundary value if out of range.*/ @@ -314,13 +293,13 @@ typedef struct _dspi_slave_config } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -355,12 +334,24 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { @@ -370,8 +361,9 @@ struct _dspi_master_handle uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ @@ -525,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -563,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -575,6 +567,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) * * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); @@ -602,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -682,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -708,7 +707,14 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. @@ -746,8 +752,8 @@ static inline void DSPI_StopTransfer(SPI_Type *base) */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! @@ -759,8 +765,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! @@ -950,10 +956,12 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word * as the data to send. * The command portion provides characteristics of the data, such as the optional continuous chip select operation - * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: @@ -968,20 +976,20 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. * @param data The data word (command and data combined) to be sent. */ @@ -1022,9 +1030,17 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} -*/ + */ /*! * @name Transactional @@ -1073,6 +1089,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * @@ -1166,15 +1211,25 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.c index e37c78eac7..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* 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. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ #include "fsl_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,46 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -101,55 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); - assert(edmaTxDataToIntermediaryHandle); - assert(edmaIntermediaryToTxRegHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); +#if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) + assert(NULL != edmaTxDataToIntermediaryHandle); +#endif + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + handle->state = (uint8_t)kDSPI_Busy; + + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -158,33 +170,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - - handle->state = kDSPI_Busy; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -192,86 +204,123 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - /* This limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (handle->bitsPerFrame > 8) + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (transfer->dataSize > 1022) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ + /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else /* For all words except the last word , frame > 8bits */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -281,9 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -293,57 +343,57 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /*dspi has shared dma request*/ - { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -351,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -363,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -373,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -388,129 +439,66 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); - /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should - write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the - SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ - EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - - if (handle->remainingSendByteCount > 0) + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*Calculate the last data : handle->lastCommand*/ + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) - { - transferConfigB.srcAddr = (uint32_t)(handle->txData); - transferConfigB.srcOffset = 1; - } - else - { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigB.srcOffset = 0; - } - - transferConfigB.destAddr = (uint32_t)(&handle->command); - transferConfigB.destOffset = 0; - - transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; - - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; - } - } - else - { - transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; - } - } - - EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); - } - - /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to - handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -518,77 +506,345 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } } +/* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO, + * allowing a single write to the command word followed by multiple writes to the transmit word. + * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the + * transmit word into a 32-bit write that pushes both the command word and transmit word into + * the TX FIFO (PUSH TX FIFO Register In Master Mode) + * So, if this feature is supported, we can use use one channel to carry the receive data from + * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer + * to transmit register,and use the scatter/gather function to prepare the last data. + * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data. + */ +#if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET + /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to PUSHR register. + */ + + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + /*User_Send_Buffer(txData) to PUSHR register. */ + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); - transferConfigC.destAddr = (uint32_t)txAddr; - - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (handle->txData) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /* For DSPI with separate RX and TX DMA requests, one frame data has been carry + * to handle->command, so need to reduce the pointer of txData. + */ + transferConfigB.srcAddr = + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); + transferConfigB.srcOffset = 1; + } + else + { + /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry + * to PUSHR register, so no need to change the pointer of txData. + */ + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcOffset = 1; + } } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD); + } + /* If only one word to transmit, only carry the lastcommand. */ + else + { + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL); + } + + /*Start the EDMA channel_A , channel_C. */ + EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); + EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); + + /* Set the channel link. + * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the + * receive register, and then carry transmit data to PUSHER register. + * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link. + */ + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /*Set channel priority*/ + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; + uint8_t t = 0; + + if (channelPriorityLow > channelPriorityHigh) + { + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; + channelPriorityHigh = t; + } + + edma_channel_Preemption_config_t preemption_config_t; + preemption_config_t.enableChannelPreemption = true; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; + + EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + &preemption_config_t); + + preemption_config_t.channelPriority = channelPriorityHigh; + EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to + channelC to carry the next data to PUSHER register.(txData to PUSHER) */ + if (handle->remainingSendByteCount > 0U) + { + EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); + } + } + + DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + + /* Setup control info to PUSHER register. */ + *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U); +#else + + /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should + write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the + SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + if (NULL != handle->txData) + { + transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcOffset = 1; + } + else + { + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + majorlink , the majorlink would not trigger the channel_C*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; + } + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; + } + } + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to + handle the last data */ + + edma_transfer_config_t transferConfigC; + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) + { + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.destAddr = (uint32_t)txAddr; + + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); + } + else + { + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -597,84 +853,83 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ - if (handle->remainingSendByteCount > 1) + to prepare the next 32bits data (txData to handle->command) */ + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); @@ -684,63 +939,147 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } - +#endif DSPI_StartTransfer(base); return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->callback) + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; + + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -756,6 +1095,25 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -763,16 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); - assert(edmaTxDataToTxRegHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -782,76 +1140,99 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } + handle->state = (uint8_t)kDSPI_Busy; + uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -862,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -874,14 +1255,15 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ @@ -891,18 +1273,18 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -910,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -926,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -942,92 +1325,92 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destAddr = (uint32_t)txAddr; transferConfigC.destOffset = 0; - if (handle->txData) + if (NULL != handle->txData) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); transferConfigC.srcOffset = 1; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - handle->txBuffIfNull = DSPI_DUMMY_DATA; + handle->txBuffIfNull = dummyData; } else { - handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } } transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; } else { transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; } EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } @@ -1035,39 +1418,39 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1077,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1097,49 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->callback) + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; + + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.h index 4b4dbd930e..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -41,14 +19,20 @@ * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! @@ -186,6 +170,21 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI base pointer + * @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * @param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief DSPI master aborts a transfer which is using eDMA. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.c index b2f28ed51a..a15314c758 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.c @@ -1,38 +1,22 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* 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. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ #include "fsl_dspi.h" /******************************************************************************* * Definitions ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi" +#endif + /*! @brief Typedef for master interrupt handler. */ typedef void (*dspi_master_isr_t)(SPI_Type *base, dspi_master_handle_t *handle); @@ -42,13 +26,6 @@ typedef void (*dspi_slave_isr_t)(SPI_Type *base, dspi_slave_handle_t *handle); /******************************************************************************* * Prototypes ******************************************************************************/ -/*! - * @brief Get instance number for DSPI module. - * - * @param base DSPI peripheral base address. - */ -uint32_t DSPI_GetInstance(SPI_Type *base); - /*! * @brief Configures the DSPI peripheral chip select polarity. * @@ -65,27 +42,27 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc /*! * @brief Master fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Master finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Slave fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle); /*! * @brief Slave finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle); @@ -100,7 +77,7 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param); /*! * @brief Master prepare the transfer. * Basically it set up dspi_master_handle . - * This is not a public API as it is called from other driver functions. fsl_dspi_edma.c also call this function. + * This is not a public API. */ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -110,11 +87,11 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/ static const uint32_t s_baudratePrescaler[] = {2, 3, 5, 7}; -static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, +static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}; static const uint32_t s_delayPrescaler[] = {1, 3, 5, 7}; -static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, +static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}; /*! @brief Pointers to dspi bases for each instance. */ @@ -123,11 +100,13 @@ static SPI_Type *const s_dspiBases[] = SPI_BASE_PTRS; /*! @brief Pointers to dspi IRQ number for each instance. */ static IRQn_Type const s_dspiIRQ[] = SPI_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to dspi clocks for each instance. */ static clock_ip_name_t const s_dspiClock[] = DSPI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to dspi handles for each instance. */ -static void *g_dspiHandle[FSL_FEATURE_SOC_DSPI_COUNT]; +static void *g_dspiHandle[ARRAY_SIZE(s_dspiBases)]; /*! @brief Pointer to master IRQ handler for each instance. */ static dspi_master_isr_t s_dspiMasterIsr; @@ -135,15 +114,22 @@ static dspi_master_isr_t s_dspiMasterIsr; /*! @brief Pointer to slave IRQ handler for each instance. */ static dspi_slave_isr_t s_dspiSlaveIsr; +/* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/ +volatile uint8_t g_dspiDummyData[ARRAY_SIZE(s_dspiBases)] = {0}; /********************************************************************************************************************** -* Code -*********************************************************************************************************************/ + * Code + *********************************************************************************************************************/ +/*! + * brief Get instance number for DSPI module. + * + * param base DSPI peripheral base address. + */ uint32_t DSPI_GetInstance(SPI_Type *base) { uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DSPI_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dspiBases); instance++) { if (s_dspiBases[instance] == base) { @@ -151,20 +137,80 @@ uint32_t DSPI_GetInstance(SPI_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DSPI_COUNT); + assert(instance < ARRAY_SIZE(s_dspiBases)); return instance; } +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base) +{ + uint8_t instance = g_dspiDummyData[DSPI_GetInstance(base)]; + + return instance; +} + +/*! + * brief Set up the dummy data. + * + * param base DSPI peripheral address. + * param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +{ + uint32_t instance = DSPI_GetInstance(base); + g_dspiDummyData[instance] = dummyData; +} + +/*! + * brief Initializes the DSPI master. + * + * This function initializes the DSPI master configuration. This is an example use case. + * code + * dspi_master_config_t masterConfig; + * masterConfig.whichCtar = kDSPI_Ctar0; + * masterConfig.ctarConfig.baudRate = 500000000U; + * masterConfig.ctarConfig.bitsPerFrame = 8; + * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.whichPcs = kDSPI_Pcs0; + * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; + * masterConfig.enableContinuousSCK = false; + * masterConfig.enableRxFifoOverWrite = false; + * masterConfig.enableModifiedTimingFormat = false; + * masterConfig.samplePoint = kDSPI_SckToSin0Clock; + * DSPI_MasterInit(base, &masterConfig, srcClock_Hz); + * endcode + * + * param base DSPI peripheral address. + * param masterConfig Pointer to the structure dspi_master_config_t. + * param srcClock_Hz Module source input clock in Hertz. + */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz) { + assert(NULL != masterConfig); + uint32_t temp; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); + DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -173,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -185,48 +229,92 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; - masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + assert(NULL != masterConfig); - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; + masterConfig->ctarConfig.bitsPerFrame = 8; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { + assert(NULL != slaveConfig); + uint32_t temp = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -239,40 +327,66 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - slaveConfig->whichCtar = kDSPI_Ctar0; - slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + assert(NULL != slaveConfig); - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; + slaveConfig->ctarConfig.bitsPerFrame = 8; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); DSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* disable DSPI clock */ CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh) @@ -293,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -312,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -378,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -402,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -424,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -455,83 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + assert(NULL != command); + + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + assert(NULL != command); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + /* First, clear Transmit Complete Flag (TCF) */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); + + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -540,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -556,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -574,45 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -621,34 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -660,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -701,54 +1013,39 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; + if (rxData != NULL) + { + *(rxData) = (uint8_t)DSPI_ReadData(base); + rxData++; + } + else + { + (void)DSPI_ReadData(base); + } + remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) - { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -756,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -769,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -822,24 +1120,28 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; + wordReceived = (uint16_t)DSPI_ReadData(base); - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + if (rxData != NULL) + { + *rxData = (uint8_t)wordReceived; + ++rxData; + *rxData = (uint8_t)(wordReceived >> 8U); + ++rxData; + } + remainingReceiveByteCount -= 2U; + + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -850,28 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - dspi_command_data_config_t commandStruct; + assert(NULL != handle); + assert(NULL != transfer); + + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -879,61 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); - - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - - DSPI_MasterTransferFillUpTxFifo(base, handle); /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -945,11 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -958,40 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + assert(NULL != handle); + + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -999,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1007,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1023,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1058,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1068,82 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1152,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1180,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1212,85 +1736,107 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); + + s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; + + /* Enable RX FIFO drain request, the slave only use this interrupt */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + + if (NULL != handle->rxData) + { + /* RX FIFO overflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); + } + if (NULL != handle->txData) + { + /* TX FIFO underflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); + } DSPI_StartTransfer(base); /* Prepare data to transmit */ DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; - - /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); - - if (handle->rxData) - { - /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); - } - if (handle->txData) - { - /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); - } - return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1302,22 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1335,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1382,24 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1408,65 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - if (handle->callback) + handle->state = (uint8_t)kDSPI_Idle; + + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - uint8_t dummyPattern = DSPI_DUMMY_DATA; + assert(NULL != handle); + + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1484,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1500,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1573,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1606,52 +2188,57 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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 (FSL_FEATURE_SOC_DSPI_COUNT > 0) +#if defined(SPI0) void SPI0_DriverIRQHandler(void) { - assert(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 1) +#if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 2) +#if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 3) +#if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 4) +#if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 5) +#if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.h index dfbeb3e457..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2019 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -37,54 +15,55 @@ * @{ */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.1. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ -/*! @brief DSPI dummy data if no Tx data.*/ -#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for tx if there is not txData. */ +#ifndef DSPI_DUMMY_DATA +/*! @brief DSPI dummy data if there is no Tx data.*/ +#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */ +#endif /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out Of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All status above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -101,12 +80,13 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in Modified Transfer Format. This field is valid - * only when CPHA bit in CTAR register is 0. + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid + * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point { @@ -130,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -165,36 +145,37 @@ typedef enum _dspi_clock_phase typedef enum _dspi_shift_direction { kDSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ - kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ + kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. + Shifting out of LSB is not supported for slave */ } dspi_shift_direction_t; /*! @brief DSPI delay type selection.*/ typedef enum _dspi_delay_type { kDSPI_PcsToSck = 1U, /*!< Pcs-to-SCK delay. */ - kDSPI_LastSckToPcs, /*!< Last SCK edge to Pcs delay. */ + kDSPI_LastSckToPcs, /*!< The last SCK edge to Pcs delay. */ kDSPI_BetweenTransfer /*!< Delay between transfers. */ } dspi_delay_type_t; /*! @brief DSPI Clock and Transfer Attributes Register (CTAR) selection.*/ typedef enum _dspi_ctar_selection { - kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode, note that CTAR0 and CTAR0_SLAVE are the + kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode; note that CTAR0 and CTAR0_SLAVE are the same register address. */ kDSPI_Ctar1 = 1U, /*!< CTAR1 selection option for master mode only. */ - kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only , note that some device do not support CTAR2. */ - kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only , note that some device do not support CTAR3. */ - kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only , note that some device do not support CTAR4. */ - kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only , note that some device do not support CTAR5. */ - kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only , note that some device do not support CTAR6. */ - kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only , note that some device do not support CTAR7. */ + kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only; note that some devices do not support CTAR2. */ + kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only; note that some devices do not support CTAR3. */ + kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only; note that some devices do not support CTAR4. */ + kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only; note that some devices do not support CTAR5. */ + kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only; note that some devices do not support CTAR6. */ + kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only; note that some devices do not support CTAR7. */ } dspi_ctar_selection_t; -#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro , internal used. */ -#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro , internal used. */ -#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro , internal used. */ -#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro , internal used. */ -/*! @brief Can use this enumeration for DSPI master transfer configFlags. */ +#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro; used internally. */ +#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro; used internally. */ +#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro; used internally. */ +#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI master transfer configFlags. */ enum _dspi_transfer_config_flag_for_master { kDSPI_MasterCtar0 = 0U << DSPI_MASTER_CTAR_SHIFT, /*!< DSPI master transfer use CTAR0 setting. */ @@ -213,13 +194,14 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Is PCS signal active after last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; -#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro , internal used. */ -#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro , internal used. */ -/*! @brief Can use this enum for DSPI slave transfer configFlags. */ +#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ +#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI slave transfer configFlags. */ enum _dspi_transfer_config_flag_for_slave { kDSPI_SlaveCtar0 = 0U << DSPI_SLAVE_CTAR_SHIFT, /*!< DSPI slave transfer use CTAR0 setting. */ @@ -234,15 +216,15 @@ enum _dspi_transfer_state kDSPI_Error /*!< Transfer error. */ }; -/*! @brief DSPI master command date configuration used for SPIx_PUSHR.*/ +/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ bool isEndOfQueue; /*!< Signals that the current transfer is the last in the queue.*/ - bool clearTransferCount; /*!< Clears SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ + bool clearTransferCount; /*!< Clears the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ } dspi_command_data_config_t; /*! @brief DSPI master ctar configuration structure.*/ @@ -254,33 +236,33 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time with nanosecond , set to 0 sets the minimum - delay. It sets the boundary value if out of range that can be set.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time with nanosecond , set to 0 sets the - minimum delay.It sets the boundary value if out of range that can be - set.*/ - uint32_t betweenTransferDelayInNanoSec; /*!< After SCK delay time with nanosecond , set to 0 sets the minimum - delay.It sets the boundary value if out of range that can be set.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ + + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ } dspi_master_ctar_config_t; /*! @brief DSPI master configuration structure.*/ typedef struct _dspi_master_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_master_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - dspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs). */ - dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low. */ + dspi_which_pcs_t whichPcs; /*!< The desired Peripheral Chip Select (pcs). */ + dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< The desired PCS active high or low. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable . Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_master_config_t; @@ -290,34 +272,34 @@ typedef struct _dspi_slave_ctar_config uint32_t bitsPerFrame; /*!< Bits per frame, minimum 4, maximum 16.*/ dspi_clock_polarity_t cpol; /*!< Clock polarity. */ dspi_clock_phase_t cpha; /*!< Clock phase. */ - /*!< Slave only supports MSB , does not support LSB.*/ + /*!< Slave only supports MSB and does not support LSB.*/ } dspi_slave_ctar_config_t; /*! @brief DSPI slave configuration structure.*/ typedef struct _dspi_slave_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_slave_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -352,47 +334,60 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags , set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ + volatile uint8_t state; /*!< DSPI transfer state, see _dspi_transfer_state.*/ dspi_master_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ }; -/*! @brief DSPI slave transfer handle structure used for transactional API. */ +/*! @brief DSPI slave transfer handle structure used for the transactional API. */ struct _dspi_slave_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ volatile uint8_t state; /*!< DSPI transfer state.*/ @@ -417,18 +412,18 @@ extern "C" { /*! * @brief Initializes the DSPI master. * - * This function initializes the DSPI master configuration. An example use case is as follows: + * This function initializes the DSPI master configuration. This is an example use case. * @code * dspi_master_config_t masterConfig; * masterConfig.whichCtar = kDSPI_Ctar0; - * masterConfig.ctarConfig.baudRate = 500000000; + * masterConfig.ctarConfig.baudRate = 500000000U; * masterConfig.ctarConfig.bitsPerFrame = 8; * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; - * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; * masterConfig.whichPcs = kDSPI_Pcs0; * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; * masterConfig.enableContinuousSCK = false; @@ -439,8 +434,8 @@ extern "C" { * @endcode * * @param base DSPI peripheral address. - * @param masterConfig Pointer to structure dspi_master_config_t. - * @param srcClock_Hz Module source input clock in Hertz + * @param masterConfig Pointer to the structure dspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz. */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz); @@ -448,8 +443,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u * @brief Sets the dspi_master_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). - * User may use the initialized structure unchanged in DSPI_MasterInit() or modify the structure - * before calling DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). * Example: * @code * dspi_master_config_t masterConfig; @@ -462,7 +457,7 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); /*! * @brief DSPI slave configuration. * - * This function initializes the DSPI slave configuration. An example use case is as follows: + * This function initializes the DSPI slave configuration. This is an example use case. * @code * dspi_slave_config_t slaveConfig; * slaveConfig->whichCtar = kDSPI_Ctar0; @@ -477,22 +472,22 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); * @endcode * * @param base DSPI peripheral address. - * @param slaveConfig Pointer to structure dspi_master_config_t. + * @param slaveConfig Pointer to the structure dspi_master_config_t. */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig); /*! - * @brief Sets the dspi_slave_config_t structure to default values. + * @brief Sets the dspi_slave_config_t structure to a default value. * * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). - * User may use the initialized structure unchanged in DSPI_SlaveInit(), or modify the structure - * before calling DSPI_SlaveInit(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. * @code * dspi_slave_config_t slaveConfig; * DSPI_SlaveGetDefaultConfig(&slaveConfig); * @endcode - * @param slaveConfig pointer to dspi_slave_config_t structure. + * @param slaveConfig Pointer to the dspi_slave_config_t structure. */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig); @@ -506,7 +501,7 @@ void DSPI_Deinit(SPI_Type *base); * @brief Enables the DSPI peripheral and sets the MCR MDIS to 0. * * @param base DSPI peripheral address. - * @param enable pass true to enable module, false to disable module. + * @param enable Pass true to enable module, false to disable module. */ static inline void DSPI_Enable(SPI_Type *base, bool enable) { @@ -522,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -532,7 +527,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! * @brief Gets the DSPI status flag state. * @param base DSPI peripheral address. - * @return The DSPI status(in SR register). + * @return DSPI status (in SR register). */ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) { @@ -545,13 +540,13 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the * desired status bit to clear. The list of status bits is defined in the dspi_status_and_interrupt_request_t. The * function uses these bit positions in its algorithm to clear the desired flag state. - * Example usage: + * This is an example. * @code * DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag); * @endcode * * @param base DSPI peripheral address. - * @param statusFlags The status flag , used from type dspi_flags. + * @param statusFlags The status flag used from the type dspi_flags. */ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) { @@ -560,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -570,15 +565,16 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! * @brief Enables the DSPI interrupts. * - * This function configures the various interrupt masks of the DSPI. The parameters are base and an interrupt mask. + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); @@ -590,7 +586,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) { @@ -599,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -609,13 +605,13 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! * @brief Enables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * DSPI_EnableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) { @@ -625,13 +621,13 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) /*! * @brief Disables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * SPI_DisableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask) { @@ -679,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -705,12 +707,19 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. * - * This function sets the module to begin data transfer in either master or slave mode. + * This function sets the module to start data transfer in either master or slave mode. * * @param base DSPI peripheral address. */ @@ -719,9 +728,9 @@ static inline void DSPI_StartTransfer(SPI_Type *base) base->MCR &= ~SPI_MCR_HALT_MASK; } /*! - * @brief Stops (halts) DSPI transfers and sets HALT bit in MCR. + * @brief Stops DSPI transfers and sets the HALT bit in MCR. * - * This function stops data transfers in either master or slave mode. + * This function stops data transfers in either master or slave modes. * * @param base DSPI peripheral address. */ @@ -731,44 +740,44 @@ static inline void DSPI_StopTransfer(SPI_Type *base) } /*! - * @brief Enables (or disables) the DSPI FIFOs. + * @brief Enables or disables the DSPI FIFOs. * - * This function allows the caller to disable/enable the Tx and Rx FIFOs (independently). - * Note that to disable, the caller must pass in a logic 0 (false) for the particular FIFO configuration. To enable, - * the caller must pass in a logic 1 (true). + * This function allows the caller to disable/enable the Tx and Rx FIFOs independently. + * Note that to disable, pass in a logic 0 (false) for the particular FIFO configuration. To enable, + * pass in a logic 1 (true). * * @param base DSPI peripheral address. - * @param enableTxFifo Disables (false) the TX FIFO, else enables (true) the TX FIFO - * @param enableRxFifo Disables (false) the RX FIFO, else enables (true) the RX FIFO + * @param enableTxFifo Disables (false) the TX FIFO; Otherwise, enables (true) the TX FIFO + * @param enableRxFifo Disables (false) the RX FIFO; Otherwise, enables (true) the RX FIFO */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! * @brief Flushes the DSPI FIFOs. * * @param base DSPI peripheral address. - * @param flushTxFifo Flushes (true) the Tx FIFO, else do not flush (false) the Tx FIFO - * @param flushRxFifo Flushes (true) the Rx FIFO, else do not flush (false) the Rx FIFO + * @param flushTxFifo Flushes (true) the Tx FIFO; Otherwise, does not flush (false) the Tx FIFO + * @param flushRxFifo Flushes (true) the Rx FIFO; Otherwise, does not flush (false) the Rx FIFO */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! * @brief Configures the DSPI peripheral chip select polarity simultaneously. - * For example, PCS0 and PCS1 set to active low and other PCS set to active high. Note that the number of + * For example, PCS0 and PCS1 are set to active low and other PCS is set to active high. Note that the number of * PCSs is specific to the device. * @code * DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow); @endcode * @param base DSPI peripheral address. - * @param mask The PCS polarity mask , can use the enum _dspi_pcs_polarity. + * @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity. */ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask) { @@ -797,19 +806,19 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, * @brief Manually configures the delay prescaler and scaler for a particular CTAR. * * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar - * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT)and scalar (DT). + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes the delay to configure along with the prescaler and scaler value. - * This allows the user to directly set the prescaler/scaler values if they have pre-calculated them or if they simply - * wish to manually increment either value. + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. * * @param base DSPI peripheral address. * @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. * @param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). * @param scaler The scaler delay value (can be any integer between 0 to 15). - * @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * @param whichDelay The desired delay to configure; must be of type dspi_delay_type_t */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay); @@ -817,15 +826,15 @@ void DSPI_MasterSetDelayScaler( /*! * @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. * - * This function calculates the values for: + * This function calculates the values for the following. * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or * After SCK delay pre-scalar (PASC) and scalar (ASC), or - * Delay after transfer pre-scalar (PDT)and scalar (DT). + * Delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes which delay they want to configure along with the desired delay value in nanoseconds. The function - * calculates the values needed for the prescaler and scaler and returning the actual calculated delay as an exact + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact * delay match may not be possible. In this case, the closest match is calculated without going below the desired * delay value input. * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum @@ -849,11 +858,11 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, * @brief Writes data into the data buffer for master mode. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_data_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -865,7 +874,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, @endcode * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) @@ -879,14 +888,14 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config * @brief Sets the dspi_command_data_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). - * User may use the initialized structure unchanged in DSPI_MasterWrite_xx() or modify the structure - * before calling DSPI_MasterWrite_xx(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. * @code * dspi_command_data_config_t command; * DSPI_GetDefaultDataCommandConfig(&command); * @endcode - * @param command pointer to dspi_command_data_config_t structure. + * @param command Pointer to the dspi_command_data_config_t structure. */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); @@ -894,11 +903,11 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * @brief Writes data into the data buffer master mode and waits till complete to return. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -911,10 +920,10 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, - * receive data is available when transmit completes. + * the received data is available when the transmit completes. * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data); @@ -929,10 +938,10 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co * improve performance in cases where the command structure is constant. For example, the user calls this function * before starting a transfer to generate the command word. When they are ready to transmit the data, they OR * this formatted command word with the desired data to transmit. This process increases transmit performance when - * compared to calling send functions such as DSPI_HAL_WriteDataMastermode which format the command word each time a + * compared to calling send functions, such as DSPI_HAL_WriteDataMastermode, which format the command word each time a * data word is to be sent. * - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @return The command word formatted to the PUSHR data register bit field. */ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t *command) @@ -945,43 +954,44 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t /*! * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data - * buffer, master mode and waits till complete to return. + * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command info then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word * as the data to send. - * The command portion provides characteristics of the data such as the optional continuous chip select operation -* between - * transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: * @code * dataWord = <16-bit command> | <16-bit data>; - * DSPI_HAL_WriteCommandDataMastermodeBlocking(base, dataWord); + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); * @endcode * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). - * Because the SPI is a synchronous protocol, the receive data is available when transmit completes. + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. - * @param data The data word (command and data combined) to be sent + * @param data The data word (command and data combined) to be sent. */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data); @@ -1020,9 +1030,17 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} -*/ + */ /*! * @name Transactional @@ -1033,13 +1051,13 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) /*! * @brief Initializes the DSPI master handle. * - * This function initializes the DSPI handle which can be used for other DSPI transactional APIs. Usually, for a + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_handle_t. - * @param callback dspi callback. - * @param userData callback function parameter. + * @param callback DSPI callback. + * @param userData Callback function parameter. */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, @@ -1049,12 +1067,11 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, /*! * @brief DSPI master transfer data using polling. * - * This function transfers data with polling. This is a blocking function, which does not return until all transfers - * have been - * completed. + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. * * @param base DSPI peripheral base address. - * @param transfer pointer to dspi_transfer_t structure. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); @@ -1063,35 +1080,63 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); * @brief DSPI master transfer data using interrupts. * * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all - data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * * This function gets the master transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count); /*! - * @brief DSPI master aborts transfer using an interrupt. + * @brief DSPI master aborts a transfer using an interrupt. * * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); @@ -1101,7 +1146,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); @@ -1111,10 +1156,10 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * @param handle DSPI handle pointer to dspi_slave_handle_t. + * @param handle DSPI handle pointer to the dspi_slave_handle_t. * @param base DSPI peripheral base address. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData Callback function parameter. */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, @@ -1125,12 +1170,11 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, * @brief DSPI slave transfers data using an interrupt. * * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all - * data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer); @@ -1141,8 +1185,8 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand * This function gets the slave transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count); @@ -1150,10 +1194,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, /*! * @brief DSPI slave aborts a transfer using an interrupt. * - * This function aborts transfer using an interrupt. + * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); @@ -1163,19 +1207,29 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.c index a1c20027b2..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* 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. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ #include "fsl_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,46 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -101,51 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); +#if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) + assert(NULL != edmaTxDataToIntermediaryHandle); +#endif + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + handle->state = (uint8_t)kDSPI_Busy; + + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -154,33 +170,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - - handle->state = kDSPI_Busy; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -188,98 +204,123 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - /* this limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (handle->bitsPerFrame > 8) + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (transfer->dataSize > 1022) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) + { + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_InvalidArgument; + } + + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) - { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } - } - else - { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - } - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - } - else /* For all words except the last word , frame > 8bits */ - { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; + } + else + { + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); + } + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; + } + else /* For all words except the last word , frame > 8bits */ + { + if (NULL != handle->txData) + { + wordToSend = *(handle->txData); + ++handle->txData; /* increment to next data byte */ + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -289,9 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -301,66 +343,57 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /*dspi has shared dma request*/ - { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -368,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -380,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -390,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -405,125 +439,66 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); - /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should - write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the - SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ - EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - - if (handle->remainingSendByteCount > 0) + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*Calculate the last data : handle->lastCommand*/ + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) - { - transferConfigB.srcAddr = (uint32_t)(handle->txData); - transferConfigB.srcOffset = 1; - } - else - { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigB.srcOffset = 0; - } - - transferConfigB.destAddr = (uint32_t)(&handle->command); - transferConfigB.destOffset = 0; - - transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; - - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; - } - } - else - { - transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; - } - } - - EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); - } - - /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to - handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -531,85 +506,345 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - if (handle->isThereExtraByte) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 2] | - ((uint32_t)dummyData << 8); - } - else - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; - } + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } } +/* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO, + * allowing a single write to the command word followed by multiple writes to the transmit word. + * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the + * transmit word into a 32-bit write that pushes both the command word and transmit word into + * the TX FIFO (PUSH TX FIFO Register In Master Mode) + * So, if this feature is supported, we can use use one channel to carry the receive data from + * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer + * to transmit register,and use the scatter/gather function to prepare the last data. + * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data. + */ +#if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET + /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to PUSHR register. + */ + + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + /*User_Send_Buffer(txData) to PUSHR register. */ + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); - transferConfigC.destAddr = (uint32_t)txAddr; - - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (handle->txData) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /* For DSPI with separate RX and TX DMA requests, one frame data has been carry + * to handle->command, so need to reduce the pointer of txData. + */ + transferConfigB.srcAddr = + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); + transferConfigB.srcOffset = 1; + } + else + { + /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry + * to PUSHR register, so no need to change the pointer of txData. + */ + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcOffset = 1; + } } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD); + } + /* If only one word to transmit, only carry the lastcommand. */ + else + { + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL); + } + + /*Start the EDMA channel_A , channel_C. */ + EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); + EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); + + /* Set the channel link. + * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the + * receive register, and then carry transmit data to PUSHER register. + * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link. + */ + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /*Set channel priority*/ + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; + uint8_t t = 0; + + if (channelPriorityLow > channelPriorityHigh) + { + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; + channelPriorityHigh = t; + } + + edma_channel_Preemption_config_t preemption_config_t; + preemption_config_t.enableChannelPreemption = true; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; + + EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + &preemption_config_t); + + preemption_config_t.channelPriority = channelPriorityHigh; + EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to + channelC to carry the next data to PUSHER register.(txData to PUSHER) */ + if (handle->remainingSendByteCount > 0U) + { + EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); + } + } + + DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + + /* Setup control info to PUSHER register. */ + *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U); +#else + + /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should + write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the + SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + if (NULL != handle->txData) + { + transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcOffset = 1; + } + else + { + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + majorlink , the majorlink would not trigger the channel_C*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; + } + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; + } + } + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to + handle the last data */ + + edma_transfer_config_t transferConfigC; + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) + { + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.destAddr = (uint32_t)txAddr; + + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); + } + else + { + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -618,165 +853,233 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ - if (handle->remainingSendByteCount > 1) + to prepare the next 32bits data (txData to handle->command) */ + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->isThereExtraByte) - { - EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); - } - EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } - +#endif DSPI_StartTransfer(base); return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -784,13 +1087,33 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -798,14 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -815,88 +1140,99 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU)); + handle->state = (uint8_t)kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } - if ((handle->bitsPerFrame > 8) && (transfer->dataSize < 2)) + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; - handle->errorCount = 0; + handle->totalByteCount = transfer->dataSize; - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } - - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -907,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -919,42 +1255,36 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ - if ((handle->remainingSendByteCount == 2) && (handle->isThereExtraByte)) - { - wordToSend |= (unsigned)(dummyData) << 8U; - ++handle->txData; /* Increment to next data byte */ - } - else - { - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - ++handle->txData; /* Increment to next data byte */ - } + + wordToSend |= (unsigned)(*(handle->txData)) << 8U; + ++handle->txData; /* Increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -962,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -978,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -994,179 +1325,132 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - /*If there is extra byte , it would use the */ - if (handle->isThereExtraByte) - { - if (handle->txData) - { - handle->txLastData = - handle->txData[handle->remainingSendByteCount - 2] | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - else - { - handle->txLastData = DSPI_DUMMY_DATA | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - transferConfigC.srcAddr = (uint32_t)(&(handle->txLastData)); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destOffset = 0; - EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); - } - - /*Set another transferConfigC*/ - if ((handle->isThereExtraByte) && (handle->remainingSendByteCount == 2)) + if (NULL != handle->txData) { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcOffset = 1; } else { - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.destOffset = 0; - - if (handle->txData) + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcOffset = 0; + if (handle->bitsPerFrame <= 8U) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); - transferConfigC.srcOffset = 1; + handle->txBuffIfNull = dummyData; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) - { - handle->txBuffIfNull = DSPI_DUMMY_DATA; - } - else - { - handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - } + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } - - transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; - } - else - { - transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - if (handle->isThereExtraByte) - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; - } - } - - if (handle->isThereExtraByte) - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, softwareTCD); - EDMA_EnableAutoStopRequest(handle->edmaTxDataToTxRegHandle->base, - handle->edmaTxDataToTxRegHandle->channel, false); - } - else - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); - } - - EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } + + transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + } + else + { + transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; + } + + EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + + EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1176,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1196,58 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1255,7 +1548,8 @@ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.h index 643efadca4..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -37,28 +15,33 @@ * @{ */ - /*********************************************************************************************************************** * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI master. + * @param handle A pointer to the handle for the DSPI master. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, dspi_master_edma_handle_t *handle, @@ -68,38 +51,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI slave. + * @param handle A pointer to the handle for the DSPI slave. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData); -/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */ +/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */ struct _dspi_master_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/ + + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ - dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ @@ -110,33 +94,30 @@ struct _dspi_master_edma_handle edma_tcd_t dspiSoftwareTCD[2]; /*!whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -173,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -185,48 +229,92 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; - masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + assert(NULL != masterConfig); - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; + masterConfig->ctarConfig.bitsPerFrame = 8; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { + assert(NULL != slaveConfig); + uint32_t temp = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -239,40 +327,66 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - slaveConfig->whichCtar = kDSPI_Ctar0; - slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + assert(NULL != slaveConfig); - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; + slaveConfig->ctarConfig.bitsPerFrame = 8; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); DSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* disable DSPI clock */ CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh) @@ -293,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -312,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -378,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -402,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -424,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -455,83 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + assert(NULL != command); + + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + assert(NULL != command); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + /* First, clear Transmit Complete Flag (TCF) */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); + + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -540,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -556,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -574,45 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -621,34 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -660,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -701,54 +1013,39 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; + if (rxData != NULL) + { + *(rxData) = (uint8_t)DSPI_ReadData(base); + rxData++; + } + else + { + (void)DSPI_ReadData(base); + } + remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) - { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -756,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -769,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -822,24 +1120,28 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; + wordReceived = (uint16_t)DSPI_ReadData(base); - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + if (rxData != NULL) + { + *rxData = (uint8_t)wordReceived; + ++rxData; + *rxData = (uint8_t)(wordReceived >> 8U); + ++rxData; + } + remainingReceiveByteCount -= 2U; + + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -850,28 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - dspi_command_data_config_t commandStruct; + assert(NULL != handle); + assert(NULL != transfer); + + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -879,61 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); - - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - - DSPI_MasterTransferFillUpTxFifo(base, handle); /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -945,11 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -958,40 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + assert(NULL != handle); + + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -999,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1007,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1023,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1058,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1068,82 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1152,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1180,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1212,85 +1736,107 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); + + s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; + + /* Enable RX FIFO drain request, the slave only use this interrupt */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + + if (NULL != handle->rxData) + { + /* RX FIFO overflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); + } + if (NULL != handle->txData) + { + /* TX FIFO underflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); + } DSPI_StartTransfer(base); /* Prepare data to transmit */ DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; - - /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); - - if (handle->rxData) - { - /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); - } - if (handle->txData) - { - /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); - } - return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1302,22 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1335,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1382,24 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1408,65 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - if (handle->callback) + handle->state = (uint8_t)kDSPI_Idle; + + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - uint8_t dummyPattern = DSPI_DUMMY_DATA; + assert(NULL != handle); + + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1484,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1500,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1573,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1606,52 +2188,57 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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 (FSL_FEATURE_SOC_DSPI_COUNT > 0) +#if defined(SPI0) void SPI0_DriverIRQHandler(void) { - assert(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 1) +#if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 2) +#if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 3) +#if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 4) +#if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 5) +#if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi.h index dfbeb3e457..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2019 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -37,54 +15,55 @@ * @{ */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.1. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ -/*! @brief DSPI dummy data if no Tx data.*/ -#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for tx if there is not txData. */ +#ifndef DSPI_DUMMY_DATA +/*! @brief DSPI dummy data if there is no Tx data.*/ +#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */ +#endif /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out Of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All status above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -101,12 +80,13 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in Modified Transfer Format. This field is valid - * only when CPHA bit in CTAR register is 0. + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid + * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point { @@ -130,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -165,36 +145,37 @@ typedef enum _dspi_clock_phase typedef enum _dspi_shift_direction { kDSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ - kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ + kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. + Shifting out of LSB is not supported for slave */ } dspi_shift_direction_t; /*! @brief DSPI delay type selection.*/ typedef enum _dspi_delay_type { kDSPI_PcsToSck = 1U, /*!< Pcs-to-SCK delay. */ - kDSPI_LastSckToPcs, /*!< Last SCK edge to Pcs delay. */ + kDSPI_LastSckToPcs, /*!< The last SCK edge to Pcs delay. */ kDSPI_BetweenTransfer /*!< Delay between transfers. */ } dspi_delay_type_t; /*! @brief DSPI Clock and Transfer Attributes Register (CTAR) selection.*/ typedef enum _dspi_ctar_selection { - kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode, note that CTAR0 and CTAR0_SLAVE are the + kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode; note that CTAR0 and CTAR0_SLAVE are the same register address. */ kDSPI_Ctar1 = 1U, /*!< CTAR1 selection option for master mode only. */ - kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only , note that some device do not support CTAR2. */ - kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only , note that some device do not support CTAR3. */ - kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only , note that some device do not support CTAR4. */ - kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only , note that some device do not support CTAR5. */ - kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only , note that some device do not support CTAR6. */ - kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only , note that some device do not support CTAR7. */ + kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only; note that some devices do not support CTAR2. */ + kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only; note that some devices do not support CTAR3. */ + kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only; note that some devices do not support CTAR4. */ + kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only; note that some devices do not support CTAR5. */ + kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only; note that some devices do not support CTAR6. */ + kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only; note that some devices do not support CTAR7. */ } dspi_ctar_selection_t; -#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro , internal used. */ -#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro , internal used. */ -#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro , internal used. */ -#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro , internal used. */ -/*! @brief Can use this enumeration for DSPI master transfer configFlags. */ +#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro; used internally. */ +#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro; used internally. */ +#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro; used internally. */ +#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI master transfer configFlags. */ enum _dspi_transfer_config_flag_for_master { kDSPI_MasterCtar0 = 0U << DSPI_MASTER_CTAR_SHIFT, /*!< DSPI master transfer use CTAR0 setting. */ @@ -213,13 +194,14 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Is PCS signal active after last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; -#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro , internal used. */ -#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro , internal used. */ -/*! @brief Can use this enum for DSPI slave transfer configFlags. */ +#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ +#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI slave transfer configFlags. */ enum _dspi_transfer_config_flag_for_slave { kDSPI_SlaveCtar0 = 0U << DSPI_SLAVE_CTAR_SHIFT, /*!< DSPI slave transfer use CTAR0 setting. */ @@ -234,15 +216,15 @@ enum _dspi_transfer_state kDSPI_Error /*!< Transfer error. */ }; -/*! @brief DSPI master command date configuration used for SPIx_PUSHR.*/ +/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ bool isEndOfQueue; /*!< Signals that the current transfer is the last in the queue.*/ - bool clearTransferCount; /*!< Clears SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ + bool clearTransferCount; /*!< Clears the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ } dspi_command_data_config_t; /*! @brief DSPI master ctar configuration structure.*/ @@ -254,33 +236,33 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time with nanosecond , set to 0 sets the minimum - delay. It sets the boundary value if out of range that can be set.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time with nanosecond , set to 0 sets the - minimum delay.It sets the boundary value if out of range that can be - set.*/ - uint32_t betweenTransferDelayInNanoSec; /*!< After SCK delay time with nanosecond , set to 0 sets the minimum - delay.It sets the boundary value if out of range that can be set.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ + + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ } dspi_master_ctar_config_t; /*! @brief DSPI master configuration structure.*/ typedef struct _dspi_master_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_master_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - dspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs). */ - dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low. */ + dspi_which_pcs_t whichPcs; /*!< The desired Peripheral Chip Select (pcs). */ + dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< The desired PCS active high or low. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable . Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_master_config_t; @@ -290,34 +272,34 @@ typedef struct _dspi_slave_ctar_config uint32_t bitsPerFrame; /*!< Bits per frame, minimum 4, maximum 16.*/ dspi_clock_polarity_t cpol; /*!< Clock polarity. */ dspi_clock_phase_t cpha; /*!< Clock phase. */ - /*!< Slave only supports MSB , does not support LSB.*/ + /*!< Slave only supports MSB and does not support LSB.*/ } dspi_slave_ctar_config_t; /*! @brief DSPI slave configuration structure.*/ typedef struct _dspi_slave_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_slave_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -352,47 +334,60 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags , set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ + volatile uint8_t state; /*!< DSPI transfer state, see _dspi_transfer_state.*/ dspi_master_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ }; -/*! @brief DSPI slave transfer handle structure used for transactional API. */ +/*! @brief DSPI slave transfer handle structure used for the transactional API. */ struct _dspi_slave_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ volatile uint8_t state; /*!< DSPI transfer state.*/ @@ -417,18 +412,18 @@ extern "C" { /*! * @brief Initializes the DSPI master. * - * This function initializes the DSPI master configuration. An example use case is as follows: + * This function initializes the DSPI master configuration. This is an example use case. * @code * dspi_master_config_t masterConfig; * masterConfig.whichCtar = kDSPI_Ctar0; - * masterConfig.ctarConfig.baudRate = 500000000; + * masterConfig.ctarConfig.baudRate = 500000000U; * masterConfig.ctarConfig.bitsPerFrame = 8; * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; - * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; * masterConfig.whichPcs = kDSPI_Pcs0; * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; * masterConfig.enableContinuousSCK = false; @@ -439,8 +434,8 @@ extern "C" { * @endcode * * @param base DSPI peripheral address. - * @param masterConfig Pointer to structure dspi_master_config_t. - * @param srcClock_Hz Module source input clock in Hertz + * @param masterConfig Pointer to the structure dspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz. */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz); @@ -448,8 +443,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u * @brief Sets the dspi_master_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). - * User may use the initialized structure unchanged in DSPI_MasterInit() or modify the structure - * before calling DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). * Example: * @code * dspi_master_config_t masterConfig; @@ -462,7 +457,7 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); /*! * @brief DSPI slave configuration. * - * This function initializes the DSPI slave configuration. An example use case is as follows: + * This function initializes the DSPI slave configuration. This is an example use case. * @code * dspi_slave_config_t slaveConfig; * slaveConfig->whichCtar = kDSPI_Ctar0; @@ -477,22 +472,22 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); * @endcode * * @param base DSPI peripheral address. - * @param slaveConfig Pointer to structure dspi_master_config_t. + * @param slaveConfig Pointer to the structure dspi_master_config_t. */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig); /*! - * @brief Sets the dspi_slave_config_t structure to default values. + * @brief Sets the dspi_slave_config_t structure to a default value. * * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). - * User may use the initialized structure unchanged in DSPI_SlaveInit(), or modify the structure - * before calling DSPI_SlaveInit(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. * @code * dspi_slave_config_t slaveConfig; * DSPI_SlaveGetDefaultConfig(&slaveConfig); * @endcode - * @param slaveConfig pointer to dspi_slave_config_t structure. + * @param slaveConfig Pointer to the dspi_slave_config_t structure. */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig); @@ -506,7 +501,7 @@ void DSPI_Deinit(SPI_Type *base); * @brief Enables the DSPI peripheral and sets the MCR MDIS to 0. * * @param base DSPI peripheral address. - * @param enable pass true to enable module, false to disable module. + * @param enable Pass true to enable module, false to disable module. */ static inline void DSPI_Enable(SPI_Type *base, bool enable) { @@ -522,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -532,7 +527,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! * @brief Gets the DSPI status flag state. * @param base DSPI peripheral address. - * @return The DSPI status(in SR register). + * @return DSPI status (in SR register). */ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) { @@ -545,13 +540,13 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the * desired status bit to clear. The list of status bits is defined in the dspi_status_and_interrupt_request_t. The * function uses these bit positions in its algorithm to clear the desired flag state. - * Example usage: + * This is an example. * @code * DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag); * @endcode * * @param base DSPI peripheral address. - * @param statusFlags The status flag , used from type dspi_flags. + * @param statusFlags The status flag used from the type dspi_flags. */ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) { @@ -560,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -570,15 +565,16 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! * @brief Enables the DSPI interrupts. * - * This function configures the various interrupt masks of the DSPI. The parameters are base and an interrupt mask. + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); @@ -590,7 +586,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) { @@ -599,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -609,13 +605,13 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! * @brief Enables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * DSPI_EnableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) { @@ -625,13 +621,13 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) /*! * @brief Disables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * SPI_DisableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask) { @@ -679,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -705,12 +707,19 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. * - * This function sets the module to begin data transfer in either master or slave mode. + * This function sets the module to start data transfer in either master or slave mode. * * @param base DSPI peripheral address. */ @@ -719,9 +728,9 @@ static inline void DSPI_StartTransfer(SPI_Type *base) base->MCR &= ~SPI_MCR_HALT_MASK; } /*! - * @brief Stops (halts) DSPI transfers and sets HALT bit in MCR. + * @brief Stops DSPI transfers and sets the HALT bit in MCR. * - * This function stops data transfers in either master or slave mode. + * This function stops data transfers in either master or slave modes. * * @param base DSPI peripheral address. */ @@ -731,44 +740,44 @@ static inline void DSPI_StopTransfer(SPI_Type *base) } /*! - * @brief Enables (or disables) the DSPI FIFOs. + * @brief Enables or disables the DSPI FIFOs. * - * This function allows the caller to disable/enable the Tx and Rx FIFOs (independently). - * Note that to disable, the caller must pass in a logic 0 (false) for the particular FIFO configuration. To enable, - * the caller must pass in a logic 1 (true). + * This function allows the caller to disable/enable the Tx and Rx FIFOs independently. + * Note that to disable, pass in a logic 0 (false) for the particular FIFO configuration. To enable, + * pass in a logic 1 (true). * * @param base DSPI peripheral address. - * @param enableTxFifo Disables (false) the TX FIFO, else enables (true) the TX FIFO - * @param enableRxFifo Disables (false) the RX FIFO, else enables (true) the RX FIFO + * @param enableTxFifo Disables (false) the TX FIFO; Otherwise, enables (true) the TX FIFO + * @param enableRxFifo Disables (false) the RX FIFO; Otherwise, enables (true) the RX FIFO */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! * @brief Flushes the DSPI FIFOs. * * @param base DSPI peripheral address. - * @param flushTxFifo Flushes (true) the Tx FIFO, else do not flush (false) the Tx FIFO - * @param flushRxFifo Flushes (true) the Rx FIFO, else do not flush (false) the Rx FIFO + * @param flushTxFifo Flushes (true) the Tx FIFO; Otherwise, does not flush (false) the Tx FIFO + * @param flushRxFifo Flushes (true) the Rx FIFO; Otherwise, does not flush (false) the Rx FIFO */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! * @brief Configures the DSPI peripheral chip select polarity simultaneously. - * For example, PCS0 and PCS1 set to active low and other PCS set to active high. Note that the number of + * For example, PCS0 and PCS1 are set to active low and other PCS is set to active high. Note that the number of * PCSs is specific to the device. * @code * DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow); @endcode * @param base DSPI peripheral address. - * @param mask The PCS polarity mask , can use the enum _dspi_pcs_polarity. + * @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity. */ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask) { @@ -797,19 +806,19 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, * @brief Manually configures the delay prescaler and scaler for a particular CTAR. * * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar - * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT)and scalar (DT). + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes the delay to configure along with the prescaler and scaler value. - * This allows the user to directly set the prescaler/scaler values if they have pre-calculated them or if they simply - * wish to manually increment either value. + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. * * @param base DSPI peripheral address. * @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. * @param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). * @param scaler The scaler delay value (can be any integer between 0 to 15). - * @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * @param whichDelay The desired delay to configure; must be of type dspi_delay_type_t */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay); @@ -817,15 +826,15 @@ void DSPI_MasterSetDelayScaler( /*! * @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. * - * This function calculates the values for: + * This function calculates the values for the following. * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or * After SCK delay pre-scalar (PASC) and scalar (ASC), or - * Delay after transfer pre-scalar (PDT)and scalar (DT). + * Delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes which delay they want to configure along with the desired delay value in nanoseconds. The function - * calculates the values needed for the prescaler and scaler and returning the actual calculated delay as an exact + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact * delay match may not be possible. In this case, the closest match is calculated without going below the desired * delay value input. * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum @@ -849,11 +858,11 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, * @brief Writes data into the data buffer for master mode. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_data_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -865,7 +874,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, @endcode * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) @@ -879,14 +888,14 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config * @brief Sets the dspi_command_data_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). - * User may use the initialized structure unchanged in DSPI_MasterWrite_xx() or modify the structure - * before calling DSPI_MasterWrite_xx(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. * @code * dspi_command_data_config_t command; * DSPI_GetDefaultDataCommandConfig(&command); * @endcode - * @param command pointer to dspi_command_data_config_t structure. + * @param command Pointer to the dspi_command_data_config_t structure. */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); @@ -894,11 +903,11 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * @brief Writes data into the data buffer master mode and waits till complete to return. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -911,10 +920,10 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, - * receive data is available when transmit completes. + * the received data is available when the transmit completes. * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data); @@ -929,10 +938,10 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co * improve performance in cases where the command structure is constant. For example, the user calls this function * before starting a transfer to generate the command word. When they are ready to transmit the data, they OR * this formatted command word with the desired data to transmit. This process increases transmit performance when - * compared to calling send functions such as DSPI_HAL_WriteDataMastermode which format the command word each time a + * compared to calling send functions, such as DSPI_HAL_WriteDataMastermode, which format the command word each time a * data word is to be sent. * - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @return The command word formatted to the PUSHR data register bit field. */ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t *command) @@ -945,43 +954,44 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t /*! * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data - * buffer, master mode and waits till complete to return. + * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command info then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word * as the data to send. - * The command portion provides characteristics of the data such as the optional continuous chip select operation -* between - * transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: * @code * dataWord = <16-bit command> | <16-bit data>; - * DSPI_HAL_WriteCommandDataMastermodeBlocking(base, dataWord); + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); * @endcode * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). - * Because the SPI is a synchronous protocol, the receive data is available when transmit completes. + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. - * @param data The data word (command and data combined) to be sent + * @param data The data word (command and data combined) to be sent. */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data); @@ -1020,9 +1030,17 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} -*/ + */ /*! * @name Transactional @@ -1033,13 +1051,13 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) /*! * @brief Initializes the DSPI master handle. * - * This function initializes the DSPI handle which can be used for other DSPI transactional APIs. Usually, for a + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_handle_t. - * @param callback dspi callback. - * @param userData callback function parameter. + * @param callback DSPI callback. + * @param userData Callback function parameter. */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, @@ -1049,12 +1067,11 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, /*! * @brief DSPI master transfer data using polling. * - * This function transfers data with polling. This is a blocking function, which does not return until all transfers - * have been - * completed. + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. * * @param base DSPI peripheral base address. - * @param transfer pointer to dspi_transfer_t structure. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); @@ -1063,35 +1080,63 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); * @brief DSPI master transfer data using interrupts. * * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all - data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * * This function gets the master transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count); /*! - * @brief DSPI master aborts transfer using an interrupt. + * @brief DSPI master aborts a transfer using an interrupt. * * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); @@ -1101,7 +1146,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); @@ -1111,10 +1156,10 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * @param handle DSPI handle pointer to dspi_slave_handle_t. + * @param handle DSPI handle pointer to the dspi_slave_handle_t. * @param base DSPI peripheral base address. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData Callback function parameter. */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, @@ -1125,12 +1170,11 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, * @brief DSPI slave transfers data using an interrupt. * * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all - * data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer); @@ -1141,8 +1185,8 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand * This function gets the slave transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count); @@ -1150,10 +1194,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, /*! * @brief DSPI slave aborts a transfer using an interrupt. * - * This function aborts transfer using an interrupt. + * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); @@ -1163,19 +1207,29 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.c index a1c20027b2..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* 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. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ #include "fsl_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,46 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -101,51 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); +#if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) + assert(NULL != edmaTxDataToIntermediaryHandle); +#endif + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + handle->state = (uint8_t)kDSPI_Busy; + + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -154,33 +170,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - - handle->state = kDSPI_Busy; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -188,98 +204,123 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - /* this limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (handle->bitsPerFrame > 8) + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (transfer->dataSize > 1022) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) + { + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_InvalidArgument; + } + + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) - { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } - } - else - { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - } - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - } - else /* For all words except the last word , frame > 8bits */ - { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; + } + else + { + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); + } + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; + } + else /* For all words except the last word , frame > 8bits */ + { + if (NULL != handle->txData) + { + wordToSend = *(handle->txData); + ++handle->txData; /* increment to next data byte */ + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -289,9 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -301,66 +343,57 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /*dspi has shared dma request*/ - { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -368,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -380,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -390,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -405,125 +439,66 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); - /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should - write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the - SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ - EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - - if (handle->remainingSendByteCount > 0) + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*Calculate the last data : handle->lastCommand*/ + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) - { - transferConfigB.srcAddr = (uint32_t)(handle->txData); - transferConfigB.srcOffset = 1; - } - else - { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigB.srcOffset = 0; - } - - transferConfigB.destAddr = (uint32_t)(&handle->command); - transferConfigB.destOffset = 0; - - transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; - - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; - } - } - else - { - transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; - } - } - - EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); - } - - /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to - handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -531,85 +506,345 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - if (handle->isThereExtraByte) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 2] | - ((uint32_t)dummyData << 8); - } - else - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; - } + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } } +/* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO, + * allowing a single write to the command word followed by multiple writes to the transmit word. + * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the + * transmit word into a 32-bit write that pushes both the command word and transmit word into + * the TX FIFO (PUSH TX FIFO Register In Master Mode) + * So, if this feature is supported, we can use use one channel to carry the receive data from + * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer + * to transmit register,and use the scatter/gather function to prepare the last data. + * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data. + */ +#if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET + /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to PUSHR register. + */ + + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + /*User_Send_Buffer(txData) to PUSHR register. */ + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); - transferConfigC.destAddr = (uint32_t)txAddr; - - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (handle->txData) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /* For DSPI with separate RX and TX DMA requests, one frame data has been carry + * to handle->command, so need to reduce the pointer of txData. + */ + transferConfigB.srcAddr = + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); + transferConfigB.srcOffset = 1; + } + else + { + /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry + * to PUSHR register, so no need to change the pointer of txData. + */ + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcOffset = 1; + } } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD); + } + /* If only one word to transmit, only carry the lastcommand. */ + else + { + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL); + } + + /*Start the EDMA channel_A , channel_C. */ + EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); + EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); + + /* Set the channel link. + * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the + * receive register, and then carry transmit data to PUSHER register. + * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link. + */ + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /*Set channel priority*/ + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; + uint8_t t = 0; + + if (channelPriorityLow > channelPriorityHigh) + { + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; + channelPriorityHigh = t; + } + + edma_channel_Preemption_config_t preemption_config_t; + preemption_config_t.enableChannelPreemption = true; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; + + EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + &preemption_config_t); + + preemption_config_t.channelPriority = channelPriorityHigh; + EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to + channelC to carry the next data to PUSHER register.(txData to PUSHER) */ + if (handle->remainingSendByteCount > 0U) + { + EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); + } + } + + DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + + /* Setup control info to PUSHER register. */ + *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U); +#else + + /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should + write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the + SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + if (NULL != handle->txData) + { + transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcOffset = 1; + } + else + { + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + majorlink , the majorlink would not trigger the channel_C*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; + } + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; + } + } + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to + handle the last data */ + + edma_transfer_config_t transferConfigC; + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) + { + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.destAddr = (uint32_t)txAddr; + + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); + } + else + { + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -618,165 +853,233 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ - if (handle->remainingSendByteCount > 1) + to prepare the next 32bits data (txData to handle->command) */ + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->isThereExtraByte) - { - EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); - } - EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } - +#endif DSPI_StartTransfer(base); return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -784,13 +1087,33 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -798,14 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -815,88 +1140,99 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU)); + handle->state = (uint8_t)kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } - if ((handle->bitsPerFrame > 8) && (transfer->dataSize < 2)) + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; - handle->errorCount = 0; + handle->totalByteCount = transfer->dataSize; - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } - - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -907,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -919,42 +1255,36 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ - if ((handle->remainingSendByteCount == 2) && (handle->isThereExtraByte)) - { - wordToSend |= (unsigned)(dummyData) << 8U; - ++handle->txData; /* Increment to next data byte */ - } - else - { - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - ++handle->txData; /* Increment to next data byte */ - } + + wordToSend |= (unsigned)(*(handle->txData)) << 8U; + ++handle->txData; /* Increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -962,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -978,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -994,179 +1325,132 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - /*If there is extra byte , it would use the */ - if (handle->isThereExtraByte) - { - if (handle->txData) - { - handle->txLastData = - handle->txData[handle->remainingSendByteCount - 2] | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - else - { - handle->txLastData = DSPI_DUMMY_DATA | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - transferConfigC.srcAddr = (uint32_t)(&(handle->txLastData)); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destOffset = 0; - EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); - } - - /*Set another transferConfigC*/ - if ((handle->isThereExtraByte) && (handle->remainingSendByteCount == 2)) + if (NULL != handle->txData) { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcOffset = 1; } else { - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.destOffset = 0; - - if (handle->txData) + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcOffset = 0; + if (handle->bitsPerFrame <= 8U) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); - transferConfigC.srcOffset = 1; + handle->txBuffIfNull = dummyData; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) - { - handle->txBuffIfNull = DSPI_DUMMY_DATA; - } - else - { - handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - } + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } - - transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; - } - else - { - transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - if (handle->isThereExtraByte) - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; - } - } - - if (handle->isThereExtraByte) - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, softwareTCD); - EDMA_EnableAutoStopRequest(handle->edmaTxDataToTxRegHandle->base, - handle->edmaTxDataToTxRegHandle->channel, false); - } - else - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); - } - - EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } + + transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + } + else + { + transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; + } + + EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + + EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1176,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1196,58 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1255,7 +1548,8 @@ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.h index 643efadca4..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -37,28 +15,33 @@ * @{ */ - /*********************************************************************************************************************** * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI master. + * @param handle A pointer to the handle for the DSPI master. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, dspi_master_edma_handle_t *handle, @@ -68,38 +51,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI slave. + * @param handle A pointer to the handle for the DSPI slave. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData); -/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */ +/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */ struct _dspi_master_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/ + + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ - dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ @@ -110,33 +94,30 @@ struct _dspi_master_edma_handle edma_tcd_t dspiSoftwareTCD[2]; /*!whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -173,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -185,48 +229,92 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; - masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + assert(NULL != masterConfig); - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; + masterConfig->ctarConfig.bitsPerFrame = 8; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { + assert(NULL != slaveConfig); + uint32_t temp = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -239,40 +327,66 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - slaveConfig->whichCtar = kDSPI_Ctar0; - slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + assert(NULL != slaveConfig); - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; + slaveConfig->ctarConfig.bitsPerFrame = 8; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); DSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* disable DSPI clock */ CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh) @@ -293,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -312,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -378,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -402,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -424,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -455,83 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + assert(NULL != command); + + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + assert(NULL != command); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + /* First, clear Transmit Complete Flag (TCF) */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); + + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -540,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -556,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -574,45 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -621,34 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -660,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -701,54 +1013,39 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; + if (rxData != NULL) + { + *(rxData) = (uint8_t)DSPI_ReadData(base); + rxData++; + } + else + { + (void)DSPI_ReadData(base); + } + remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) - { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -756,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -769,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -822,24 +1120,28 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; + wordReceived = (uint16_t)DSPI_ReadData(base); - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + if (rxData != NULL) + { + *rxData = (uint8_t)wordReceived; + ++rxData; + *rxData = (uint8_t)(wordReceived >> 8U); + ++rxData; + } + remainingReceiveByteCount -= 2U; + + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -850,28 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - dspi_command_data_config_t commandStruct; + assert(NULL != handle); + assert(NULL != transfer); + + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -879,61 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); - - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - - DSPI_MasterTransferFillUpTxFifo(base, handle); /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -945,11 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -958,40 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + assert(NULL != handle); + + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -999,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1007,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1023,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1058,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1068,82 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1152,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1180,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1212,85 +1736,107 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); + + s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; + + /* Enable RX FIFO drain request, the slave only use this interrupt */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + + if (NULL != handle->rxData) + { + /* RX FIFO overflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); + } + if (NULL != handle->txData) + { + /* TX FIFO underflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); + } DSPI_StartTransfer(base); /* Prepare data to transmit */ DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; - - /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); - - if (handle->rxData) - { - /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); - } - if (handle->txData) - { - /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); - } - return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1302,22 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1335,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1382,24 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1408,65 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - if (handle->callback) + handle->state = (uint8_t)kDSPI_Idle; + + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - uint8_t dummyPattern = DSPI_DUMMY_DATA; + assert(NULL != handle); + + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1484,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1500,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1573,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1606,52 +2188,57 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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 (FSL_FEATURE_SOC_DSPI_COUNT > 0) +#if defined(SPI0) void SPI0_DriverIRQHandler(void) { - assert(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 1) +#if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 2) +#if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 3) +#if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 4) +#if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 5) +#if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi.h index dfbeb3e457..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2019 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -37,54 +15,55 @@ * @{ */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.1. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ -/*! @brief DSPI dummy data if no Tx data.*/ -#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for tx if there is not txData. */ +#ifndef DSPI_DUMMY_DATA +/*! @brief DSPI dummy data if there is no Tx data.*/ +#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */ +#endif /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out Of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All status above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -101,12 +80,13 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in Modified Transfer Format. This field is valid - * only when CPHA bit in CTAR register is 0. + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid + * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point { @@ -130,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -165,36 +145,37 @@ typedef enum _dspi_clock_phase typedef enum _dspi_shift_direction { kDSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ - kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ + kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. + Shifting out of LSB is not supported for slave */ } dspi_shift_direction_t; /*! @brief DSPI delay type selection.*/ typedef enum _dspi_delay_type { kDSPI_PcsToSck = 1U, /*!< Pcs-to-SCK delay. */ - kDSPI_LastSckToPcs, /*!< Last SCK edge to Pcs delay. */ + kDSPI_LastSckToPcs, /*!< The last SCK edge to Pcs delay. */ kDSPI_BetweenTransfer /*!< Delay between transfers. */ } dspi_delay_type_t; /*! @brief DSPI Clock and Transfer Attributes Register (CTAR) selection.*/ typedef enum _dspi_ctar_selection { - kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode, note that CTAR0 and CTAR0_SLAVE are the + kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode; note that CTAR0 and CTAR0_SLAVE are the same register address. */ kDSPI_Ctar1 = 1U, /*!< CTAR1 selection option for master mode only. */ - kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only , note that some device do not support CTAR2. */ - kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only , note that some device do not support CTAR3. */ - kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only , note that some device do not support CTAR4. */ - kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only , note that some device do not support CTAR5. */ - kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only , note that some device do not support CTAR6. */ - kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only , note that some device do not support CTAR7. */ + kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only; note that some devices do not support CTAR2. */ + kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only; note that some devices do not support CTAR3. */ + kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only; note that some devices do not support CTAR4. */ + kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only; note that some devices do not support CTAR5. */ + kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only; note that some devices do not support CTAR6. */ + kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only; note that some devices do not support CTAR7. */ } dspi_ctar_selection_t; -#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro , internal used. */ -#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro , internal used. */ -#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro , internal used. */ -#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro , internal used. */ -/*! @brief Can use this enumeration for DSPI master transfer configFlags. */ +#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro; used internally. */ +#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro; used internally. */ +#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro; used internally. */ +#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI master transfer configFlags. */ enum _dspi_transfer_config_flag_for_master { kDSPI_MasterCtar0 = 0U << DSPI_MASTER_CTAR_SHIFT, /*!< DSPI master transfer use CTAR0 setting. */ @@ -213,13 +194,14 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Is PCS signal active after last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; -#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro , internal used. */ -#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro , internal used. */ -/*! @brief Can use this enum for DSPI slave transfer configFlags. */ +#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ +#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI slave transfer configFlags. */ enum _dspi_transfer_config_flag_for_slave { kDSPI_SlaveCtar0 = 0U << DSPI_SLAVE_CTAR_SHIFT, /*!< DSPI slave transfer use CTAR0 setting. */ @@ -234,15 +216,15 @@ enum _dspi_transfer_state kDSPI_Error /*!< Transfer error. */ }; -/*! @brief DSPI master command date configuration used for SPIx_PUSHR.*/ +/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ bool isEndOfQueue; /*!< Signals that the current transfer is the last in the queue.*/ - bool clearTransferCount; /*!< Clears SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ + bool clearTransferCount; /*!< Clears the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ } dspi_command_data_config_t; /*! @brief DSPI master ctar configuration structure.*/ @@ -254,33 +236,33 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time with nanosecond , set to 0 sets the minimum - delay. It sets the boundary value if out of range that can be set.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time with nanosecond , set to 0 sets the - minimum delay.It sets the boundary value if out of range that can be - set.*/ - uint32_t betweenTransferDelayInNanoSec; /*!< After SCK delay time with nanosecond , set to 0 sets the minimum - delay.It sets the boundary value if out of range that can be set.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ + + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ } dspi_master_ctar_config_t; /*! @brief DSPI master configuration structure.*/ typedef struct _dspi_master_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_master_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - dspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs). */ - dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low. */ + dspi_which_pcs_t whichPcs; /*!< The desired Peripheral Chip Select (pcs). */ + dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< The desired PCS active high or low. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable . Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_master_config_t; @@ -290,34 +272,34 @@ typedef struct _dspi_slave_ctar_config uint32_t bitsPerFrame; /*!< Bits per frame, minimum 4, maximum 16.*/ dspi_clock_polarity_t cpol; /*!< Clock polarity. */ dspi_clock_phase_t cpha; /*!< Clock phase. */ - /*!< Slave only supports MSB , does not support LSB.*/ + /*!< Slave only supports MSB and does not support LSB.*/ } dspi_slave_ctar_config_t; /*! @brief DSPI slave configuration structure.*/ typedef struct _dspi_slave_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_slave_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -352,47 +334,60 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags , set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ + volatile uint8_t state; /*!< DSPI transfer state, see _dspi_transfer_state.*/ dspi_master_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ }; -/*! @brief DSPI slave transfer handle structure used for transactional API. */ +/*! @brief DSPI slave transfer handle structure used for the transactional API. */ struct _dspi_slave_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ volatile uint8_t state; /*!< DSPI transfer state.*/ @@ -417,18 +412,18 @@ extern "C" { /*! * @brief Initializes the DSPI master. * - * This function initializes the DSPI master configuration. An example use case is as follows: + * This function initializes the DSPI master configuration. This is an example use case. * @code * dspi_master_config_t masterConfig; * masterConfig.whichCtar = kDSPI_Ctar0; - * masterConfig.ctarConfig.baudRate = 500000000; + * masterConfig.ctarConfig.baudRate = 500000000U; * masterConfig.ctarConfig.bitsPerFrame = 8; * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; - * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; * masterConfig.whichPcs = kDSPI_Pcs0; * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; * masterConfig.enableContinuousSCK = false; @@ -439,8 +434,8 @@ extern "C" { * @endcode * * @param base DSPI peripheral address. - * @param masterConfig Pointer to structure dspi_master_config_t. - * @param srcClock_Hz Module source input clock in Hertz + * @param masterConfig Pointer to the structure dspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz. */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz); @@ -448,8 +443,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u * @brief Sets the dspi_master_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). - * User may use the initialized structure unchanged in DSPI_MasterInit() or modify the structure - * before calling DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). * Example: * @code * dspi_master_config_t masterConfig; @@ -462,7 +457,7 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); /*! * @brief DSPI slave configuration. * - * This function initializes the DSPI slave configuration. An example use case is as follows: + * This function initializes the DSPI slave configuration. This is an example use case. * @code * dspi_slave_config_t slaveConfig; * slaveConfig->whichCtar = kDSPI_Ctar0; @@ -477,22 +472,22 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); * @endcode * * @param base DSPI peripheral address. - * @param slaveConfig Pointer to structure dspi_master_config_t. + * @param slaveConfig Pointer to the structure dspi_master_config_t. */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig); /*! - * @brief Sets the dspi_slave_config_t structure to default values. + * @brief Sets the dspi_slave_config_t structure to a default value. * * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). - * User may use the initialized structure unchanged in DSPI_SlaveInit(), or modify the structure - * before calling DSPI_SlaveInit(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. * @code * dspi_slave_config_t slaveConfig; * DSPI_SlaveGetDefaultConfig(&slaveConfig); * @endcode - * @param slaveConfig pointer to dspi_slave_config_t structure. + * @param slaveConfig Pointer to the dspi_slave_config_t structure. */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig); @@ -506,7 +501,7 @@ void DSPI_Deinit(SPI_Type *base); * @brief Enables the DSPI peripheral and sets the MCR MDIS to 0. * * @param base DSPI peripheral address. - * @param enable pass true to enable module, false to disable module. + * @param enable Pass true to enable module, false to disable module. */ static inline void DSPI_Enable(SPI_Type *base, bool enable) { @@ -522,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -532,7 +527,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! * @brief Gets the DSPI status flag state. * @param base DSPI peripheral address. - * @return The DSPI status(in SR register). + * @return DSPI status (in SR register). */ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) { @@ -545,13 +540,13 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the * desired status bit to clear. The list of status bits is defined in the dspi_status_and_interrupt_request_t. The * function uses these bit positions in its algorithm to clear the desired flag state. - * Example usage: + * This is an example. * @code * DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag); * @endcode * * @param base DSPI peripheral address. - * @param statusFlags The status flag , used from type dspi_flags. + * @param statusFlags The status flag used from the type dspi_flags. */ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) { @@ -560,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -570,15 +565,16 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! * @brief Enables the DSPI interrupts. * - * This function configures the various interrupt masks of the DSPI. The parameters are base and an interrupt mask. + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); @@ -590,7 +586,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) { @@ -599,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -609,13 +605,13 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! * @brief Enables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * DSPI_EnableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) { @@ -625,13 +621,13 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) /*! * @brief Disables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * SPI_DisableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask) { @@ -679,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -705,12 +707,19 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. * - * This function sets the module to begin data transfer in either master or slave mode. + * This function sets the module to start data transfer in either master or slave mode. * * @param base DSPI peripheral address. */ @@ -719,9 +728,9 @@ static inline void DSPI_StartTransfer(SPI_Type *base) base->MCR &= ~SPI_MCR_HALT_MASK; } /*! - * @brief Stops (halts) DSPI transfers and sets HALT bit in MCR. + * @brief Stops DSPI transfers and sets the HALT bit in MCR. * - * This function stops data transfers in either master or slave mode. + * This function stops data transfers in either master or slave modes. * * @param base DSPI peripheral address. */ @@ -731,44 +740,44 @@ static inline void DSPI_StopTransfer(SPI_Type *base) } /*! - * @brief Enables (or disables) the DSPI FIFOs. + * @brief Enables or disables the DSPI FIFOs. * - * This function allows the caller to disable/enable the Tx and Rx FIFOs (independently). - * Note that to disable, the caller must pass in a logic 0 (false) for the particular FIFO configuration. To enable, - * the caller must pass in a logic 1 (true). + * This function allows the caller to disable/enable the Tx and Rx FIFOs independently. + * Note that to disable, pass in a logic 0 (false) for the particular FIFO configuration. To enable, + * pass in a logic 1 (true). * * @param base DSPI peripheral address. - * @param enableTxFifo Disables (false) the TX FIFO, else enables (true) the TX FIFO - * @param enableRxFifo Disables (false) the RX FIFO, else enables (true) the RX FIFO + * @param enableTxFifo Disables (false) the TX FIFO; Otherwise, enables (true) the TX FIFO + * @param enableRxFifo Disables (false) the RX FIFO; Otherwise, enables (true) the RX FIFO */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! * @brief Flushes the DSPI FIFOs. * * @param base DSPI peripheral address. - * @param flushTxFifo Flushes (true) the Tx FIFO, else do not flush (false) the Tx FIFO - * @param flushRxFifo Flushes (true) the Rx FIFO, else do not flush (false) the Rx FIFO + * @param flushTxFifo Flushes (true) the Tx FIFO; Otherwise, does not flush (false) the Tx FIFO + * @param flushRxFifo Flushes (true) the Rx FIFO; Otherwise, does not flush (false) the Rx FIFO */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! * @brief Configures the DSPI peripheral chip select polarity simultaneously. - * For example, PCS0 and PCS1 set to active low and other PCS set to active high. Note that the number of + * For example, PCS0 and PCS1 are set to active low and other PCS is set to active high. Note that the number of * PCSs is specific to the device. * @code * DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow); @endcode * @param base DSPI peripheral address. - * @param mask The PCS polarity mask , can use the enum _dspi_pcs_polarity. + * @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity. */ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask) { @@ -797,19 +806,19 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, * @brief Manually configures the delay prescaler and scaler for a particular CTAR. * * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar - * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT)and scalar (DT). + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes the delay to configure along with the prescaler and scaler value. - * This allows the user to directly set the prescaler/scaler values if they have pre-calculated them or if they simply - * wish to manually increment either value. + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. * * @param base DSPI peripheral address. * @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. * @param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). * @param scaler The scaler delay value (can be any integer between 0 to 15). - * @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * @param whichDelay The desired delay to configure; must be of type dspi_delay_type_t */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay); @@ -817,15 +826,15 @@ void DSPI_MasterSetDelayScaler( /*! * @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. * - * This function calculates the values for: + * This function calculates the values for the following. * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or * After SCK delay pre-scalar (PASC) and scalar (ASC), or - * Delay after transfer pre-scalar (PDT)and scalar (DT). + * Delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes which delay they want to configure along with the desired delay value in nanoseconds. The function - * calculates the values needed for the prescaler and scaler and returning the actual calculated delay as an exact + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact * delay match may not be possible. In this case, the closest match is calculated without going below the desired * delay value input. * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum @@ -849,11 +858,11 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, * @brief Writes data into the data buffer for master mode. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_data_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -865,7 +874,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, @endcode * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) @@ -879,14 +888,14 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config * @brief Sets the dspi_command_data_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). - * User may use the initialized structure unchanged in DSPI_MasterWrite_xx() or modify the structure - * before calling DSPI_MasterWrite_xx(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. * @code * dspi_command_data_config_t command; * DSPI_GetDefaultDataCommandConfig(&command); * @endcode - * @param command pointer to dspi_command_data_config_t structure. + * @param command Pointer to the dspi_command_data_config_t structure. */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); @@ -894,11 +903,11 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * @brief Writes data into the data buffer master mode and waits till complete to return. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -911,10 +920,10 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, - * receive data is available when transmit completes. + * the received data is available when the transmit completes. * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data); @@ -929,10 +938,10 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co * improve performance in cases where the command structure is constant. For example, the user calls this function * before starting a transfer to generate the command word. When they are ready to transmit the data, they OR * this formatted command word with the desired data to transmit. This process increases transmit performance when - * compared to calling send functions such as DSPI_HAL_WriteDataMastermode which format the command word each time a + * compared to calling send functions, such as DSPI_HAL_WriteDataMastermode, which format the command word each time a * data word is to be sent. * - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @return The command word formatted to the PUSHR data register bit field. */ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t *command) @@ -945,43 +954,44 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t /*! * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data - * buffer, master mode and waits till complete to return. + * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command info then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word * as the data to send. - * The command portion provides characteristics of the data such as the optional continuous chip select operation -* between - * transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: * @code * dataWord = <16-bit command> | <16-bit data>; - * DSPI_HAL_WriteCommandDataMastermodeBlocking(base, dataWord); + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); * @endcode * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). - * Because the SPI is a synchronous protocol, the receive data is available when transmit completes. + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. - * @param data The data word (command and data combined) to be sent + * @param data The data word (command and data combined) to be sent. */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data); @@ -1020,9 +1030,17 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} -*/ + */ /*! * @name Transactional @@ -1033,13 +1051,13 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) /*! * @brief Initializes the DSPI master handle. * - * This function initializes the DSPI handle which can be used for other DSPI transactional APIs. Usually, for a + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_handle_t. - * @param callback dspi callback. - * @param userData callback function parameter. + * @param callback DSPI callback. + * @param userData Callback function parameter. */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, @@ -1049,12 +1067,11 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, /*! * @brief DSPI master transfer data using polling. * - * This function transfers data with polling. This is a blocking function, which does not return until all transfers - * have been - * completed. + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. * * @param base DSPI peripheral base address. - * @param transfer pointer to dspi_transfer_t structure. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); @@ -1063,35 +1080,63 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); * @brief DSPI master transfer data using interrupts. * * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all - data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * * This function gets the master transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count); /*! - * @brief DSPI master aborts transfer using an interrupt. + * @brief DSPI master aborts a transfer using an interrupt. * * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); @@ -1101,7 +1146,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); @@ -1111,10 +1156,10 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * @param handle DSPI handle pointer to dspi_slave_handle_t. + * @param handle DSPI handle pointer to the dspi_slave_handle_t. * @param base DSPI peripheral base address. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData Callback function parameter. */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, @@ -1125,12 +1170,11 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, * @brief DSPI slave transfers data using an interrupt. * * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all - * data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer); @@ -1141,8 +1185,8 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand * This function gets the slave transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count); @@ -1150,10 +1194,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, /*! * @brief DSPI slave aborts a transfer using an interrupt. * - * This function aborts transfer using an interrupt. + * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); @@ -1163,19 +1207,29 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.c index a1c20027b2..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* 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. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ #include "fsl_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,46 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -101,51 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); +#if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) + assert(NULL != edmaTxDataToIntermediaryHandle); +#endif + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + handle->state = (uint8_t)kDSPI_Busy; + + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -154,33 +170,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - - handle->state = kDSPI_Busy; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -188,98 +204,123 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - /* this limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (handle->bitsPerFrame > 8) + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (transfer->dataSize > 1022) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) + { + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_InvalidArgument; + } + + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) - { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } - } - else - { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - } - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - } - else /* For all words except the last word , frame > 8bits */ - { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; + } + else + { + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); + } + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; + } + else /* For all words except the last word , frame > 8bits */ + { + if (NULL != handle->txData) + { + wordToSend = *(handle->txData); + ++handle->txData; /* increment to next data byte */ + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -289,9 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -301,66 +343,57 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /*dspi has shared dma request*/ - { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -368,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -380,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -390,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -405,125 +439,66 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); - /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should - write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the - SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ - EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - - if (handle->remainingSendByteCount > 0) + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*Calculate the last data : handle->lastCommand*/ + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) - { - transferConfigB.srcAddr = (uint32_t)(handle->txData); - transferConfigB.srcOffset = 1; - } - else - { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigB.srcOffset = 0; - } - - transferConfigB.destAddr = (uint32_t)(&handle->command); - transferConfigB.destOffset = 0; - - transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; - - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; - } - } - else - { - transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; - } - } - - EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); - } - - /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to - handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -531,85 +506,345 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - if (handle->isThereExtraByte) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 2] | - ((uint32_t)dummyData << 8); - } - else - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; - } + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } } +/* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO, + * allowing a single write to the command word followed by multiple writes to the transmit word. + * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the + * transmit word into a 32-bit write that pushes both the command word and transmit word into + * the TX FIFO (PUSH TX FIFO Register In Master Mode) + * So, if this feature is supported, we can use use one channel to carry the receive data from + * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer + * to transmit register,and use the scatter/gather function to prepare the last data. + * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data. + */ +#if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET + /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to PUSHR register. + */ + + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + /*User_Send_Buffer(txData) to PUSHR register. */ + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); - transferConfigC.destAddr = (uint32_t)txAddr; - - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (handle->txData) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /* For DSPI with separate RX and TX DMA requests, one frame data has been carry + * to handle->command, so need to reduce the pointer of txData. + */ + transferConfigB.srcAddr = + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); + transferConfigB.srcOffset = 1; + } + else + { + /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry + * to PUSHR register, so no need to change the pointer of txData. + */ + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcOffset = 1; + } } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD); + } + /* If only one word to transmit, only carry the lastcommand. */ + else + { + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL); + } + + /*Start the EDMA channel_A , channel_C. */ + EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); + EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); + + /* Set the channel link. + * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the + * receive register, and then carry transmit data to PUSHER register. + * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link. + */ + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /*Set channel priority*/ + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; + uint8_t t = 0; + + if (channelPriorityLow > channelPriorityHigh) + { + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; + channelPriorityHigh = t; + } + + edma_channel_Preemption_config_t preemption_config_t; + preemption_config_t.enableChannelPreemption = true; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; + + EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + &preemption_config_t); + + preemption_config_t.channelPriority = channelPriorityHigh; + EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to + channelC to carry the next data to PUSHER register.(txData to PUSHER) */ + if (handle->remainingSendByteCount > 0U) + { + EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); + } + } + + DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + + /* Setup control info to PUSHER register. */ + *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U); +#else + + /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should + write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the + SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + if (NULL != handle->txData) + { + transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcOffset = 1; + } + else + { + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + majorlink , the majorlink would not trigger the channel_C*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; + } + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; + } + } + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to + handle the last data */ + + edma_transfer_config_t transferConfigC; + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) + { + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.destAddr = (uint32_t)txAddr; + + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); + } + else + { + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -618,165 +853,233 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ - if (handle->remainingSendByteCount > 1) + to prepare the next 32bits data (txData to handle->command) */ + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->isThereExtraByte) - { - EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); - } - EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } - +#endif DSPI_StartTransfer(base); return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -784,13 +1087,33 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -798,14 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -815,88 +1140,99 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU)); + handle->state = (uint8_t)kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } - if ((handle->bitsPerFrame > 8) && (transfer->dataSize < 2)) + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; - handle->errorCount = 0; + handle->totalByteCount = transfer->dataSize; - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } - - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -907,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -919,42 +1255,36 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ - if ((handle->remainingSendByteCount == 2) && (handle->isThereExtraByte)) - { - wordToSend |= (unsigned)(dummyData) << 8U; - ++handle->txData; /* Increment to next data byte */ - } - else - { - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - ++handle->txData; /* Increment to next data byte */ - } + + wordToSend |= (unsigned)(*(handle->txData)) << 8U; + ++handle->txData; /* Increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -962,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -978,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -994,179 +1325,132 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - /*If there is extra byte , it would use the */ - if (handle->isThereExtraByte) - { - if (handle->txData) - { - handle->txLastData = - handle->txData[handle->remainingSendByteCount - 2] | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - else - { - handle->txLastData = DSPI_DUMMY_DATA | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - transferConfigC.srcAddr = (uint32_t)(&(handle->txLastData)); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destOffset = 0; - EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); - } - - /*Set another transferConfigC*/ - if ((handle->isThereExtraByte) && (handle->remainingSendByteCount == 2)) + if (NULL != handle->txData) { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcOffset = 1; } else { - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.destOffset = 0; - - if (handle->txData) + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcOffset = 0; + if (handle->bitsPerFrame <= 8U) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); - transferConfigC.srcOffset = 1; + handle->txBuffIfNull = dummyData; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) - { - handle->txBuffIfNull = DSPI_DUMMY_DATA; - } - else - { - handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - } + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } - - transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; - } - else - { - transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - if (handle->isThereExtraByte) - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; - } - } - - if (handle->isThereExtraByte) - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, softwareTCD); - EDMA_EnableAutoStopRequest(handle->edmaTxDataToTxRegHandle->base, - handle->edmaTxDataToTxRegHandle->channel, false); - } - else - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); - } - - EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } + + transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + } + else + { + transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; + } + + EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + + EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1176,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1196,58 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1255,7 +1548,8 @@ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.h index 643efadca4..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW41Z/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -37,28 +15,33 @@ * @{ */ - /*********************************************************************************************************************** * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI master. + * @param handle A pointer to the handle for the DSPI master. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, dspi_master_edma_handle_t *handle, @@ -68,38 +51,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI slave. + * @param handle A pointer to the handle for the DSPI slave. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData); -/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */ +/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */ struct _dspi_master_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/ + + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ - dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ @@ -110,33 +94,30 @@ struct _dspi_master_edma_handle edma_tcd_t dspiSoftwareTCD[2]; /*!whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -173,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -185,48 +229,92 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; - masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + assert(NULL != masterConfig); - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; + masterConfig->ctarConfig.bitsPerFrame = 8; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { + assert(NULL != slaveConfig); + uint32_t temp = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -239,40 +327,66 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - slaveConfig->whichCtar = kDSPI_Ctar0; - slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + assert(NULL != slaveConfig); - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; + slaveConfig->ctarConfig.bitsPerFrame = 8; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); DSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* disable DSPI clock */ CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh) @@ -293,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -312,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -378,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -402,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -424,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -455,83 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + assert(NULL != command); + + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + assert(NULL != command); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + /* First, clear Transmit Complete Flag (TCF) */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); + + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -540,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -556,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -574,44 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isEndOfQueue = true; + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -620,34 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -659,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -700,54 +1013,39 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; + if (rxData != NULL) + { + *(rxData) = (uint8_t)DSPI_ReadData(base); + rxData++; + } + else + { + (void)DSPI_ReadData(base); + } + remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) - { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) - { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -755,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -768,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -821,24 +1120,28 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; + wordReceived = (uint16_t)DSPI_ReadData(base); - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + if (rxData != NULL) + { + *rxData = (uint8_t)wordReceived; + ++rxData; + *rxData = (uint8_t)(wordReceived >> 8U); + ++rxData; + } + remainingReceiveByteCount -= 2U; + + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -849,27 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - dspi_command_data_config_t commandStruct; + assert(NULL != handle); + assert(NULL != transfer); + + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isEndOfQueue = true; + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -877,61 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); - - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - - DSPI_MasterTransferFillUpTxFifo(base, handle); /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -943,11 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -956,40 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; + assert(NULL != handle); + + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -997,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1005,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1021,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1056,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1066,82 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { + assert(NULL != handle); + /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1150,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1178,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1210,85 +1736,107 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); + + s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; + + /* Enable RX FIFO drain request, the slave only use this interrupt */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + + if (NULL != handle->rxData) + { + /* RX FIFO overflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); + } + if (NULL != handle->txData) + { + /* TX FIFO underflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); + } DSPI_StartTransfer(base); /* Prepare data to transmit */ DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; - - /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); - - if (handle->rxData) - { - /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); - } - if (handle->txData) - { - /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); - } - return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1300,22 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_SLAVE_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1333,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1380,24 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1406,65 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - if (handle->callback) + handle->state = (uint8_t)kDSPI_Idle; + + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - uint8_t dummyPattern = DSPI_SLAVE_DUMMY_DATA; + assert(NULL != handle); + + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1482,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1498,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1571,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1604,12 +2188,17 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif @@ -1617,7 +2206,7 @@ void SPI0_DriverIRQHandler(void) #if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif @@ -1625,7 +2214,7 @@ void SPI1_DriverIRQHandler(void) #if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif @@ -1633,7 +2222,7 @@ void SPI2_DriverIRQHandler(void) #if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif @@ -1641,7 +2230,7 @@ void SPI3_DriverIRQHandler(void) #if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif @@ -1649,7 +2238,7 @@ void SPI4_DriverIRQHandler(void) #if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi.h index 93da32fa2f..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2019 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -33,62 +11,59 @@ #include "fsl_common.h" /*! - * @addtogroup dspi + * @addtogroup dspi_driver * @{ */ -/*! @file */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.0. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ -/*! @name Dummy data */ -/*@{*/ -#define DSPI_MASTER_DUMMY_DATA (0x00U) /*!< Master dummy data used for tx if there is not txData. */ -#define DSPI_SLAVE_DUMMY_DATA (0x00U) /*!< Slave dummy data used for tx if there is not txData. */ -/*@}*/ +#ifndef DSPI_DUMMY_DATA +/*! @brief DSPI dummy data if there is no Tx data.*/ +#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */ +#endif /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out Of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All status above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -105,12 +80,13 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in Modified Transfer Format. This field is valid - * only when CPHA bit in CTAR register is 0. + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid + * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point { @@ -134,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -169,36 +145,37 @@ typedef enum _dspi_clock_phase typedef enum _dspi_shift_direction { kDSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ - kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ + kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. + Shifting out of LSB is not supported for slave */ } dspi_shift_direction_t; /*! @brief DSPI delay type selection.*/ typedef enum _dspi_delay_type { kDSPI_PcsToSck = 1U, /*!< Pcs-to-SCK delay. */ - kDSPI_LastSckToPcs, /*!< Last SCK edge to Pcs delay. */ + kDSPI_LastSckToPcs, /*!< The last SCK edge to Pcs delay. */ kDSPI_BetweenTransfer /*!< Delay between transfers. */ } dspi_delay_type_t; /*! @brief DSPI Clock and Transfer Attributes Register (CTAR) selection.*/ typedef enum _dspi_ctar_selection { - kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode, note that CTAR0 and CTAR0_SLAVE are the + kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode; note that CTAR0 and CTAR0_SLAVE are the same register address. */ kDSPI_Ctar1 = 1U, /*!< CTAR1 selection option for master mode only. */ - kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only , note that some device do not support CTAR2. */ - kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only , note that some device do not support CTAR3. */ - kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only , note that some device do not support CTAR4. */ - kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only , note that some device do not support CTAR5. */ - kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only , note that some device do not support CTAR6. */ - kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only , note that some device do not support CTAR7. */ + kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only; note that some devices do not support CTAR2. */ + kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only; note that some devices do not support CTAR3. */ + kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only; note that some devices do not support CTAR4. */ + kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only; note that some devices do not support CTAR5. */ + kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only; note that some devices do not support CTAR6. */ + kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only; note that some devices do not support CTAR7. */ } dspi_ctar_selection_t; -#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro , internal used. */ -#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro , internal used. */ -#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro , internal used. */ -#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro , internal used. */ -/*! @brief Can use this enumeration for DSPI master transfer configFlags. */ +#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro; used internally. */ +#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro; used internally. */ +#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro; used internally. */ +#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI master transfer configFlags. */ enum _dspi_transfer_config_flag_for_master { kDSPI_MasterCtar0 = 0U << DSPI_MASTER_CTAR_SHIFT, /*!< DSPI master transfer use CTAR0 setting. */ @@ -217,20 +194,21 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Is PCS signal active after last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; -#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro , internal used. */ -#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro , internal used. */ -/*! @brief Can use this enum for DSPI slave transfer configFlags. */ +#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ +#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI slave transfer configFlags. */ enum _dspi_transfer_config_flag_for_slave { kDSPI_SlaveCtar0 = 0U << DSPI_SLAVE_CTAR_SHIFT, /*!< DSPI slave transfer use CTAR0 setting. */ /*!< DSPI slave can only use PCS0. */ }; -/*! @brief DSPI transfer state, which is used for DSPI transactional APIs' state machine. */ +/*! @brief DSPI transfer state, which is used for DSPI transactional API state machine. */ enum _dspi_transfer_state { kDSPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver. */ @@ -238,15 +216,15 @@ enum _dspi_transfer_state kDSPI_Error /*!< Transfer error. */ }; -/*! @brief DSPI master command date configuration used for SPIx_PUSHR.*/ +/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ bool isEndOfQueue; /*!< Signals that the current transfer is the last in the queue.*/ - bool clearTransferCount; /*!< Clears SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ + bool clearTransferCount; /*!< Clears the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ } dspi_command_data_config_t; /*! @brief DSPI master ctar configuration structure.*/ @@ -258,33 +236,33 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time with nanosecond , set to 0 sets the minimum - delay. It sets the boundary value if out of range that can be set.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time with nanosecond , set to 0 sets the - minimum delay.It sets the boundary value if out of range that can be - set.*/ - uint32_t betweenTransferDelayInNanoSec; /*!< After SCK delay time with nanosecond , set to 0 sets the minimum - delay.It sets the boundary value if out of range that can be set.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ + + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ } dspi_master_ctar_config_t; /*! @brief DSPI master configuration structure.*/ typedef struct _dspi_master_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_master_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - dspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs). */ - dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low. */ + dspi_which_pcs_t whichPcs; /*!< The desired Peripheral Chip Select (pcs). */ + dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< The desired PCS active high or low. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable . Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_master_config_t; @@ -294,34 +272,34 @@ typedef struct _dspi_slave_ctar_config uint32_t bitsPerFrame; /*!< Bits per frame, minimum 4, maximum 16.*/ dspi_clock_polarity_t cpol; /*!< Clock polarity. */ dspi_clock_phase_t cpha; /*!< Clock phase. */ - /*!< Slave only supports MSB , does not support LSB.*/ + /*!< Slave only supports MSB and does not support LSB.*/ } dspi_slave_ctar_config_t; /*! @brief DSPI slave configuration structure.*/ typedef struct _dspi_slave_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_slave_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -356,47 +334,60 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags , set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ + volatile uint8_t state; /*!< DSPI transfer state, see _dspi_transfer_state.*/ dspi_master_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ }; -/*! @brief DSPI slave transfer handle structure used for transactional API. */ +/*! @brief DSPI slave transfer handle structure used for the transactional API. */ struct _dspi_slave_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ volatile uint8_t state; /*!< DSPI transfer state.*/ @@ -421,18 +412,18 @@ extern "C" { /*! * @brief Initializes the DSPI master. * - * This function initializes the DSPI master configuration. An example use case is as follows: + * This function initializes the DSPI master configuration. This is an example use case. * @code * dspi_master_config_t masterConfig; * masterConfig.whichCtar = kDSPI_Ctar0; - * masterConfig.ctarConfig.baudRate = 500000000; + * masterConfig.ctarConfig.baudRate = 500000000U; * masterConfig.ctarConfig.bitsPerFrame = 8; * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; - * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; * masterConfig.whichPcs = kDSPI_Pcs0; * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; * masterConfig.enableContinuousSCK = false; @@ -443,8 +434,8 @@ extern "C" { * @endcode * * @param base DSPI peripheral address. - * @param masterConfig Pointer to structure dspi_master_config_t. - * @param srcClock_Hz Module source input clock in Hertz + * @param masterConfig Pointer to the structure dspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz. */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz); @@ -452,8 +443,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u * @brief Sets the dspi_master_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). - * User may use the initialized structure unchanged in DSPI_MasterInit() or modify the structure - * before calling DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). * Example: * @code * dspi_master_config_t masterConfig; @@ -466,7 +457,7 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); /*! * @brief DSPI slave configuration. * - * This function initializes the DSPI slave configuration. An example use case is as follows: + * This function initializes the DSPI slave configuration. This is an example use case. * @code * dspi_slave_config_t slaveConfig; * slaveConfig->whichCtar = kDSPI_Ctar0; @@ -481,22 +472,22 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); * @endcode * * @param base DSPI peripheral address. - * @param slaveConfig Pointer to structure dspi_master_config_t. + * @param slaveConfig Pointer to the structure dspi_master_config_t. */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig); /*! - * @brief Sets the dspi_slave_config_t structure to default values. + * @brief Sets the dspi_slave_config_t structure to a default value. * * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). - * User may use the initialized structure unchanged in DSPI_SlaveInit(), or modify the structure - * before calling DSPI_SlaveInit(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. * @code * dspi_slave_config_t slaveConfig; * DSPI_SlaveGetDefaultConfig(&slaveConfig); * @endcode - * @param slaveConfig pointer to dspi_slave_config_t structure. + * @param slaveConfig Pointer to the dspi_slave_config_t structure. */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig); @@ -510,7 +501,7 @@ void DSPI_Deinit(SPI_Type *base); * @brief Enables the DSPI peripheral and sets the MCR MDIS to 0. * * @param base DSPI peripheral address. - * @param enable pass true to enable module, false to disable module. + * @param enable Pass true to enable module, false to disable module. */ static inline void DSPI_Enable(SPI_Type *base, bool enable) { @@ -526,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -536,7 +527,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! * @brief Gets the DSPI status flag state. * @param base DSPI peripheral address. - * @return The DSPI status(in SR register). + * @return DSPI status (in SR register). */ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) { @@ -549,13 +540,13 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the * desired status bit to clear. The list of status bits is defined in the dspi_status_and_interrupt_request_t. The * function uses these bit positions in its algorithm to clear the desired flag state. - * Example usage: + * This is an example. * @code * DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag); * @endcode * * @param base DSPI peripheral address. - * @param statusFlags The status flag , used from type dspi_flags. + * @param statusFlags The status flag used from the type dspi_flags. */ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) { @@ -564,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -574,15 +565,16 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! * @brief Enables the DSPI interrupts. * - * This function configures the various interrupt masks of the DSPI. The parameters are base and an interrupt mask. + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); @@ -594,7 +586,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) { @@ -603,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -613,13 +605,13 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! * @brief Enables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * DSPI_EnableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) { @@ -629,13 +621,13 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) /*! * @brief Disables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * SPI_DisableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask) { @@ -683,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -709,12 +707,19 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. * - * This function sets the module to begin data transfer in either master or slave mode. + * This function sets the module to start data transfer in either master or slave mode. * * @param base DSPI peripheral address. */ @@ -723,9 +728,9 @@ static inline void DSPI_StartTransfer(SPI_Type *base) base->MCR &= ~SPI_MCR_HALT_MASK; } /*! - * @brief Stops (halts) DSPI transfers and sets HALT bit in MCR. + * @brief Stops DSPI transfers and sets the HALT bit in MCR. * - * This function stops data transfers in either master or slave mode. + * This function stops data transfers in either master or slave modes. * * @param base DSPI peripheral address. */ @@ -735,44 +740,44 @@ static inline void DSPI_StopTransfer(SPI_Type *base) } /*! - * @brief Enables (or disables) the DSPI FIFOs. + * @brief Enables or disables the DSPI FIFOs. * - * This function allows the caller to disable/enable the Tx and Rx FIFOs (independently). - * Note that to disable, the caller must pass in a logic 0 (false) for the particular FIFO configuration. To enable, - * the caller must pass in a logic 1 (true). + * This function allows the caller to disable/enable the Tx and Rx FIFOs independently. + * Note that to disable, pass in a logic 0 (false) for the particular FIFO configuration. To enable, + * pass in a logic 1 (true). * * @param base DSPI peripheral address. - * @param enableTxFifo Disables (false) the TX FIFO, else enables (true) the TX FIFO - * @param enableRxFifo Disables (false) the RX FIFO, else enables (true) the RX FIFO + * @param enableTxFifo Disables (false) the TX FIFO; Otherwise, enables (true) the TX FIFO + * @param enableRxFifo Disables (false) the RX FIFO; Otherwise, enables (true) the RX FIFO */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! * @brief Flushes the DSPI FIFOs. * * @param base DSPI peripheral address. - * @param flushTxFifo Flushes (true) the Tx FIFO, else do not flush (false) the Tx FIFO - * @param flushRxFifo Flushes (true) the Rx FIFO, else do not flush (false) the Rx FIFO + * @param flushTxFifo Flushes (true) the Tx FIFO; Otherwise, does not flush (false) the Tx FIFO + * @param flushRxFifo Flushes (true) the Rx FIFO; Otherwise, does not flush (false) the Rx FIFO */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! * @brief Configures the DSPI peripheral chip select polarity simultaneously. - * For example, PCS0 and PCS1 set to active low and other PCS set to active high. Note that the number of + * For example, PCS0 and PCS1 are set to active low and other PCS is set to active high. Note that the number of * PCSs is specific to the device. * @code * DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow); @endcode * @param base DSPI peripheral address. - * @param mask The PCS polarity mask , can use the enum _dspi_pcs_polarity. + * @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity. */ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask) { @@ -801,19 +806,19 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, * @brief Manually configures the delay prescaler and scaler for a particular CTAR. * * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar - * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT)and scalar (DT). + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes the delay to configure along with the prescaler and scaler value. - * This allows the user to directly set the prescaler/scaler values if they have pre-calculated them or if they simply - * wish to manually increment either value. + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. * * @param base DSPI peripheral address. * @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. * @param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). * @param scaler The scaler delay value (can be any integer between 0 to 15). - * @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * @param whichDelay The desired delay to configure; must be of type dspi_delay_type_t */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay); @@ -821,19 +826,19 @@ void DSPI_MasterSetDelayScaler( /*! * @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. * - * This function calculates the values for: + * This function calculates the values for the following. * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or * After SCK delay pre-scalar (PASC) and scalar (ASC), or - * Delay after transfer pre-scalar (PDT)and scalar (DT). + * Delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes which delay they want to configure along with the desired delay value in nanoseconds. The function - * calculates the values needed for the prescaler and scaler and returning the actual calculated delay as an exact + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact * delay match may not be possible. In this case, the closest match is calculated without going below the desired * delay value input. * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum - * supported delay is returned. The higher level peripheral driver alerts the user of an out of range delay + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay * input. * * @param base DSPI peripheral address. @@ -853,11 +858,11 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, * @brief Writes data into the data buffer for master mode. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_data_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -869,7 +874,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, @endcode * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) @@ -883,14 +888,14 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config * @brief Sets the dspi_command_data_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). - * User may use the initialized structure unchanged in DSPI_MasterWrite_xx() or modify the structure - * before calling DSPI_MasterWrite_xx(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. * @code * dspi_command_data_config_t command; * DSPI_GetDefaultDataCommandConfig(&command); * @endcode - * @param command pointer to dspi_command_data_config_t structure. + * @param command Pointer to the dspi_command_data_config_t structure. */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); @@ -898,11 +903,11 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * @brief Writes data into the data buffer master mode and waits till complete to return. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -915,10 +920,10 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, - * receive data is available when transmit completes. + * the received data is available when the transmit completes. * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data); @@ -933,10 +938,10 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co * improve performance in cases where the command structure is constant. For example, the user calls this function * before starting a transfer to generate the command word. When they are ready to transmit the data, they OR * this formatted command word with the desired data to transmit. This process increases transmit performance when - * compared to calling send functions such as DSPI_HAL_WriteDataMastermode which format the command word each time a + * compared to calling send functions, such as DSPI_HAL_WriteDataMastermode, which format the command word each time a * data word is to be sent. * - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @return The command word formatted to the PUSHR data register bit field. */ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t *command) @@ -949,43 +954,44 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t /*! * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data - * buffer, master mode and waits till complete to return. + * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command info then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word * as the data to send. - * The command portion provides characteristics of the data such as the optional continuous chip select operation -* between - * transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: * @code * dataWord = <16-bit command> | <16-bit data>; - * DSPI_HAL_WriteCommandDataMastermodeBlocking(base, dataWord); + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); * @endcode * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). - * Because the SPI is a synchronous protocol, the receive data is available when transmit completes. + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. - * @param data The data word (command and data combined) to be sent + * @param data The data word (command and data combined) to be sent. */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data); @@ -1024,9 +1030,17 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} -*/ + */ /*! * @name Transactional @@ -1037,13 +1051,13 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) /*! * @brief Initializes the DSPI master handle. * - * This function initializes the DSPI handle which can be used for other DSPI transactional APIs. Usually, for a + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_handle_t. - * @param callback dspi callback. - * @param userData callback function parameter. + * @param callback DSPI callback. + * @param userData Callback function parameter. */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, @@ -1053,12 +1067,11 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, /*! * @brief DSPI master transfer data using polling. * - * This function transfers data with polling. This is a blocking function, which does not return until all transfers - * have been - * completed. + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. * * @param base DSPI peripheral base address. - * @param transfer pointer to dspi_transfer_t structure. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); @@ -1067,35 +1080,63 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); * @brief DSPI master transfer data using interrupts. * * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all - data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * * This function gets the master transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count); /*! - * @brief DSPI master aborts transfer using an interrupt. + * @brief DSPI master aborts a transfer using an interrupt. * * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); @@ -1105,7 +1146,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); @@ -1115,10 +1156,10 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * @param handle DSPI handle pointer to dspi_slave_handle_t. + * @param handle DSPI handle pointer to the dspi_slave_handle_t. * @param base DSPI peripheral base address. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData Callback function parameter. */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, @@ -1129,12 +1170,11 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, * @brief DSPI slave transfers data using an interrupt. * * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all - * data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer); @@ -1145,8 +1185,8 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand * This function gets the slave transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count); @@ -1154,10 +1194,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, /*! * @brief DSPI slave aborts a transfer using an interrupt. * - * This function aborts transfer using an interrupt. + * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); @@ -1167,19 +1207,29 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.c index 4d9e129ff2..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* 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. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ #include "fsl_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,46 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -101,51 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); +#if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) + assert(NULL != edmaTxDataToIntermediaryHandle); +#endif + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_MASTER_DUMMY_DATA; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + handle->state = (uint8_t)kDSPI_Busy; + + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -154,32 +170,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_MASTER_DUMMY_DATA << 8) | DSPI_MASTER_DUMMY_DATA; - - handle->state = kDSPI_Busy; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isEndOfQueue = true; + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -187,98 +204,123 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - /* this limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (handle->bitsPerFrame > 8) + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (transfer->dataSize > 1022) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) + { + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_InvalidArgument; + } + + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) - { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } - } - else - { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - } - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - } - else /* For all words except the last word , frame > 8bits */ - { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; + } + else + { + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); + } + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; + } + else /* For all words except the last word , frame > 8bits */ + { + if (NULL != handle->txData) + { + wordToSend = *(handle->txData); + ++handle->txData; /* increment to next data byte */ + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -288,9 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -300,66 +343,57 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /*dspi has shared dma request*/ - { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -367,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -379,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -389,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -404,125 +439,66 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); - /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should - write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the - SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ - EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - - if (handle->remainingSendByteCount > 0) + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*Calculate the last data : handle->lastCommand*/ + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) - { - transferConfigB.srcAddr = (uint32_t)(handle->txData); - transferConfigB.srcOffset = 1; - } - else - { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigB.srcOffset = 0; - } - - transferConfigB.destAddr = (uint32_t)(&handle->command); - transferConfigB.destOffset = 0; - - transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; - - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; - } - } - else - { - transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; - } - } - - EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); - } - - /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to - handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -530,85 +506,345 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - if (handle->isThereExtraByte) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 2] | - ((uint32_t)dummyData << 8); - } - else - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; - } + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } } +/* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO, + * allowing a single write to the command word followed by multiple writes to the transmit word. + * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the + * transmit word into a 32-bit write that pushes both the command word and transmit word into + * the TX FIFO (PUSH TX FIFO Register In Master Mode) + * So, if this feature is supported, we can use use one channel to carry the receive data from + * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer + * to transmit register,and use the scatter/gather function to prepare the last data. + * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data. + */ +#if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET + /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to PUSHR register. + */ + + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + /*User_Send_Buffer(txData) to PUSHR register. */ + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); - transferConfigC.destAddr = (uint32_t)txAddr; - - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (handle->txData) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /* For DSPI with separate RX and TX DMA requests, one frame data has been carry + * to handle->command, so need to reduce the pointer of txData. + */ + transferConfigB.srcAddr = + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); + transferConfigB.srcOffset = 1; + } + else + { + /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry + * to PUSHR register, so no need to change the pointer of txData. + */ + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcOffset = 1; + } } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD); + } + /* If only one word to transmit, only carry the lastcommand. */ + else + { + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL); + } + + /*Start the EDMA channel_A , channel_C. */ + EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); + EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); + + /* Set the channel link. + * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the + * receive register, and then carry transmit data to PUSHER register. + * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link. + */ + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /*Set channel priority*/ + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; + uint8_t t = 0; + + if (channelPriorityLow > channelPriorityHigh) + { + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; + channelPriorityHigh = t; + } + + edma_channel_Preemption_config_t preemption_config_t; + preemption_config_t.enableChannelPreemption = true; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; + + EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + &preemption_config_t); + + preemption_config_t.channelPriority = channelPriorityHigh; + EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to + channelC to carry the next data to PUSHER register.(txData to PUSHER) */ + if (handle->remainingSendByteCount > 0U) + { + EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); + } + } + + DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + + /* Setup control info to PUSHER register. */ + *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U); +#else + + /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should + write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the + SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + if (NULL != handle->txData) + { + transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcOffset = 1; + } + else + { + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + majorlink , the majorlink would not trigger the channel_C*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; + } + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; + } + else + { + /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; + } + } + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to + handle the last data */ + + edma_transfer_config_t transferConfigC; + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) + { + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.destAddr = (uint32_t)txAddr; + + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); + } + else + { + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + } + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -617,165 +853,233 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ - if (handle->remainingSendByteCount > 1) + to prepare the next 32bits data (txData to handle->command) */ + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->isThereExtraByte) - { - EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); - } - EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } - +#endif DSPI_StartTransfer(base); return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -783,13 +1087,33 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -797,14 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -814,88 +1140,99 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU)); + handle->state = (uint8_t)kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8U) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = (uint8_t)kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } - if ((handle->bitsPerFrame > 8) && (transfer->dataSize < 2)) + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; - handle->errorCount = 0; + handle->totalByteCount = transfer->dataSize; - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } - - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_SLAVE_DUMMY_DATA; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -906,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -918,42 +1255,36 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ - if ((handle->remainingSendByteCount == 2) && (handle->isThereExtraByte)) - { - wordToSend |= (unsigned)(dummyData) << 8U; - ++handle->txData; /* Increment to next data byte */ - } - else - { - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - ++handle->txData; /* Increment to next data byte */ - } + + wordToSend |= (unsigned)(*(handle->txData)) << 8U; + ++handle->txData; /* Increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -961,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -977,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -993,179 +1325,132 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - /*If there is extra byte , it would use the */ - if (handle->isThereExtraByte) - { - if (handle->txData) - { - handle->txLastData = - handle->txData[handle->remainingSendByteCount - 2] | ((uint32_t)DSPI_SLAVE_DUMMY_DATA << 8); - } - else - { - handle->txLastData = DSPI_SLAVE_DUMMY_DATA | ((uint32_t)DSPI_SLAVE_DUMMY_DATA << 8); - } - transferConfigC.srcAddr = (uint32_t)(&(handle->txLastData)); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destOffset = 0; - EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); - } - - /*Set another transferConfigC*/ - if ((handle->isThereExtraByte) && (handle->remainingSendByteCount == 2)) + if (NULL != handle->txData) { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcOffset = 1; } else { - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.destOffset = 0; - - if (handle->txData) + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcOffset = 0; + if (handle->bitsPerFrame <= 8U) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); - transferConfigC.srcOffset = 1; + handle->txBuffIfNull = dummyData; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) - { - handle->txBuffIfNull = DSPI_SLAVE_DUMMY_DATA; - } - else - { - handle->txBuffIfNull = (DSPI_SLAVE_DUMMY_DATA << 8) | DSPI_SLAVE_DUMMY_DATA; - } + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } - - transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - - if (handle->bitsPerFrame <= 8) - { - transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; - } - else - { - transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - if (handle->isThereExtraByte) - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; - } - } - - if (handle->isThereExtraByte) - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, softwareTCD); - EDMA_EnableAutoStopRequest(handle->edmaTxDataToTxRegHandle->base, - handle->edmaTxDataToTxRegHandle->channel, false); - } - else - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); - } - - EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } + + transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + } + else + { + transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; + } + + EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); + + EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1175,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1195,58 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); + dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } - - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { + assert(NULL != handle); + DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1254,7 +1548,8 @@ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.h index 326b7ee442..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -37,29 +15,33 @@ * @{ */ -/*! @file */ - /*********************************************************************************************************************** * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI master. + * @param handle A pointer to the handle for the DSPI master. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, dspi_master_edma_handle_t *handle, @@ -69,38 +51,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI slave. + * @param handle A pointer to the handle for the DSPI slave. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData); -/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */ +/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */ struct _dspi_master_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/ + + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ - dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ @@ -111,33 +94,30 @@ struct _dspi_master_edma_handle edma_tcd_t dspiSoftwareTCD[2]; /*!whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -179,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -191,47 +229,85 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - assert(masterConfig); + assert(NULL != masterConfig); - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); uint32_t temp = 0; @@ -251,35 +327,57 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); + DSPI_SetDummyData(base, DSPI_DUMMY_DATA); + DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); - slaveConfig->whichCtar = kDSPI_Ctar0; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); @@ -309,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -328,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -394,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -418,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -440,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -471,87 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - assert(command); + assert(NULL != command); - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - assert(command); + assert(NULL != command); /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -560,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -576,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -594,45 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -641,15 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -661,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -702,24 +1013,25 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -727,13 +1039,13 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -741,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -754,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -807,26 +1120,27 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); if (rxData != NULL) { - *rxData = wordReceived; + *rxData = (uint8_t)wordReceived; ++rxData; - *rxData = wordReceived >> 8; + *rxData = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -838,31 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); - dspi_command_data_config_t commandStruct; + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -870,62 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - DSPI_StartTransfer(base); - - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - - DSPI_MasterTransferFillUpTxFifo(base, handle); /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_StartTransfer(base); + + /* Fill up the Tx FIFO to trigger the transfer. */ + DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -937,13 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -952,41 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - handle->state = kDSPI_Idle; - - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -994,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1002,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1018,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1053,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1063,86 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1151,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1179,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1211,86 +1736,107 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); + + s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; + + /* Enable RX FIFO drain request, the slave only use this interrupt */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); + + if (NULL != handle->rxData) + { + /* RX FIFO overflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); + } + if (NULL != handle->txData) + { + /* TX FIFO underflow request enable */ + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); + } DSPI_StartTransfer(base); /* Prepare data to transmit */ DSPI_SlaveTransferFillUpTxFifo(base, handle); - s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; - - /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); - - if (handle->rxData) - { - /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); - } - if (handle->txData) - { - /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); - } - return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1302,24 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); uint16_t transmitData = 0; - uint8_t dummyPattern = DSPI_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1337,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1384,26 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1412,69 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; - if (handle->callback) + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint8_t dummyPattern = DSPI_DUMMY_DATA; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1492,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1508,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1581,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1614,12 +2188,17 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif @@ -1627,7 +2206,7 @@ void SPI0_DriverIRQHandler(void) #if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif @@ -1635,7 +2214,7 @@ void SPI1_DriverIRQHandler(void) #if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif @@ -1643,7 +2222,7 @@ void SPI2_DriverIRQHandler(void) #if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif @@ -1651,7 +2230,7 @@ void SPI3_DriverIRQHandler(void) #if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif @@ -1659,7 +2238,7 @@ void SPI4_DriverIRQHandler(void) #if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi.h index 5dd96afcbe..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2019 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 the copyright holder 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -37,15 +15,14 @@ * @{ */ - /********************************************************************************************************************** * Definitions *********************************************************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.4. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 4)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ #ifndef DSPI_DUMMY_DATA @@ -56,37 +33,37 @@ /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -103,11 +80,12 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is valid + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is + * valid * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point @@ -132,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -216,8 +194,9 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = + 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; #define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ @@ -240,7 +219,7 @@ enum _dspi_transfer_state /*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ @@ -257,10 +236,10 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum - delay. It also sets the boundary value if out of range.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the - minimum delay. It also sets the boundary value if out of range.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum delay. It also sets the boundary value if out of range.*/ @@ -314,13 +293,13 @@ typedef struct _dspi_slave_config } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -355,12 +334,24 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { @@ -370,8 +361,9 @@ struct _dspi_master_handle uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ @@ -525,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -563,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -575,6 +567,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) * * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. * * @code * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); @@ -602,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -682,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -708,7 +707,14 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. @@ -746,8 +752,8 @@ static inline void DSPI_StopTransfer(SPI_Type *base) */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! @@ -759,8 +765,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! @@ -950,10 +956,12 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word * as the data to send. * The command portion provides characteristics of the data, such as the optional continuous chip select operation - * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: @@ -968,20 +976,20 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. * @param data The data word (command and data combined) to be sent. */ @@ -1022,9 +1030,17 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) return (base->POPR); } +/*! + * @brief Set up the dummy data. + * + * @param base DSPI peripheral address. + * @param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); + /*! *@} -*/ + */ /*! * @name Transactional @@ -1073,6 +1089,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * @@ -1166,15 +1211,25 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.c index ef0d15174f..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2018 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 the copyright holder 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_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,46 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -101,57 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); - assert(edmaTxDataToIntermediaryHandle); - assert(edmaIntermediaryToTxRegHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); +#if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) + assert(NULL != edmaTxDataToIntermediaryHandle); +#endif + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -160,31 +170,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - edma_transfer_config_t transferConfigC; - handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -192,15 +204,15 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ uint32_t limited_size = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { @@ -211,11 +223,11 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand limited_size = 511u; } - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { if (transfer->dataSize > (limited_size << 1u)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } @@ -223,19 +235,19 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (transfer->dataSize > limited_size) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); @@ -268,47 +280,47 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - handle->command = handle->lastCommand; + handle->command = handle->lastCommand; } else /* For all words except the last word , frame > 8bits */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -318,10 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - handle->command = handle->lastCommand; + handle->command = handle->lastCommand; } else { @@ -331,57 +343,57 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /*dspi has shared dma request*/ - { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -389,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -401,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -411,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -429,68 +442,63 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); - - /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should - write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the - SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ - - EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + (uint32_t)kEDMA_MajorInterruptEnable); + tmpRemainingSendByteCount = handle->remainingSendByteCount; /*Calculate the last data : handle->lastCommand*/ - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -498,175 +506,335 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } } - /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data - * (handle->lastCommand) to handle->Command*/ - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) +/* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO, + * allowing a single write to the command word followed by multiple writes to the transmit word. + * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the + * transmit word into a 32-bit write that pushes both the command word and transmit word into + * the TX FIFO (PUSH TX FIFO Register In Master Mode) + * So, if this feature is supported, we can use use one channel to carry the receive data from + * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer + * to transmit register,and use the scatter/gather function to prepare the last data. + * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data. + */ +#if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET + /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to PUSHR register. + */ + + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + + if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || + ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigB.destAddr = (uint32_t) & (handle->command); - transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigB.srcOffset = 0; - transferConfigB.destOffset = 0; - transferConfigB.minorLoopBytes = 4; - transferConfigB.majorLoopCounts = 1; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } - /*User_Send_Buffer(txData) to intermediary(handle->command)*/ - if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + /*User_Send_Buffer(txData) to PUSHR register. */ + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { if (handle->txData) { - transferConfigB.srcAddr = (uint32_t)(handle->txData); - transferConfigB.srcOffset = 1; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /* For DSPI with separate RX and TX DMA requests, one frame data has been carry + * to handle->command, so need to reduce the pointer of txData. + */ + transferConfigB.srcAddr = + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); + transferConfigB.srcOffset = 1; + } + else + { + /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry + * to PUSHR register, so no need to change the pointer of txData. + */ + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcOffset = 1; + } } else { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigB.srcOffset = 0; } - transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destAddr = (uint32_t)txAddr; transferConfigB.destOffset = 0; transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; + transferConfigB.minorLoopBytes = 1; + + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; + } + else + { + transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD); + } + /* If only one word to transmit, only carry the lastcommand. */ + else + { + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL); + } + + /*Start the EDMA channel_A , channel_C. */ + EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); + EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); + + /* Set the channel link. + * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the + * receive register, and then carry transmit data to PUSHER register. + * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link. + */ + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + /*Set channel priority*/ + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; + uint8_t t = 0; + + if (channelPriorityLow > channelPriorityHigh) + { + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; + channelPriorityHigh = t; + } + + edma_channel_Preemption_config_t preemption_config_t; + preemption_config_t.enableChannelPreemption = true; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; + + EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + &preemption_config_t); + + preemption_config_t.channelPriority = channelPriorityHigh; + EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to + channelC to carry the next data to PUSHER register.(txData to PUSHER) */ + if (handle->remainingSendByteCount > 0U) + { + EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, + kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); + } + } + + DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + + /* Setup control info to PUSHER register. */ + *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U); +#else + + /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should + write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the + SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); + } + + tmpRemainingSendByteCount = handle->remainingSendByteCount; + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) + { + if (NULL != handle->txData) + { + transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcOffset = 1; + } + else + { + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcOffset = 0; + } + + transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destOffset = 0; + + transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; + + if (handle->bitsPerFrame <= 8U) + { + transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigB.minorLoopBytes = 1; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; } else { /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; } } else { transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; + transferConfigB.minorLoopBytes = 2; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; } else { /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; } } if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); } } else { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); } /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to handle the last data */ + edma_transfer_config_t transferConfigC; EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + tmpRemainingSendByteCount = handle->remainingSendByteCount; /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data * (handle->lastCommand) to SPI_PUSHR*/ - if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) || + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); } else { transferConfigC.majorLoopCounts = 1; EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, @@ -675,7 +843,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -684,60 +853,64 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link.*/ @@ -745,18 +918,18 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB to prepare the next 32bits data (txData to handle->command) */ - if (handle->remainingSendByteCount > 1) + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); @@ -766,63 +939,147 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } - +#endif DSPI_StartTransfer(base); return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -838,6 +1095,25 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -845,16 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); - assert(edmaTxDataToTxRegHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -864,39 +1140,52 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ uint32_t limited_size = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { @@ -907,11 +1196,11 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle limited_size = 511u; } - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { if (transfer->dataSize > (limited_size << 1u)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } @@ -919,31 +1208,31 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle { if (transfer->dataSize > limited_size) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - uint16_t wordToSend = 0; - uint8_t dummyData = DSPI_DUMMY_DATA; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -954,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -966,14 +1255,15 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ @@ -983,18 +1273,18 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -1002,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -1018,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -1034,92 +1325,92 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destAddr = (uint32_t)txAddr; transferConfigC.destOffset = 0; - if (handle->txData) + if (NULL != handle->txData) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); transferConfigC.srcOffset = 1; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - handle->txBuffIfNull = DSPI_DUMMY_DATA; + handle->txBuffIfNull = dummyData; } else { - handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } } transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; } else { transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; } EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } @@ -1127,39 +1418,39 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1169,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1189,49 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.h index 23e29ce298..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K24F/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2018 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 the copyright holder 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -41,14 +19,20 @@ * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! @@ -186,6 +170,21 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI base pointer + * @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * @param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief DSPI master aborts a transfer which is using eDMA. * diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.c index d3b3f0aa5f..a15314c758 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.c @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2019 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 the copyright holder 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_dspi.h" @@ -33,6 +11,12 @@ /******************************************************************************* * Definitions ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi" +#endif + /*! @brief Typedef for master interrupt handler. */ typedef void (*dspi_master_isr_t)(SPI_Type *base, dspi_master_handle_t *handle); @@ -42,13 +26,6 @@ typedef void (*dspi_slave_isr_t)(SPI_Type *base, dspi_slave_handle_t *handle); /******************************************************************************* * Prototypes ******************************************************************************/ -/*! - * @brief Get instance number for DSPI module. - * - * @param base DSPI peripheral base address. - */ -uint32_t DSPI_GetInstance(SPI_Type *base); - /*! * @brief Configures the DSPI peripheral chip select polarity. * @@ -110,11 +87,11 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/ static const uint32_t s_baudratePrescaler[] = {2, 3, 5, 7}; -static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, +static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768}; static const uint32_t s_delayPrescaler[] = {1, 3, 5, 7}; -static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, +static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}; /*! @brief Pointers to dspi bases for each instance. */ @@ -138,10 +115,15 @@ static dspi_master_isr_t s_dspiMasterIsr; static dspi_slave_isr_t s_dspiSlaveIsr; /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/ -volatile uint8_t s_dummyData[ARRAY_SIZE(s_dspiBases)] = {0}; +volatile uint8_t g_dspiDummyData[ARRAY_SIZE(s_dspiBases)] = {0}; /********************************************************************************************************************** -* Code -*********************************************************************************************************************/ + * Code + *********************************************************************************************************************/ +/*! + * brief Get instance number for DSPI module. + * + * param base DSPI peripheral base address. + */ uint32_t DSPI_GetInstance(SPI_Type *base) { uint32_t instance; @@ -160,15 +142,64 @@ uint32_t DSPI_GetInstance(SPI_Type *base) return instance; } -void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base) { - uint32_t instance = DSPI_GetInstance(base); - s_dummyData[instance] = dummyData; + uint8_t instance = g_dspiDummyData[DSPI_GetInstance(base)]; + + return instance; } +/*! + * brief Set up the dummy data. + * + * param base DSPI peripheral address. + * param dummyData Data to be transferred when tx buffer is NULL. + */ +void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData) +{ + uint32_t instance = DSPI_GetInstance(base); + g_dspiDummyData[instance] = dummyData; +} + +/*! + * brief Initializes the DSPI master. + * + * This function initializes the DSPI master configuration. This is an example use case. + * code + * dspi_master_config_t masterConfig; + * masterConfig.whichCtar = kDSPI_Ctar0; + * masterConfig.ctarConfig.baudRate = 500000000U; + * masterConfig.ctarConfig.bitsPerFrame = 8; + * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.whichPcs = kDSPI_Pcs0; + * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; + * masterConfig.enableContinuousSCK = false; + * masterConfig.enableRxFifoOverWrite = false; + * masterConfig.enableModifiedTimingFormat = false; + * masterConfig.samplePoint = kDSPI_SckToSin0Clock; + * DSPI_MasterInit(base, &masterConfig, srcClock_Hz); + * endcode + * + * param base DSPI peripheral address. + * param masterConfig Pointer to the structure dspi_master_config_t. + * param srcClock_Hz Module source input clock in Hertz. + */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz) { - assert(masterConfig); + assert(NULL != masterConfig); uint32_t temp; #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) @@ -179,6 +210,7 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u DSPI_Enable(base, true); DSPI_StopTransfer(base); + DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); DSPI_SetMasterSlaveMode(base, kDSPI_Master); temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK | @@ -187,11 +219,9 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) | SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); - DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow); - - if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) + if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz)) { assert(false); } @@ -199,48 +229,85 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u temp = base->CTAR[masterConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[masterConfig->whichCtar] = - temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | - SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); + base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) | + SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) | + SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | + SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, - masterConfig->ctarConfig.pcsToSckDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); - DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, - masterConfig->ctarConfig.betweenTransferDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz, + masterConfig->ctarConfig.pcsToSckDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz, + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec); + (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz, + masterConfig->ctarConfig.betweenTransferDelayInNanoSec); DSPI_SetDummyData(base, DSPI_DUMMY_DATA); DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_master_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). + * Example: + * code + * dspi_master_config_t masterConfig; + * DSPI_MasterGetDefaultConfig(&masterConfig); + * endcode + * param masterConfig pointer to dspi_master_config_t structure + */ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { - assert(masterConfig); + assert(NULL != masterConfig); - masterConfig->whichCtar = kDSPI_Ctar0; - masterConfig->ctarConfig.baudRate = 500000; + /* Initializes the configure structure to zero. */ + (void)memset(masterConfig, 0, sizeof(*masterConfig)); + + masterConfig->whichCtar = kDSPI_Ctar0; + masterConfig->ctarConfig.baudRate = 500000; masterConfig->ctarConfig.bitsPerFrame = 8; - masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - masterConfig->ctarConfig.direction = kDSPI_MsbFirst; + masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + masterConfig->ctarConfig.direction = kDSPI_MsbFirst; - masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; - masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; + masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000; + masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000; masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000; - masterConfig->whichPcs = kDSPI_Pcs0; + masterConfig->whichPcs = kDSPI_Pcs0; masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow; - masterConfig->enableContinuousSCK = false; - masterConfig->enableRxFifoOverWrite = false; + masterConfig->enableContinuousSCK = false; + masterConfig->enableRxFifoOverWrite = false; masterConfig->enableModifiedTimingFormat = false; - masterConfig->samplePoint = kDSPI_SckToSin0Clock; + masterConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief DSPI slave configuration. + * + * This function initializes the DSPI slave configuration. This is an example use case. + * code + * dspi_slave_config_t slaveConfig; + * slaveConfig->whichCtar = kDSPI_Ctar0; + * slaveConfig->ctarConfig.bitsPerFrame = 8; + * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + * slaveConfig->enableContinuousSCK = false; + * slaveConfig->enableRxFifoOverWrite = false; + * slaveConfig->enableModifiedTimingFormat = false; + * slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + * DSPI_SlaveInit(base, &slaveConfig); + * endcode + * + * param base DSPI peripheral address. + * param slaveConfig Pointer to the structure dspi_master_config_t. + */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); uint32_t temp = 0; @@ -260,14 +327,14 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) | SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) | SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) | - SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false); + SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U); DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow); temp = base->CTAR[slaveConfig->whichCtar] & ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK); - base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) | + base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) | SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) | SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha); @@ -276,21 +343,41 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) DSPI_StartTransfer(base); } +/*! + * brief Sets the dspi_slave_config_t structure to a default value. + * + * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. + * code + * dspi_slave_config_t slaveConfig; + * DSPI_SlaveGetDefaultConfig(&slaveConfig); + * endcode + * param slaveConfig Pointer to the dspi_slave_config_t structure. + */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { - assert(slaveConfig); + assert(NULL != slaveConfig); - slaveConfig->whichCtar = kDSPI_Ctar0; + /* Initializes the configure structure to zero. */ + (void)memset(slaveConfig, 0, sizeof(*slaveConfig)); + + slaveConfig->whichCtar = kDSPI_Ctar0; slaveConfig->ctarConfig.bitsPerFrame = 8; - slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; - slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; + slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; + slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; - slaveConfig->enableContinuousSCK = false; - slaveConfig->enableRxFifoOverWrite = false; + slaveConfig->enableContinuousSCK = false; + slaveConfig->enableRxFifoOverWrite = false; slaveConfig->enableModifiedTimingFormat = false; - slaveConfig->samplePoint = kDSPI_SckToSin0Clock; + slaveConfig->samplePoint = kDSPI_SckToSin0Clock; } +/*! + * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock. + * param base DSPI peripheral address. + */ void DSPI_Deinit(SPI_Type *base) { DSPI_StopTransfer(base); @@ -320,6 +407,19 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc base->MCR = temp; } +/*! + * brief Sets the DSPI baud rate in bits per second. + * + * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without + * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the + * caller also provide the frequency of the module source clock (in Hertz). + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t + * param baudRate_Bps The desired baud rate in bits per second + * param srcClock_Hz Module source input clock in Hertz + * return The actual calculated baud rate + */ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t baudRate_Bps, @@ -339,51 +439,82 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate = baudRate_Bps; /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */ - min_diff = 0xFFFFFFFFU; + min_diff = 0xFFFFFFFFU; bestPrescaler = 0; - bestScaler = 0; - bestDbr = 1; - bestBaudrate = 0; /* required to avoid compilation warning */ + bestScaler = 0; + bestDbr = 1; + bestBaudrate = 0; /* required to avoid compilation warning */ /* In all for loops, if min_diff = 0, the exit for loop*/ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0U; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0U; scaler < 16U; scaler++) { - for (dbr = 1; (dbr < 3) && min_diff; dbr++) + for (dbr = 1U; dbr < 3U; dbr++) { realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler]))); /* calculate the baud rate difference based on the conditional statement that states that the calculated - * baud rate must not exceed the desired baud rate. - */ + * baud rate must not exceed the desired baud rate. + */ if (baudrate >= realBaudrate) { diff = baudrate - realBaudrate; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestBaudrate = realBaudrate; - bestDbr = dbr; + bestScaler = scaler; + bestBaudrate = realBaudrate; + bestDbr = dbr; } } + if (0U == min_diff) + { + break; + } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } /* write the best dbr, prescalar, and baud rate scalar to the CTAR */ temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK); - base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | + base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) | (bestScaler << SPI_CTAR_BR_SHIFT); /* return the actual calculated baud rate */ return bestBaudrate; } +/*! + * brief Manually configures the delay prescaler and scaler for a particular CTAR. + * + * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). + * param scaler The scaler delay value (can be any integer between 0 to 15). + * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t + */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay) { @@ -405,11 +536,38 @@ void DSPI_MasterSetDelayScaler( SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler); break; default: + /* All cases have been listed above, the default clause should not be reached. */ + assert(false); break; } } } +/*! + * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. + * + * This function calculates the values for the following. + * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or + * After SCK delay pre-scalar (PASC) and scalar (ASC), or + * Delay after transfer pre-scalar (PDT) and scalar (DT). + * + * These delay names are available in the type dspi_delay_type_t. + * + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact + * delay match may not be possible. In this case, the closest match is calculated without going below the desired + * delay value input. + * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum + * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay + * input. + * + * param base DSPI peripheral address. + * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. + * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * param srcClock_Hz Module source input clock in Hertz + * param delayTimeInNanoSec The desired delay value in nanoseconds. + * return The actual calculated delay value. + */ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, dspi_ctar_selection_t whichCtar, dspi_delay_type_t whichDelay, @@ -429,21 +587,21 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, uint32_t initialDelayNanoSec; /* find combination of prescaler and scaler resulting in the delay closest to the - * requested value - */ + * requested value + */ min_diff = 0xFFFFFFFFU; /* Initialize prescaler and scaler to their max values to generate the max delay */ bestPrescaler = 0x3; - bestScaler = 0xF; - bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4; + bestScaler = 0xF; + bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U; /* First calculate the initial, default delay */ - initialDelayNanoSec = 1000000000U / srcClock_Hz * 2; + initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U; /* If the initial, default delay is already greater than the desired delay, then - * set the delays to their initial value (0) and return the delay. In other words, - * there is no way to decrease the delay value further. - */ + * set the delays to their initial value (0) and return the delay. In other words, + * there is no way to decrease the delay value further. + */ if (initialDelayNanoSec >= delayTimeInNanoSec) { DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay); @@ -451,27 +609,36 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, } /* In all for loops, if min_diff = 0, the exit for loop */ - for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++) + for (prescaler = 0; prescaler < 4U; prescaler++) { - for (scaler = 0; (scaler < 16) && min_diff; scaler++) + for (scaler = 0; scaler < 16U; scaler++) { - realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4; + realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U; /* calculate the delay difference based on the conditional statement - * that states that the calculated delay must not be less then the desired delay - */ + * that states that the calculated delay must not be less then the desired delay + */ if (realDelay >= delayTimeInNanoSec) { diff = realDelay - delayTimeInNanoSec; if (min_diff > diff) { /* a better match found */ - min_diff = diff; + min_diff = diff; bestPrescaler = prescaler; - bestScaler = scaler; - bestDelay = realDelay; + bestScaler = scaler; + bestDelay = realDelay; } } + + if (0U == min_diff) + { + break; + } + } + if (0U == min_diff) + { + break; } } @@ -482,87 +649,194 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, return bestDelay; } +/*! + * brief Sets the dspi_command_data_config_t structure to default values. + * + * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. + * code + * dspi_command_data_config_t command; + * DSPI_GetDefaultDataCommandConfig(&command); + * endcode + * param command Pointer to the dspi_command_data_config_t structure. + */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { - assert(command); + assert(NULL != command); - command->isPcsContinuous = false; - command->whichCtar = kDSPI_Ctar0; - command->whichPcs = kDSPI_Pcs0; - command->isEndOfQueue = false; + /* Initializes the configure structure to zero. */ + (void)memset(command, 0, sizeof(*command)); + + command->isPcsContinuous = false; + command->whichCtar = kDSPI_Ctar0; + command->whichPcs = kDSPI_Pcs0; + command->isEndOfQueue = false; command->clearTransferCount = false; } +/*! + * brief Writes data into the data buffer master mode and waits till complete to return. + * + * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion + * provides characteristics of the data, such as the optional continuous chip select + * operation between transfers, the desired Clock and Transfer Attributes register to use for the + * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current + * transfer is the last in the queue, and whether to clear the transfer count (normally needed when + * sending the first frame of a data packet). This is an example. + * code + * dspi_command_config_t commandConfig; + * commandConfig.isPcsContinuous = true; + * commandConfig.whichCtar = kDSPICtar0; + * commandConfig.whichPcs = kDSPIPcs1; + * commandConfig.clearTransferCount = false; + * commandConfig.isEndOfQueue = false; + * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, + * the received data is available when the transmit completes. + * + * param base DSPI peripheral address. + * param command Pointer to the command structure. + * param data The data word to be sent. + */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { - assert(command); + assert(NULL != command); /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) | SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) | SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data); - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data + * buffer master mode and waits till complete to return. + * + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total + * 32-bit word + * as the data to send. + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the + * desired PCS + * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the + * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for + * appending this command with the data to send. This is an example: + * code + * dataWord = <16-bit command> | <16-bit data>; + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); + * endcode + * + * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be + * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. + * + * For a blocking polling transfer, see methods below. + * Option 1: + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * + * param base DSPI peripheral address. + * param data The data word (command and data combined) to be sent. + */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns. + * + * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data + * into data register, and finally waits until the data is transmitted. + * + * param base DSPI peripheral address. + * param data The data to send. + */ void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data) { /* First, clear Transmit Complete Flag (TCF) */ - DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag); - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } base->PUSHR_SLAVE = data; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Wait till TCF sets */ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag)) { } } +/*! + * brief Enables the DSPI interrupts. + * + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. + * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. + * Do not use this API(write to RSER register) while DSPI is in running state. + * + * code + * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable ); + * endcode + * + * param base DSPI peripheral address. + * param mask The interrupt mask; use the enum _dspi_interrupt_enable. + */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) { - if (mask & SPI_RSER_TFFF_RE_MASK) + if (0U != (mask & SPI_RSER_TFFF_RE_MASK)) { base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK; } - if (mask & SPI_RSER_RFDF_RE_MASK) + if (0U != (mask & SPI_RSER_RFDF_RE_MASK)) { base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK; } @@ -571,15 +845,26 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask) /*Transactional APIs -- Master*/ +/*! + * brief Initializes the DSPI master handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_handle_t. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, dspi_master_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -587,13 +872,23 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI master transfer data using polling. + * + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. + * + * param base DSPI peripheral base address. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { - assert(transfer); + assert(NULL != transfer); - uint16_t wordToSend = 0; + uint16_t wordToSend = 0; uint16_t wordReceived = 0; - uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t bitsPerFrame; uint32_t command; @@ -605,45 +900,49 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) uint32_t remainingReceiveByteCount; uint32_t fifoSize; + uint32_t tmpMCR = 0; dspi_command_data_config_t commandStruct; /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } DSPI_StopTransfer(base); - DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable); + DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); /*Calculate the command and lastCommand*/ commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); /*Calculate the bitsPerFrame*/ - bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U); - txData = transfer->txData; - rxData = transfer->rxData; - remainingSendByteCount = transfer->dataSize; + txData = transfer->txData; + rxData = transfer->rxData; + remainingSendByteCount = transfer->dataSize; remainingReceiveByteCount = transfer->dataSize; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { - fifoSize = 1; + fifoSize = 1U; } else { @@ -652,15 +951,15 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_StartTransfer(base); - if (bitsPerFrame <= 8) + if (bitsPerFrame <= 8U) { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount == 1) + if (remainingSendByteCount == 1U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -672,35 +971,36 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { base->PUSHR = (lastCommand) | (dummyData); } - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount--; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { /* Read data from POPR*/ - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { @@ -713,24 +1013,25 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } remainingSendByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { if (rxData != NULL) { - *(rxData) = DSPI_ReadData(base); + *(rxData) = (uint8_t)DSPI_ReadData(base); rxData++; } else { - DSPI_ReadData(base); + (void)DSPI_ReadData(base); } remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -738,13 +1039,13 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) } else { - while (remainingSendByteCount > 0) + while (remainingSendByteCount > 0U) { - if (remainingSendByteCount <= 2) + if (remainingSendByteCount <= 2U) { - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) @@ -752,9 +1053,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = *(txData); ++txData; - if (remainingSendByteCount > 1) + if (remainingSendByteCount > 1U) { - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } } @@ -765,52 +1066,53 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) base->PUSHR = lastCommand | wordToSend; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); remainingSendByteCount = 0; - while (remainingReceiveByteCount > 0) + while (remainingReceiveByteCount > 0U) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); - if (remainingReceiveByteCount != 1) + if (remainingReceiveByteCount != 1U) { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; - *(rxData) = wordReceived >> 8; + *(rxData) = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; } else { if (rxData != NULL) { - *(rxData) = wordReceived; + *(rxData) = (uint8_t)wordReceived; ++rxData; } remainingReceiveByteCount--; } - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } else { /*Wait until Tx Fifo is not full*/ - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) + while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } if (txData != NULL) { wordToSend = *(txData); ++txData; - wordToSend |= (unsigned)(*(txData)) << 8U; + wordToSend |= (uint16_t)(*(txData)) << 8U; ++txData; } else @@ -818,26 +1120,27 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) wordToSend = dummyData; } base->PUSHR = command | wordToSend; - remainingSendByteCount -= 2; + remainingSendByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize) { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + if ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); if (rxData != NULL) { - *rxData = wordReceived; + *rxData = (uint8_t)wordReceived; ++rxData; - *rxData = wordReceived >> 8; + *rxData = (uint8_t)(wordReceived >> 8U); ++rxData; } - remainingReceiveByteCount -= 2; + remainingReceiveByteCount -= 2U; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); } } } @@ -849,31 +1152,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); - dspi_command_data_config_t commandStruct; + uint32_t tmpMCR = 0; + dspi_command_data_config_t commandStruct = {false, kDSPI_Ctar0, kDSPI_Pcs0, false, false}; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -881,62 +1188,221 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; } +/*! + * brief DSPI master transfer data using interrupts. + * + * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; + + /* Disable the NVIC for DSPI peripheral. */ + (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); DSPI_MasterTransferPrepare(base, handle, transfer); - /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); - /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt - * Since SPI is a synchronous interface, we only need to enable the RX interrupt. - * The IRQ handler will get the status of RX and TX interrupt flags. - */ + * Since SPI is a synchronous interface, we only need to enable the RX interrupt. + * The IRQ handler will get the status of RX and TX interrupt flags. + */ s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ; - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); DSPI_StartTransfer(base); /* Fill up the Tx FIFO to trigger the transfer. */ DSPI_MasterTransferFillUpTxFifo(base, handle); + + /* Enable the NVIC for DSPI peripheral. */ + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + return kStatus_Success; } +/*! + * brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * param base DSPI base pointer + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + /* DSPI transfer blocking. */ + status = DSPI_MasterTransferBlocking(base, &tempXfer); + + return status; +} + +/*! + * brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle pointer to dspi_master_handle_t structure which stores the transfer state + * param xfer pointer to dspi_half_duplex_transfer_t structure + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer); + + return status; +} + +/*! + * brief Gets the master transfer count. + * + * This function gets the master transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -948,13 +1414,14 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -963,41 +1430,43 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } - handle->state = kDSPI_Idle; - - if (handle->callback) + if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state)) { + handle->state = (uint8_t)kDSPI_Idle; handle->callback(base, handle, status, handle->userData); } } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint16_t wordToSend = 0; - uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + size_t tmpRemainingSendByteCount = handle->remainingSendByteCount; + size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + uint8_t tmpFifoSize = handle->fifoSize; /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the - * send data, hence the difference between the remainingReceiveByteCount and - * remainingSendByteCount must be divided by 2 to convert this difference into a - * 16-bit (2 byte) value. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the + * send data, hence the difference between the remainingReceiveByteCount and + * remainingSendByteCount must be divided by 2 to convert this difference into a + * 16-bit (2 byte) value. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { wordToSend = *(handle->txData); } @@ -1005,7 +1474,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } } else @@ -1013,12 +1482,12 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } handle->remainingSendByteCount = 0; - base->PUSHR = handle->lastCommand | wordToSend; + base->PUSHR = handle->lastCommand | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ @@ -1029,32 +1498,38 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t { wordToSend = dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR = handle->command | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop. + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U)) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } /* End of TX FIFO fill while loop */ } /* Optimized for bits/frame less than or equal to one byte. */ else { /* Fill the fifo until it is full or until the send word count is 0 or until the difference - * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. - * The reason for checking the difference is to ensure we only send as much as the - * RX FIFO can receive. - */ - while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) && - ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize)) + * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth. + * The reason for checking the difference is to ensure we only send as much as the + * RX FIFO can receive. + */ + while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) && + ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -1064,7 +1539,7 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = handle->lastCommand | wordToSend; } @@ -1074,86 +1549,110 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; - /* exit loop if send count is zero, else update local variables for next loop */ - if (handle->remainingSendByteCount == 0) + /* exit loop if send count is zero, else update local variables for next loop + * If this is the first time write to the PUSHR, write only once. + */ + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U))) { break; } + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + tmpRemainingSendByteCount = handle->remainingSendByteCount; + tmpFifoSize = handle->fifoSize; } } } +/*! + * brief DSPI master aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests*/ - DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable)); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ - if (handle->remainingReceiveByteCount) + if (0U != (handle->remainingReceiveByteCount)) { /* Check read buffer.*/ uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { /* For the last word received, if there is an extra byte due to the odd transfer - * byte count, only save the the last byte and discard the upper byte - */ - if (handle->remainingReceiveByteCount == 1) + * byte count, only save the last byte and discard the upper byte + */ + if (handle->remainingReceiveByteCount == 1U) { - *handle->rxData = wordReceived; /* Write first data byte */ + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ --handle->remainingReceiveByteCount; } else { - *handle->rxData = wordReceived; /* Write first data byte */ - ++handle->rxData; /* increment to next data byte */ - *handle->rxData = wordReceived >> 8; /* Write second data byte */ - ++handle->rxData; /* increment to next data byte */ - handle->remainingReceiveByteCount -= 2; + *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */ + ++handle->rxData; /* increment to next data byte */ + *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */ + ++handle->rxData; /* increment to next data byte */ + handle->remainingReceiveByteCount -= 2U; } } else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1162,26 +1661,27 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) /* Optimized for bits/frame less than or equal to one byte. */ else { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { - wordReceived = DSPI_ReadData(base); + wordReceived = (uint16_t)DSPI_ReadData(base); /* clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* Store read bytes into rx buffer only if a buffer pointer was provided */ - if (handle->rxData) + if (NULL != handle->rxData) { - *handle->rxData = wordReceived; + *handle->rxData = (uint8_t)wordReceived; ++handle->rxData; } --handle->remainingReceiveByteCount; - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } @@ -1190,31 +1690,45 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) } /* Check write buffer. We always have to send a word in order to keep the transfer - * moving. So if the caller didn't provide a send buffer, we just send a zero. - */ - if (handle->remainingSendByteCount) + * moving. So if the caller didn't provide a send buffer, we just send a zero. + */ + if (0U != (handle->remainingSendByteCount)) { DSPI_MasterTransferFillUpTxFifo(base, handle); } /* Check if we're done with this transfer.*/ - if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0)) + if (handle->remainingSendByteCount == 0U) { - /* Complete the transfer and disable the interrupts */ - DSPI_MasterTransferComplete(base, handle); + if (handle->remainingReceiveByteCount == 0U) + { + /* Complete the transfer and disable the interrupts */ + DSPI_MasterTransferComplete(base, handle); + } } } /*Transactional APIs -- Slave*/ +/*! + * brief Initializes the DSPI slave handle. + * + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * param handle DSPI handle pointer to the dspi_slave_handle_t. + * param base DSPI peripheral base address. + * param callback DSPI callback. + * param userData Callback function parameter. + */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, dspi_slave_transfer_callback_t callback, void *userData) { - assert(handle); + assert(NULL != handle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); g_dspiHandle[DSPI_GetInstance(base)] = handle; @@ -1222,65 +1736,76 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, handle->userData = userData; } +/*! + * brief DSPI slave transfers data using an interrupt. + * + * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all + * data is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * param transfer Pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; /* Enable the NVIC for DSPI peripheral. */ - EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); + (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; handle->errorCount = 0; - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ; /* Enable RX FIFO drain request, the slave only use this interrupt */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable); - if (handle->rxData) + if (NULL != handle->rxData) { /* RX FIFO overflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable); } - if (handle->txData) + if (NULL != handle->txData) { /* TX FIFO underflow request enable */ - DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable); + DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable); } DSPI_StartTransfer(base); @@ -1291,17 +1816,27 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand return kStatus_Success; } +/*! + * brief Gets the slave transfer count. + * + * This function gets the slave transfer count. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * param count The number of bytes transferred by using the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -1313,24 +1848,24 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); uint16_t transmitData = 0; - uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); /* Service the transmitter, if transmit buffer provided, transmit the data, - * else transmit dummy pattern - */ - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + * else transmit dummy pattern + */ + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { /* Transmit data */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /* Have data to transmit, update the transmit data and push to FIFO */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { /* bits/frame is 1 byte */ - if (handle->txData) + if (NULL != handle->txData) { /* Update transmit data and transmit pointer */ transmitData = *handle->txData; @@ -1348,41 +1883,41 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * else { /* With multibytes per frame transmission, the transmit frame contains data from - * transmit buffer until sent dataSize matches user request. Other bytes will set to - * dummy pattern value. - */ - if (handle->txData) + * transmit buffer until sent dataSize matches user request. Other bytes will set to + * dummy pattern value. + */ + if (NULL != handle->txData) { /* Update first byte of transmit data and transmit pointer */ transmitData = *handle->txData; handle->txData++; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { /* Decrease remaining dataSize */ --handle->remainingSendByteCount; /* Update second byte of transmit data to second byte of dummy pattern */ - transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8); + transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U); } else { /* Update second byte of transmit data and transmit pointer */ - transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8); + transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U); handle->txData++; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern; } } } @@ -1395,26 +1930,27 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * base->PUSHR_SLAVE = transmitData; /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); } } static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); /* The transfer is complete. */ - handle->txData = NULL; - handle->rxData = NULL; + handle->txData = NULL; + handle->rxData = NULL; handle->remainingReceiveByteCount = 0; - handle->remainingSendByteCount = 0; + handle->remainingSendByteCount = 0; status_t status = 0; - if (handle->state == kDSPI_Error) + if (handle->state == (uint8_t)kDSPI_Error) { status = kStatus_DSPI_Error; } @@ -1423,69 +1959,88 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; - if (handle->callback) + if (NULL != handle->callback) { handle->callback(base, handle, status, handle->userData); } } +/*! + * brief DSPI slave aborts a transfer using an interrupt. + * + * This function aborts a transfer using an interrupt. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); /* Disable interrupt requests */ - DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | - kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); + DSPI_DisableInterrupts( + base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable | + (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable)); - handle->state = kDSPI_Idle; - handle->remainingSendByteCount = 0; + handle->state = (uint8_t)kDSPI_Idle; + handle->remainingSendByteCount = 0; handle->remainingReceiveByteCount = 0; } +/*! + * brief DSPI Master IRQ handler function. + * + * This function processes the DSPI transmit and receive IRQ. + * + * param base DSPI peripheral base address. + * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { - assert(handle); + assert(NULL != handle); - uint8_t dummyPattern = s_dummyData[DSPI_GetInstance(base)]; + uint8_t dummyPattern = DSPI_GetDummyDataInstance(base); uint32_t dataReceived; - uint32_t dataSend = 0; + uint32_t dataSend = 0; + uint32_t tmpRemainingReceiveByteCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the - * master is the actual number of bytes that the slave transmitted to the master. So we only - * monitor the received dataSize to know when the transfer is complete. - */ - if (handle->remainingReceiveByteCount > 0) + * master is the actual number of bytes that the slave transmitted to the master. So we only + * monitor the received dataSize to know when the transfer is complete. + */ + if (handle->remainingReceiveByteCount > 0U) { - while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((uint32_t)kDSPI_RxFifoDrainRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag)) { /* Have received data in the buffer. */ dataReceived = base->POPR; /*Clear the rx fifo drain request, needed for non-DMA applications as this flag - * will remain set even if the rx fifo is empty. By manually clearing this flag, it - * either remain clear if no more data is in the fifo, or it will set if there is - * more data in the fifo. - */ - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + * will remain set even if the rx fifo is empty. By manually clearing this flag, it + * either remain clear if no more data is in the fifo, or it will set if there is + * more data in the fifo. + */ + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag); /* If bits/frame is one byte */ - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - if (handle->rxData) + if (NULL != handle->rxData) { /* Receive buffer is not null, store data into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; } /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; @@ -1503,15 +2058,15 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else /* If bits/frame is 2 bytes */ { /* With multibytes frame receiving, we only receive till the received dataSize - * matches user request. Other bytes will be ignored. - */ - if (handle->rxData) + * matches user request. Other bytes will be ignored. + */ + if (NULL != handle->rxData) { /* Receive buffer is not null, store first byte into it */ - *handle->rxData = dataReceived; + *handle->rxData = (uint8_t)dataReceived; ++handle->rxData; - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; @@ -1519,72 +2074,73 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) else { /* Receive buffer is not null, store second byte into it */ - *handle->rxData = dataReceived >> 8; + *handle->rxData = (uint8_t)(dataReceived >> 8U); ++handle->rxData; - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } /* If no handle->rxData*/ else { - if (handle->remainingReceiveByteCount == 1) + if (handle->remainingReceiveByteCount == 1U) { /* Decrease remaining receive byte count */ --handle->remainingReceiveByteCount; } else { - handle->remainingReceiveByteCount -= 2; + handle->remainingReceiveByteCount -= 2U; } } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { - if (handle->txData) + if (NULL != handle->txData) { dataSend = *handle->txData; ++handle->txData; - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; - dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8); + dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U); } else { - dataSend |= (uint32_t)(*handle->txData) << 8; + dataSend |= (uint32_t)(*handle->txData) << 8U; ++handle->txData; - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } } /* If no handle->txData*/ else { - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { --handle->remainingSendByteCount; } else { - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; } - dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern; + dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern; } /* Write the data to the DSPI data register */ base->PUSHR_SLAVE = dataSend; } } /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - if (handle->remainingReceiveByteCount == 0) + if (handle->remainingReceiveByteCount == 0U) { break; } } } /* Check if remaining receive byte count matches user request */ - if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error)) + tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount; + if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U)) { /* Other cases, stop the transfer. */ DSPI_SlaveTransferComplete(base, handle); @@ -1592,26 +2148,33 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) } /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } + /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */ - if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK)) + if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag)) { - DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag); - /* Change state to error and clear flag */ - if (handle->txData) + if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK)) { - handle->state = kDSPI_Error; + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag); + /* Change state to error and clear flag */ + if (NULL != handle->txData) + { + handle->state = kDSPI_Error; + } + handle->errorCount++; } - handle->errorCount++; } } @@ -1625,12 +2188,17 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) { s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param); } +/* 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(g_dspiHandle[0]); + assert(NULL != g_dspiHandle[0]); DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]); } #endif @@ -1638,7 +2206,7 @@ void SPI0_DriverIRQHandler(void) #if defined(SPI1) void SPI1_DriverIRQHandler(void) { - assert(g_dspiHandle[1]); + assert(NULL != g_dspiHandle[1]); DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]); } #endif @@ -1646,7 +2214,7 @@ void SPI1_DriverIRQHandler(void) #if defined(SPI2) void SPI2_DriverIRQHandler(void) { - assert(g_dspiHandle[2]); + assert(NULL != g_dspiHandle[2]); DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]); } #endif @@ -1654,7 +2222,7 @@ void SPI2_DriverIRQHandler(void) #if defined(SPI3) void SPI3_DriverIRQHandler(void) { - assert(g_dspiHandle[3]); + assert(NULL != g_dspiHandle[3]); DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]); } #endif @@ -1662,7 +2230,7 @@ void SPI3_DriverIRQHandler(void) #if defined(SPI4) void SPI4_DriverIRQHandler(void) { - assert(g_dspiHandle[4]); + assert(NULL != g_dspiHandle[4]); DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]); } #endif @@ -1670,7 +2238,7 @@ void SPI4_DriverIRQHandler(void) #if defined(SPI5) void SPI5_DriverIRQHandler(void) { - assert(g_dspiHandle[5]); + assert(NULL != g_dspiHandle[5]); DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]); } #endif diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.h index 48d7353935..43416fb446 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2019 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 the copyright holder 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_DSPI_H_ #define _FSL_DSPI_H_ @@ -43,8 +21,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.2.0. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief DSPI driver version 2.2.2. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) /*@}*/ #ifndef DSPI_DUMMY_DATA @@ -55,37 +33,37 @@ /*! @brief Status for the DSPI driver.*/ enum _dspi_status { - kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ - kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ - kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ + kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ + kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ + kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ enum _dspi_flags { - kDSPI_TxCompleteFlag = SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ - kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ - kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ - kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ - kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ - kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ - kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ - kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/ + kDSPI_TxCompleteFlag = (int)SPI_SR_TCF_MASK, /*!< Transfer Complete Flag. */ + kDSPI_EndOfQueueFlag = SPI_SR_EOQF_MASK, /*!< End of Queue Flag.*/ + kDSPI_TxFifoUnderflowFlag = SPI_SR_TFUF_MASK, /*!< Transmit FIFO Underflow Flag.*/ + kDSPI_TxFifoFillRequestFlag = SPI_SR_TFFF_MASK, /*!< Transmit FIFO Fill Flag.*/ + kDSPI_RxFifoOverflowFlag = SPI_SR_RFOF_MASK, /*!< Receive FIFO Overflow Flag.*/ + kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ + kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ + kDSPI_AllStatusFlag = (int)(SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | + SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK) /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ enum _dspi_interrupt_enable { - kDSPI_TxCompleteInterruptEnable = SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ - kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ - kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ - kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ - kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ - kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ - kDSPI_AllInterruptEnable = SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | - SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK + kDSPI_TxCompleteInterruptEnable = (int)SPI_RSER_TCF_RE_MASK, /*!< TCF interrupt enable.*/ + kDSPI_EndOfQueueInterruptEnable = SPI_RSER_EOQF_RE_MASK, /*!< EOQF interrupt enable.*/ + kDSPI_TxFifoUnderflowInterruptEnable = SPI_RSER_TFUF_RE_MASK, /*!< TFUF interrupt enable.*/ + kDSPI_TxFifoFillRequestInterruptEnable = SPI_RSER_TFFF_RE_MASK, /*!< TFFF interrupt enable, DMA disable.*/ + kDSPI_RxFifoOverflowInterruptEnable = SPI_RSER_RFOF_RE_MASK, /*!< RFOF interrupt enable.*/ + kDSPI_RxFifoDrainRequestInterruptEnable = SPI_RSER_RFDF_RE_MASK, /*!< RFDF interrupt enable, DMA disable.*/ + kDSPI_AllInterruptEnable = (int)(SPI_RSER_TCF_RE_MASK | SPI_RSER_EOQF_RE_MASK | SPI_RSER_TFUF_RE_MASK | + SPI_RSER_TFFF_RE_MASK | SPI_RSER_RFOF_RE_MASK | SPI_RSER_RFDF_RE_MASK) /*!< All above interrupts enable.*/ }; @@ -102,7 +80,7 @@ enum _dspi_dma_enable typedef enum _dspi_master_slave_mode { kDSPI_Master = 1U, /*!< DSPI peripheral operates in master mode.*/ - kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ + kDSPI_Slave = 0U /*!< DSPI peripheral operates in slave mode.*/ } dspi_master_slave_mode_t; /*! @@ -132,26 +110,26 @@ typedef enum _dspi_which_pcs_config typedef enum _dspi_pcs_polarity_config { kDSPI_PcsActiveHigh = 0U, /*!< Pcs Active High (idles low). */ - kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ + kDSPI_PcsActiveLow = 1U /*!< Pcs Active Low (idles high). */ } dspi_pcs_polarity_config_t; /*! @brief DSPI Peripheral Chip Select (Pcs) Polarity.*/ enum _dspi_pcs_polarity { - kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ - kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ - kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ - kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ - kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ - kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ - kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ + kDSPI_Pcs0ActiveLow = 1U << 0, /*!< Pcs0 Active Low (idles high). */ + kDSPI_Pcs1ActiveLow = 1U << 1, /*!< Pcs1 Active Low (idles high). */ + kDSPI_Pcs2ActiveLow = 1U << 2, /*!< Pcs2 Active Low (idles high). */ + kDSPI_Pcs3ActiveLow = 1U << 3, /*!< Pcs3 Active Low (idles high). */ + kDSPI_Pcs4ActiveLow = 1U << 4, /*!< Pcs4 Active Low (idles high). */ + kDSPI_Pcs5ActiveLow = 1U << 5, /*!< Pcs5 Active Low (idles high). */ + kDSPI_PcsAllActiveLow = 0xFFU /*!< Pcs0 to Pcs5 Active Low (idles high). */ }; /*! @brief DSPI clock polarity configuration for a given CTAR.*/ typedef enum _dspi_clock_polarity { kDSPI_ClockPolarityActiveHigh = 0U, /*!< CPOL=0. Active-high DSPI clock (idles low).*/ - kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ + kDSPI_ClockPolarityActiveLow = 1U /*!< CPOL=1. Active-low DSPI clock (idles high).*/ } dspi_clock_polarity_t; /*! @brief DSPI clock phase configuration for a given CTAR.*/ @@ -315,13 +293,13 @@ typedef struct _dspi_slave_config } dspi_slave_config_t; /*! -* @brief Forward declaration of the _dspi_master_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_master_handle typedefs. + */ typedef struct _dspi_master_handle dspi_master_handle_t; /*! -* @brief Forward declaration of the _dspi_slave_handle typedefs. -*/ + * @brief Forward declaration of the _dspi_slave_handle typedefs. + */ typedef struct _dspi_slave_handle dspi_slave_handle_t; /*! @@ -356,12 +334,24 @@ typedef struct _dspi_transfer uint8_t *rxData; /*!< Receive buffer. */ volatile size_t dataSize; /*!< Transfer bytes. */ - uint32_t - configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the - transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer - is used for slave.*/ + uint32_t configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if + the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the + transfer is used for slave.*/ } dspi_transfer_t; +/*! @brief DSPI half-duplex(master) transfer structure */ +typedef struct _dspi_half_duplex_transfer +{ + uint8_t *txData; /*!< Send buffer */ + uint8_t *rxData; /*!< Receive buffer */ + size_t txDataSize; /*!< Transfer bytes for transmit */ + size_t rxDataSize; /*!< Transfer bytes */ + uint32_t configFlags; /*!< Transfer configuration flags; set from _dspi_transfer_config_flag_for_master. */ + bool isPcsAssertInTransfer; /*!< If Pcs pin keep assert between transmit and receive. true for assert and false for + deassert. */ + bool isTransmitFirst; /*!< True for transmit first and false for receive first. */ +} dspi_half_duplex_transfer_t; + /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { @@ -527,7 +517,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! *@} -*/ + */ /*! * @name Status @@ -565,7 +555,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! *@} -*/ + */ /*! * @name Interrupts @@ -605,7 +595,7 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! *@} -*/ + */ /*! * @name DMA Control @@ -685,12 +675,18 @@ static inline uint32_t DSPI_GetRxRegisterAddress(SPI_Type *base) /*! *@} -*/ + */ /*! * @name Bus Operations * @{ */ +/*! + * @brief Get instance number for DSPI module. + * + * @param base DSPI peripheral base address. + */ +uint32_t DSPI_GetInstance(SPI_Type *base); /*! * @brief Configures the DSPI for master or slave. @@ -711,7 +707,14 @@ static inline void DSPI_SetMasterSlaveMode(SPI_Type *base, dspi_master_slave_mod */ static inline bool DSPI_IsMaster(SPI_Type *base) { - return (bool)((base->MCR) & SPI_MCR_MSTR_MASK); + if (0U != ((base->MCR) & SPI_MCR_MSTR_MASK)) + { + return true; + } + else + { + return false; + } } /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. @@ -749,8 +752,8 @@ static inline void DSPI_StopTransfer(SPI_Type *base) */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | SPI_MCR_DIS_TXF(!enableTxFifo) | - SPI_MCR_DIS_RXF(!enableRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_DIS_RXF_MASK | SPI_MCR_DIS_TXF_MASK))) | + SPI_MCR_DIS_TXF((false == enableTxFifo ? 1U : 0U)) | SPI_MCR_DIS_RXF((false == enableRxFifo ? 1U : 0U)); } /*! @@ -762,8 +765,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { - base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | SPI_MCR_CLR_TXF(flushTxFifo) | - SPI_MCR_CLR_RXF(flushRxFifo); + base->MCR = (base->MCR & (~(SPI_MCR_CLR_TXF_MASK | SPI_MCR_CLR_RXF_MASK))) | + SPI_MCR_CLR_TXF((true == flushTxFifo ? 1U : 0U)) | SPI_MCR_CLR_RXF((true == flushRxFifo ? 1U : 0U)); } /*! @@ -954,11 +957,11 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * buffer master mode and waits till complete to return. * * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total -* 32-bit word + * 32-bit word * as the data to send. * The command portion provides characteristics of the data, such as the optional continuous chip select operation * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the -* desired PCS + * desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: @@ -973,20 +976,20 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * * For a blocking polling transfer, see methods below. * Option 1: -* uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); -* uint32_t data0 = command_to_send | data_need_to_send_0; -* uint32_t data1 = command_to_send | data_need_to_send_1; -* uint32_t data2 = command_to_send | data_need_to_send_2; -* -* DSPI_MasterWriteCommandDataBlocking(base,data0); -* DSPI_MasterWriteCommandDataBlocking(base,data1); -* DSPI_MasterWriteCommandDataBlocking(base,data2); -* -* Option 2: -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); -* DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); -* + * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command); + * uint32_t data0 = command_to_send | data_need_to_send_0; + * uint32_t data1 = command_to_send | data_need_to_send_1; + * uint32_t data2 = command_to_send | data_need_to_send_2; + * + * DSPI_MasterWriteCommandDataBlocking(base,data0); + * DSPI_MasterWriteCommandDataBlocking(base,data1); + * DSPI_MasterWriteCommandDataBlocking(base,data2); + * + * Option 2: + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1); + * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); + * * @param base DSPI peripheral address. * @param data The data word (command and data combined) to be sent. */ @@ -1037,7 +1040,7 @@ void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData); /*! *@} -*/ + */ /*! * @name Transactional @@ -1086,6 +1089,35 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a polling method. + * + * This function will do a half-duplex transfer for DSPI master, This is a blocking function, + * which does not retuen until all transfer have been completed. And data transfer will be half-duplex, + * users can set transmit first or receive first. + * + * @param base DSPI base pointer + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer); + +/*! + * @brief Performs a non-blocking DSPI interrupt transfer. + * + * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking + * function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI peripheral base address. + * @param handle pointer to dspi_master_handle_t structure which stores the transfer state + * @param xfer pointer to dspi_half_duplex_transfer_t structure + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base, + dspi_master_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief Gets the master transfer count. * @@ -1179,15 +1211,25 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); +/*! + * brief Dummy data for each instance. + * + * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of + * externally-linked object or function g_dspiDummyData. + * + * param base DSPI peripheral base address. + */ +uint8_t DSPI_GetDummyDataInstance(SPI_Type *base); + /*! *@} -*/ + */ #if defined(__cplusplus) } #endif /*_cplusplus*/ /*! *@} - */ + */ #endif /*_FSL_DSPI_H_*/ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.c index 467c892ff4..7e535a35c0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.c @@ -1,42 +1,25 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2018 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 the copyright holder 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_dspi_edma.h" /*********************************************************************************************************************** -* Definitons -***********************************************************************************************************************/ + * Definitions + ***********************************************************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.dspi_edma" +#endif /*! -* @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_master_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -44,8 +27,8 @@ typedef struct _dspi_master_edma_private_handle } dspi_master_edma_private_handle_t; /*! -* @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. -*/ + * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private. + */ typedef struct _dspi_slave_edma_private_handle { SPI_Type *base; /*!< DSPI peripheral base address. */ @@ -53,48 +36,58 @@ typedef struct _dspi_slave_edma_private_handle } dspi_slave_edma_private_handle_t; /*********************************************************************************************************************** -* Prototypes -***********************************************************************************************************************/ + * Prototypes + ***********************************************************************************************************************/ /*! -* @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API. -*/ + * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); /*! -* @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API. -*/ + * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. + * This is not a public API. + */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds); -/*! -* @brief Get instance number for DSPI module. -* -* This is not a public API and it's extern from fsl_dspi.c. -* -* @param base DSPI peripheral base address -*/ -extern uint32_t DSPI_GetInstance(SPI_Type *base); /*********************************************************************************************************************** -* Variables -***********************************************************************************************************************/ + * Variables + ***********************************************************************************************************************/ /*! @brief Pointers to dspi edma handles for each instance. */ static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT]; -/*! @brief Global variable for dummy data value setting. */ -extern volatile uint8_t s_dummyData[]; /*********************************************************************************************************************** -* Code -***********************************************************************************************************************/ + * Code + ***********************************************************************************************************************/ +/*! + * brief Initializes the DSPI master eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaIntermediaryToTxRegHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_master_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. + * param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. + */ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_master_edma_transfer_callback_t callback, @@ -103,59 +96,72 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToIntermediaryHandle, edma_handle_t *edmaIntermediaryToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); #if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET)) - assert(edmaTxDataToIntermediaryHandle); + assert(NULL != edmaTxDataToIntermediaryHandle); #endif - assert(edmaIntermediaryToTxRegHandle); + assert(NULL != edmaIntermediaryToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiMasterEdmaPrivateHandle[instance].base = base; + s_dspiMasterEdmaPrivateHandle[instance].base = base; s_dspiMasterEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; handle->userData = userData; - handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; + handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle; handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle; - handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; + handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle; } +/*! + * brief DSPI master transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If the transfer count is zero, then return immediately.*/ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; - uint32_t instance = DSPI_GetInstance(base); - uint16_t wordToSend = 0; - uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; - uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint32_t instance = DSPI_GetInstance(base); + uint16_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); + uint8_t dataAlreadyFed = 0; + uint8_t dataFedMax = 2; + uint32_t tmpMCR = 0; + size_t tmpRemainingSendByteCount = 0; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base); @@ -165,29 +171,32 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigA; edma_transfer_config_t transferConfigB; - handle->txBuffIfNull = ((uint32_t)dummyData << 8) | dummyData; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); commandStruct.whichPcs = - (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); - commandStruct.isEndOfQueue = false; + (dspi_which_pcs_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT)); + commandStruct.isEndOfQueue = false; commandStruct.clearTransferCount = false; commandStruct.whichCtar = (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT); - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false; handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct)); commandStruct.isEndOfQueue = true; - commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer); + commandStruct.isPcsContinuous = + (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false; handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct)); - handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1; + handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U; - if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK)) + tmpMCR = base->MCR; + if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK))) { handle->fifoSize = 1; } @@ -195,15 +204,15 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base); } - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ uint32_t limited_size = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { @@ -214,11 +223,11 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand limited_size = 511u; } - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { if (transfer->dataSize > (limited_size << 1u)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } @@ -226,19 +235,19 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (transfer->dataSize > limited_size) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); @@ -271,47 +280,47 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to - * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel - */ + * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel + */ /*Prepare the firt data*/ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { /* If it's the last word */ - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - handle->command = handle->lastCommand; + handle->command = handle->lastCommand; } else /* For all words except the last word , frame > 8bits */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; /* increment to next data byte */ } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->command = (handle->command & 0xffff0000U) | wordToSend; } } else /* Optimized for bits/frame less than or equal to one byte. */ { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* increment to next data word*/ @@ -321,10 +330,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - handle->command = handle->lastCommand; + handle->command = handle->lastCommand; } else { @@ -340,50 +349,51 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->remainingSendByteCount <= 2) + if (handle->remainingSendByteCount <= 2U) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->remainingSendByteCount = 0; - base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; + base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } /* For all words except the last word */ else { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; + wordToSend |= (uint16_t)(*(handle->txData)) << 8U; ++handle->txData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } - handle->remainingSendByteCount -= 2; + handle->remainingSendByteCount -= 2U; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -391,9 +401,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; @@ -403,7 +414,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand wordToSend = dummyData; } - if (handle->remainingSendByteCount == 1) + if (handle->remainingSendByteCount == 1U) { base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -413,14 +424,14 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); --handle->remainingSendByteCount; dataAlreadyFed++; /* exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -431,62 +442,63 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); + tmpRemainingSendByteCount = handle->remainingSendByteCount; /*Calculate the last data : handle->lastCommand*/ - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) + if (((tmpRemainingSendByteCount > 0U) && (1U != (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U))) && + (1U == (uint8_t)FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - if (handle->txData) + if (NULL != handle->txData) { uint32_t bufferIndex = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - bufferIndex = handle->remainingSendByteCount - 1; + bufferIndex = handle->remainingSendByteCount - 1U; } else { - bufferIndex = handle->remainingSendByteCount - 2; + bufferIndex = handle->remainingSendByteCount - 2U; } } else @@ -494,26 +506,30 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand bufferIndex = handle->remainingSendByteCount; } - if (handle->bitsPerFrame <= 8) + uint32_t tmpLastCommand = handle->lastCommand; + uint8_t *tmpTxData = handle->txData; + + if (handle->bitsPerFrame <= 8U) { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | tmpTxData[bufferIndex - 1U]; } else { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; + tmpLastCommand = (tmpLastCommand & 0xffff0000U) | ((uint32_t)tmpTxData[bufferIndex - 1U] << 8U) | + tmpTxData[bufferIndex - 2U]; } + + handle->lastCommand = tmpLastCommand; } else { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { wordToSend = dummyData; } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = (((uint16_t)dummyData << 8U) | (uint16_t)dummyData); } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; } @@ -539,22 +555,22 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) { - transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigB.destAddr = (uint32_t)txAddr; - transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigB.srcOffset = 0; - transferConfigB.destOffset = 0; - transferConfigB.minorLoopBytes = 4; - transferConfigB.majorLoopCounts = 1; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); } /*User_Send_Buffer(txData) to PUSHR register. */ - if (((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) + if (((handle->remainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((handle->remainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) { if (handle->txData) { @@ -564,7 +580,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand * to handle->command, so need to reduce the pointer of txData. */ transferConfigB.srcAddr = - (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8) ? (1U) : (2U))); + (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8U) ? (1U) : (2U))); transferConfigB.srcOffset = 1; } else @@ -572,33 +588,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry * to PUSHR register, so no need to change the pointer of txData. */ - transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); + transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData)); transferConfigB.srcOffset = 1; } } else { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigB.srcOffset = 0; } - transferConfigB.destAddr = (uint32_t)txAddr; + transferConfigB.destAddr = (uint32_t)txAddr; transferConfigB.destOffset = 0; transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; + transferConfigB.minorLoopBytes = 1; - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1U; } else { transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; - transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2) - 1; + transferConfigB.minorLoopBytes = 2; + transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, @@ -623,21 +639,21 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, &preemption_config_t); @@ -647,7 +663,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to channelC to carry the next data to PUSHER register.(txData to PUSHER) */ - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); @@ -670,90 +686,94 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand * (handle->lastCommand) to handle->Command*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigB.destAddr = (uint32_t) & (handle->command); - transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigB.srcOffset = 0; - transferConfigB.destOffset = 0; - transferConfigB.minorLoopBytes = 4; - transferConfigB.majorLoopCounts = 1; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); } + tmpRemainingSendByteCount = handle->remainingSendByteCount; /*User_Send_Buffer(txData) to intermediary(handle->command)*/ - if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) && + if (((((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 4U) && (handle->bitsPerFrame > 8U))) && (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { - if (handle->txData) + if (NULL != handle->txData) { - transferConfigB.srcAddr = (uint32_t)(handle->txData); + transferConfigB.srcAddr = (uint32_t)(handle->txData); transferConfigB.srcOffset = 1; } else { - transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigB.srcOffset = 0; } - transferConfigB.destAddr = (uint32_t)(&handle->command); + transferConfigB.destAddr = (uint32_t)(&handle->command); transferConfigB.destOffset = 0; transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigB.minorLoopBytes = 1; + transferConfigB.minorLoopBytes = 1; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2U; } else { /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is majorlink , the majorlink would not trigger the channel_C*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1U; } } else { transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigB.minorLoopBytes = 2; + transferConfigB.minorLoopBytes = 2; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U - 2U; } else { /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is - * majorlink*/ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1; + * majorlink*/ + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2U + 1U; } } if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, softwareTCD); EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } else { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); } } else { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigB, NULL); } /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to @@ -762,55 +782,59 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand edma_transfer_config_t transferConfigC; EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); + tmpRemainingSendByteCount = handle->remainingSendByteCount; /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data * (handle->lastCommand) to SPI_PUSHR*/ - if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (tmpRemainingSendByteCount > 0U))) { - transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; + transferConfigC.majorLoopCounts = 1; EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); + EDMA_TcdSetTransferConfig(softwareTCD, (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } - if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) || + tmpRemainingSendByteCount = handle->remainingSendByteCount; + if (((tmpRemainingSendByteCount > 1U) && (handle->bitsPerFrame <= 8U)) || + ((tmpRemainingSendByteCount > 2U) && (handle->bitsPerFrame > 8U)) || (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { - transferConfigC.srcAddr = (uint32_t)(&(handle->command)); + transferConfigC.srcAddr = (uint32_t)(&(handle->command)); transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; + transferConfigC.srcOffset = 0; + transferConfigC.destOffset = 0; + transferConfigC.minorLoopBytes = 4; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1U; } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigC.majorLoopCounts = (handle->remainingSendByteCount / 2U) - 1U; } EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, softwareTCD); } else { transferConfigC.majorLoopCounts = 1; EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, @@ -819,7 +843,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand else { EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); } /*Start the EDMA channel_A , channel_B , channel_C transfer*/ @@ -828,60 +853,64 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; - uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel; uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityMid) { - t = channelPriorityLow; + t = channelPriorityLow; channelPriorityLow = channelPriorityMid; channelPriorityMid = t; } if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } if (channelPriorityMid > channelPriorityHigh) { - t = channelPriorityMid; - channelPriorityMid = channelPriorityHigh; + t = channelPriorityMid; + channelPriorityMid = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t); + handle->edmaIntermediaryToTxRegHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityMid; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base, - handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t); + handle->edmaTxDataToIntermediaryHandle->channel, + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link.*/ @@ -889,18 +918,18 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB to prepare the next 32bits data (txData to handle->command) */ - if (handle->remainingSendByteCount > 1) + if (handle->remainingSendByteCount > 1U) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } else { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); @@ -910,7 +939,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->edmaIntermediaryToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } #endif DSPI_StartTransfer(base); @@ -918,55 +947,139 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand return kStatus_Success; } +/*! + * brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * param base DSPI base pointer + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer) +{ + assert(NULL != xfer); + assert(NULL != handle); + dspi_transfer_t tempXfer = {0}; + status_t status; + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + else + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + /* If the pcs pin keep assert between transmit and receive. */ + if (true == xfer->isPcsAssertInTransfer) + { + tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer; + } + else + { + tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer); + } + + status = DSPI_MasterTransferBlocking(base, &tempXfer); + if (status != kStatus_Success) + { + return status; + } + + if (true == xfer->isTransmitFirst) + { + tempXfer.txData = NULL; + tempXfer.rxData = xfer->rxData; + tempXfer.dataSize = xfer->rxDataSize; + } + else + { + tempXfer.txData = xfer->txData; + tempXfer.rxData = NULL; + tempXfer.dataSize = xfer->txDataSize; + } + tempXfer.configFlags = xfer->configFlags; + + status = DSPI_MasterTransferEDMA(base, handle, &tempXfer); + + return status; +} static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } } +/*! + * brief DSPI master aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle); EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the master eDMA transfer count. + * + * This function gets the master eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; @@ -982,6 +1095,25 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle return kStatus_Success; } +/*! + * brief Initializes the DSPI slave eDMA handle. + * + * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a + * specified DSPI instance, call this API once to get the initialized handle. + * + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. + * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * TX DMAMUX source for edmaTxDataToTxRegHandle. + * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * + * param base DSPI peripheral base address. + * param handle DSPI handle pointer to dspi_slave_edma_handle_t. + * param callback DSPI callback. + * param userData A callback function parameter. + * param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. + * param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. + */ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_slave_edma_transfer_callback_t callback, @@ -989,16 +1121,16 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaRxRegToRxDataHandle, edma_handle_t *edmaTxDataToTxRegHandle) { - assert(handle); - assert(edmaRxRegToRxDataHandle); - assert(edmaTxDataToTxRegHandle); + assert(NULL != handle); + assert(NULL != edmaRxRegToRxDataHandle); + assert(NULL != edmaTxDataToTxRegHandle); /* Zero the handle. */ - memset(handle, 0, sizeof(*handle)); + (void)memset(handle, 0, sizeof(*handle)); uint32_t instance = DSPI_GetInstance(base); - s_dspiSlaveEdmaPrivateHandle[instance].base = base; + s_dspiSlaveEdmaPrivateHandle[instance].base = base; s_dspiSlaveEdmaPrivateHandle[instance].handle = handle; handle->callback = callback; @@ -1008,39 +1140,52 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle; } +/*! + * brief DSPI slave transfer data using eDMA. + * + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. + + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param transfer A pointer to the dspi_transfer_t structure. + * return status of status_t. + */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle); - assert(transfer); + assert(NULL != handle); + assert(NULL != transfer); /* If send/receive length is zero */ - if (transfer->dataSize == 0) + if (transfer->dataSize == 0U) { return kStatus_InvalidArgument; } /* If both send buffer and receive buffer is null */ - if ((!(transfer->txData)) && (!(transfer->rxData))) + if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData))) { return kStatus_InvalidArgument; } /* Check that we're not busy.*/ - if (handle->state == kDSPI_Busy) + if (handle->state == (uint8_t)kDSPI_Busy) { return kStatus_DSPI_Busy; } - handle->state = kDSPI_Busy; + handle->state = (uint8_t)kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); - uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; + uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT); handle->bitsPerFrame = - (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1; + (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U; /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer - * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame - */ + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + */ uint32_t limited_size = 0; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { @@ -1051,11 +1196,11 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle limited_size = 511u; } - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { if (transfer->dataSize > (limited_size << 1u)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } @@ -1063,31 +1208,31 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle { if (transfer->dataSize > limited_size) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ - if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + if ((0U != (transfer->dataSize & 0x1U)) && (handle->bitsPerFrame > 8U)) { - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); /* Store transfer information */ - handle->txData = transfer->txData; - handle->rxData = transfer->rxData; - handle->remainingSendByteCount = transfer->dataSize; + handle->txData = transfer->txData; + handle->rxData = transfer->rxData; + handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; - handle->totalByteCount = transfer->dataSize; + handle->totalByteCount = transfer->dataSize; - uint16_t wordToSend = 0; - uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)]; + uint32_t wordToSend = 0; + uint8_t dummyData = DSPI_GetDummyDataInstance(base); uint8_t dataAlreadyFed = 0; - uint8_t dataFedMax = 2; + uint8_t dataFedMax = 2; uint32_t rxAddr = DSPI_GetRxRegisterAddress(base); uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base); @@ -1098,9 +1243,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); - DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); DSPI_StartTransfer(base); @@ -1110,14 +1255,15 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to - * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. - */ + * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel. + */ /* If bits/frame is greater than one byte */ - if (handle->bitsPerFrame > 8) + if (handle->bitsPerFrame > 8U) { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ @@ -1127,18 +1273,18 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; + wordToSend = ((uint32_t)dummyData << 8U) | dummyData; } - handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */ + handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */ base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); - dataAlreadyFed += 2; + dataAlreadyFed += 2U; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2))) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == (dataFedMax * 2U))) { break; } @@ -1146,9 +1292,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } else /* Optimized for bits/frame less than or equal to one byte. */ { - while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) + while ((uint32_t)kDSPI_TxFifoFillRequestFlag == + (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) { - if (handle->txData) + if (NULL != handle->txData) { wordToSend = *(handle->txData); /* Increment to next data word*/ @@ -1162,14 +1309,14 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle base->PUSHR_SLAVE = wordToSend; /* Try to clear the TFFF; if the TX FIFO is full this will clear */ - DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); + DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag); /* Decrement remainingSendByteCount*/ --handle->remainingSendByteCount; dataAlreadyFed++; /* Exit loop if send count is zero, else update local variables for next loop */ - if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax)) + if ((handle->remainingSendByteCount == 0U) || (dataAlreadyFed == dataFedMax)) { break; } @@ -1178,92 +1325,92 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle } /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ - if (handle->remainingReceiveByteCount > 0) + if (handle->remainingReceiveByteCount > 0U) { EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); - transferConfigA.srcAddr = (uint32_t)rxAddr; + transferConfigA.srcAddr = (uint32_t)rxAddr; transferConfigA.srcOffset = 0; - if (handle->rxData) + if (NULL != handle->rxData) { - transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); + transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]); transferConfigA.destOffset = 1; } else { - transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); + transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull); transferConfigA.destOffset = 0; } transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes; - transferConfigA.minorLoopBytes = 1; + transferConfigA.minorLoopBytes = 1; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount; } else { transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes; - transferConfigA.minorLoopBytes = 2; - transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; + transferConfigA.minorLoopBytes = 2; + transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2U; } /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ - handle->nbytes = transferConfigA.minorLoopBytes; + handle->nbytes = (uint8_t)(transferConfigA.minorLoopBytes); EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &transferConfigA, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorInterruptEnable); + (uint32_t)kEDMA_MajorInterruptEnable); } - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destAddr = (uint32_t)txAddr; transferConfigC.destOffset = 0; - if (handle->txData) + if (NULL != handle->txData) { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); transferConfigC.srcOffset = 1; } else { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { handle->txBuffIfNull = dummyData; } else { - handle->txBuffIfNull = ((uint32_t)dummyData << 8) | dummyData; + handle->txBuffIfNull = ((uint32_t)dummyData << 8U) | dummyData; } } transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - if (handle->bitsPerFrame <= 8) + if (handle->bitsPerFrame <= 8U) { transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; } else { transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2U; } EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + (const edma_transfer_config_t *)(uint32_t)&transferConfigC, NULL); EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } @@ -1271,39 +1418,39 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); /*Set channel priority*/ - uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; + uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel; uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel; - uint8_t t = 0; + uint8_t t = 0; if (channelPriorityLow > channelPriorityHigh) { - t = channelPriorityLow; - channelPriorityLow = channelPriorityHigh; + t = channelPriorityLow; + channelPriorityLow = channelPriorityHigh; channelPriorityHigh = t; } edma_channel_Preemption_config_t preemption_config_t; preemption_config_t.enableChannelPreemption = true; - preemption_config_t.enablePreemptAbility = true; - preemption_config_t.channelPriority = channelPriorityLow; + preemption_config_t.enablePreemptAbility = true; + preemption_config_t.channelPriority = channelPriorityLow; if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } else { EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); preemption_config_t.channelPriority = channelPriorityHigh; EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - &preemption_config_t); + (const edma_channel_Preemption_config_t *)(uint32_t)&preemption_config_t); } /*Set the channel link. @@ -1313,16 +1460,16 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle Tx DMA request -> channel_C */ if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->remainingSendByteCount > 0) + if (handle->remainingSendByteCount > 0U) { EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel); } - DSPI_EnableDMA(base, kDSPI_RxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable); } else { - DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_EnableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); } return kStatus_Success; @@ -1333,49 +1480,67 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { - assert(edmaHandle); - assert(g_dspiEdmaPrivateHandle); + assert(NULL != edmaHandle); + assert(NULL != g_dspiEdmaPrivateHandle); dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA((dspiEdmaPrivateHandle->base), (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; + dspiEdmaPrivateHandle->handle->state = (uint8_t)kDSPI_Idle; - if (dspiEdmaPrivateHandle->handle->callback) + if (NULL != dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } } +/*! + * brief DSPI slave aborts a transfer which is using eDMA. + * + * This function aborts a transfer which is using eDMA. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { - assert(handle); + assert(NULL != handle); DSPI_StopTransfer(base); - DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); + DSPI_DisableDMA(base, (uint32_t)kDSPI_RxDmaEnable | (uint32_t)kDSPI_TxDmaEnable); EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle); EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle); - handle->state = kDSPI_Idle; + handle->state = (uint8_t)kDSPI_Idle; } +/*! + * brief Gets the slave eDMA transfer count. + * + * This function gets the slave eDMA transfer count. + * + * param base DSPI peripheral base address. + * param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * param count A number of bytes transferred so far by the non-blocking transaction. + * return status of status_t. + */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count) { - assert(handle); + assert(NULL != handle); - if (!count) + if (NULL == count) { return kStatus_InvalidArgument; } /* Catch when there is not an active transfer. */ - if (handle->state != kDSPI_Busy) + if (handle->state != (uint8_t)kDSPI_Busy) { *count = 0; return kStatus_NoTransferInProgress; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.h index 23e29ce298..8f4ffe96e3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_dspi_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * Copyright 2016-2017 NXP + * Copyright 2016-2018 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 the copyright holder 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_DSPI_EDMA_H_ #define _FSL_DSPI_EDMA_H_ @@ -41,14 +19,20 @@ * Definitions **********************************************************************************************************************/ +/*! @name Driver version */ +/*@{*/ +/*! @brief DSPI EDMA driver version 2.2.2. */ +#define FSL_DSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 2)) +/*@}*/ + /*! -* @brief Forward declaration of the DSPI eDMA master handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA master handle typedefs. + */ typedef struct _dspi_master_edma_handle dspi_master_edma_handle_t; /*! -* @brief Forward declaration of the DSPI eDMA slave handle typedefs. -*/ + * @brief Forward declaration of the DSPI eDMA slave handle typedefs. + */ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; /*! @@ -186,6 +170,21 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer); +/*! + * @brief Transfers a block of data using a eDMA method. + * + * This function transfers data using eDNA, the transfer mechanism is half-duplex. This is a non-blocking function, + * which returns right away. When all data is transferred, the callback function is called. + * + * @param base DSPI base pointer + * @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * @param transfer A pointer to the dspi_half_duplex_transfer_t structure. + * @return status of status_t. + */ +status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base, + dspi_master_edma_handle_t *handle, + dspi_half_duplex_transfer_t *xfer); + /*! * @brief DSPI master aborts a transfer which is using eDMA. *