Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /*
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
kadonotakashi 0:8fdf9a60065b 3 * All rights reserved.
kadonotakashi 0:8fdf9a60065b 4 *
kadonotakashi 0:8fdf9a60065b 5 * Redistribution and use in source and binary forms, with or without modification,
kadonotakashi 0:8fdf9a60065b 6 * are permitted provided that the following conditions are met:
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * o Redistributions of source code must retain the above copyright notice, this list
kadonotakashi 0:8fdf9a60065b 9 * of conditions and the following disclaimer.
kadonotakashi 0:8fdf9a60065b 10 *
kadonotakashi 0:8fdf9a60065b 11 * o Redistributions in binary form must reproduce the above copyright notice, this
kadonotakashi 0:8fdf9a60065b 12 * list of conditions and the following disclaimer in the documentation and/or
kadonotakashi 0:8fdf9a60065b 13 * other materials provided with the distribution.
kadonotakashi 0:8fdf9a60065b 14 *
kadonotakashi 0:8fdf9a60065b 15 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
kadonotakashi 0:8fdf9a60065b 16 * contributors may be used to endorse or promote products derived from this
kadonotakashi 0:8fdf9a60065b 17 * software without specific prior written permission.
kadonotakashi 0:8fdf9a60065b 18 *
kadonotakashi 0:8fdf9a60065b 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
kadonotakashi 0:8fdf9a60065b 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
kadonotakashi 0:8fdf9a60065b 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
kadonotakashi 0:8fdf9a60065b 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
kadonotakashi 0:8fdf9a60065b 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
kadonotakashi 0:8fdf9a60065b 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
kadonotakashi 0:8fdf9a60065b 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
kadonotakashi 0:8fdf9a60065b 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
kadonotakashi 0:8fdf9a60065b 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
kadonotakashi 0:8fdf9a60065b 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
kadonotakashi 0:8fdf9a60065b 29 */
kadonotakashi 0:8fdf9a60065b 30
kadonotakashi 0:8fdf9a60065b 31 #include "fsl_dspi.h"
kadonotakashi 0:8fdf9a60065b 32
kadonotakashi 0:8fdf9a60065b 33 /*******************************************************************************
kadonotakashi 0:8fdf9a60065b 34 * Definitions
kadonotakashi 0:8fdf9a60065b 35 ******************************************************************************/
kadonotakashi 0:8fdf9a60065b 36 /*! @brief Typedef for master interrupt handler. */
kadonotakashi 0:8fdf9a60065b 37 typedef void (*dspi_master_isr_t)(SPI_Type *base, dspi_master_handle_t *handle);
kadonotakashi 0:8fdf9a60065b 38
kadonotakashi 0:8fdf9a60065b 39 /*! @brief Typedef for slave interrupt handler. */
kadonotakashi 0:8fdf9a60065b 40 typedef void (*dspi_slave_isr_t)(SPI_Type *base, dspi_slave_handle_t *handle);
kadonotakashi 0:8fdf9a60065b 41
kadonotakashi 0:8fdf9a60065b 42 /*******************************************************************************
kadonotakashi 0:8fdf9a60065b 43 * Prototypes
kadonotakashi 0:8fdf9a60065b 44 ******************************************************************************/
kadonotakashi 0:8fdf9a60065b 45 /*!
kadonotakashi 0:8fdf9a60065b 46 * @brief Get instance number for DSPI module.
kadonotakashi 0:8fdf9a60065b 47 *
kadonotakashi 0:8fdf9a60065b 48 * @param base DSPI peripheral base address.
kadonotakashi 0:8fdf9a60065b 49 */
kadonotakashi 0:8fdf9a60065b 50 uint32_t DSPI_GetInstance(SPI_Type *base);
kadonotakashi 0:8fdf9a60065b 51
kadonotakashi 0:8fdf9a60065b 52 /*!
kadonotakashi 0:8fdf9a60065b 53 * @brief Configures the DSPI peripheral chip select polarity.
kadonotakashi 0:8fdf9a60065b 54 *
kadonotakashi 0:8fdf9a60065b 55 * This function takes in the desired peripheral chip select (Pcs) and it's corresponding desired polarity and
kadonotakashi 0:8fdf9a60065b 56 * configures the Pcs signal to operate with the desired characteristic.
kadonotakashi 0:8fdf9a60065b 57 *
kadonotakashi 0:8fdf9a60065b 58 * @param base DSPI peripheral address.
kadonotakashi 0:8fdf9a60065b 59 * @param pcs The particular peripheral chip select (parameter value is of type dspi_which_pcs_t) for which we wish to
kadonotakashi 0:8fdf9a60065b 60 * apply the active high or active low characteristic.
kadonotakashi 0:8fdf9a60065b 61 * @param activeLowOrHigh The setting for either "active high, inactive low (0)" or "active low, inactive high(1)" of
kadonotakashi 0:8fdf9a60065b 62 * type dspi_pcs_polarity_config_t.
kadonotakashi 0:8fdf9a60065b 63 */
kadonotakashi 0:8fdf9a60065b 64 static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh);
kadonotakashi 0:8fdf9a60065b 65
kadonotakashi 0:8fdf9a60065b 66 /*!
kadonotakashi 0:8fdf9a60065b 67 * @brief Master fill up the TX FIFO with data.
kadonotakashi 0:8fdf9a60065b 68 * This is not a public API as it is called from other driver functions.
kadonotakashi 0:8fdf9a60065b 69 */
kadonotakashi 0:8fdf9a60065b 70 static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle);
kadonotakashi 0:8fdf9a60065b 71
kadonotakashi 0:8fdf9a60065b 72 /*!
kadonotakashi 0:8fdf9a60065b 73 * @brief Master finish up a transfer.
kadonotakashi 0:8fdf9a60065b 74 * It would call back if there is callback function and set the state to idle.
kadonotakashi 0:8fdf9a60065b 75 * This is not a public API as it is called from other driver functions.
kadonotakashi 0:8fdf9a60065b 76 */
kadonotakashi 0:8fdf9a60065b 77 static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle);
kadonotakashi 0:8fdf9a60065b 78
kadonotakashi 0:8fdf9a60065b 79 /*!
kadonotakashi 0:8fdf9a60065b 80 * @brief Slave fill up the TX FIFO with data.
kadonotakashi 0:8fdf9a60065b 81 * This is not a public API as it is called from other driver functions.
kadonotakashi 0:8fdf9a60065b 82 */
kadonotakashi 0:8fdf9a60065b 83 static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle);
kadonotakashi 0:8fdf9a60065b 84
kadonotakashi 0:8fdf9a60065b 85 /*!
kadonotakashi 0:8fdf9a60065b 86 * @brief Slave finish up a transfer.
kadonotakashi 0:8fdf9a60065b 87 * It would call back if there is callback function and set the state to idle.
kadonotakashi 0:8fdf9a60065b 88 * This is not a public API as it is called from other driver functions.
kadonotakashi 0:8fdf9a60065b 89 */
kadonotakashi 0:8fdf9a60065b 90 static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle);
kadonotakashi 0:8fdf9a60065b 91
kadonotakashi 0:8fdf9a60065b 92 /*!
kadonotakashi 0:8fdf9a60065b 93 * @brief DSPI common interrupt handler.
kadonotakashi 0:8fdf9a60065b 94 *
kadonotakashi 0:8fdf9a60065b 95 * @param base DSPI peripheral address.
kadonotakashi 0:8fdf9a60065b 96 * @param handle pointer to g_dspiHandle which stores the transfer state.
kadonotakashi 0:8fdf9a60065b 97 */
kadonotakashi 0:8fdf9a60065b 98 static void DSPI_CommonIRQHandler(SPI_Type *base, void *param);
kadonotakashi 0:8fdf9a60065b 99
kadonotakashi 0:8fdf9a60065b 100 /*!
kadonotakashi 0:8fdf9a60065b 101 * @brief Master prepare the transfer.
kadonotakashi 0:8fdf9a60065b 102 * Basically it set up dspi_master_handle .
kadonotakashi 0:8fdf9a60065b 103 * This is not a public API as it is called from other driver functions. fsl_dspi_edma.c also call this function.
kadonotakashi 0:8fdf9a60065b 104 */
kadonotakashi 0:8fdf9a60065b 105 static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer);
kadonotakashi 0:8fdf9a60065b 106
kadonotakashi 0:8fdf9a60065b 107 /*******************************************************************************
kadonotakashi 0:8fdf9a60065b 108 * Variables
kadonotakashi 0:8fdf9a60065b 109 ******************************************************************************/
kadonotakashi 0:8fdf9a60065b 110
kadonotakashi 0:8fdf9a60065b 111 /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/
kadonotakashi 0:8fdf9a60065b 112 static const uint32_t s_baudratePrescaler[] = {2, 3, 5, 7};
kadonotakashi 0:8fdf9a60065b 113 static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128,
kadonotakashi 0:8fdf9a60065b 114 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
kadonotakashi 0:8fdf9a60065b 115
kadonotakashi 0:8fdf9a60065b 116 static const uint32_t s_delayPrescaler[] = {1, 3, 5, 7};
kadonotakashi 0:8fdf9a60065b 117 static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256,
kadonotakashi 0:8fdf9a60065b 118 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};
kadonotakashi 0:8fdf9a60065b 119
kadonotakashi 0:8fdf9a60065b 120 /*! @brief Pointers to dspi bases for each instance. */
kadonotakashi 0:8fdf9a60065b 121 static SPI_Type *const s_dspiBases[] = SPI_BASE_PTRS;
kadonotakashi 0:8fdf9a60065b 122
kadonotakashi 0:8fdf9a60065b 123 /*! @brief Pointers to dspi IRQ number for each instance. */
kadonotakashi 0:8fdf9a60065b 124 static IRQn_Type const s_dspiIRQ[] = SPI_IRQS;
kadonotakashi 0:8fdf9a60065b 125
kadonotakashi 0:8fdf9a60065b 126 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
kadonotakashi 0:8fdf9a60065b 127 /*! @brief Pointers to dspi clocks for each instance. */
kadonotakashi 0:8fdf9a60065b 128 static clock_ip_name_t const s_dspiClock[] = DSPI_CLOCKS;
kadonotakashi 0:8fdf9a60065b 129 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
kadonotakashi 0:8fdf9a60065b 130
kadonotakashi 0:8fdf9a60065b 131 /*! @brief Pointers to dspi handles for each instance. */
kadonotakashi 0:8fdf9a60065b 132 static void *g_dspiHandle[FSL_FEATURE_SOC_DSPI_COUNT];
kadonotakashi 0:8fdf9a60065b 133
kadonotakashi 0:8fdf9a60065b 134 /*! @brief Pointer to master IRQ handler for each instance. */
kadonotakashi 0:8fdf9a60065b 135 static dspi_master_isr_t s_dspiMasterIsr;
kadonotakashi 0:8fdf9a60065b 136
kadonotakashi 0:8fdf9a60065b 137 /*! @brief Pointer to slave IRQ handler for each instance. */
kadonotakashi 0:8fdf9a60065b 138 static dspi_slave_isr_t s_dspiSlaveIsr;
kadonotakashi 0:8fdf9a60065b 139
kadonotakashi 0:8fdf9a60065b 140 /**********************************************************************************************************************
kadonotakashi 0:8fdf9a60065b 141 * Code
kadonotakashi 0:8fdf9a60065b 142 *********************************************************************************************************************/
kadonotakashi 0:8fdf9a60065b 143 uint32_t DSPI_GetInstance(SPI_Type *base)
kadonotakashi 0:8fdf9a60065b 144 {
kadonotakashi 0:8fdf9a60065b 145 uint32_t instance;
kadonotakashi 0:8fdf9a60065b 146
kadonotakashi 0:8fdf9a60065b 147 /* Find the instance index from base address mappings. */
kadonotakashi 0:8fdf9a60065b 148 for (instance = 0; instance < FSL_FEATURE_SOC_DSPI_COUNT; instance++)
kadonotakashi 0:8fdf9a60065b 149 {
kadonotakashi 0:8fdf9a60065b 150 if (s_dspiBases[instance] == base)
kadonotakashi 0:8fdf9a60065b 151 {
kadonotakashi 0:8fdf9a60065b 152 break;
kadonotakashi 0:8fdf9a60065b 153 }
kadonotakashi 0:8fdf9a60065b 154 }
kadonotakashi 0:8fdf9a60065b 155
kadonotakashi 0:8fdf9a60065b 156 assert(instance < FSL_FEATURE_SOC_DSPI_COUNT);
kadonotakashi 0:8fdf9a60065b 157
kadonotakashi 0:8fdf9a60065b 158 return instance;
kadonotakashi 0:8fdf9a60065b 159 }
kadonotakashi 0:8fdf9a60065b 160
kadonotakashi 0:8fdf9a60065b 161 void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz)
kadonotakashi 0:8fdf9a60065b 162 {
kadonotakashi 0:8fdf9a60065b 163 assert(masterConfig);
kadonotakashi 0:8fdf9a60065b 164
kadonotakashi 0:8fdf9a60065b 165 uint32_t temp;
kadonotakashi 0:8fdf9a60065b 166 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
kadonotakashi 0:8fdf9a60065b 167 /* enable DSPI clock */
kadonotakashi 0:8fdf9a60065b 168 CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]);
kadonotakashi 0:8fdf9a60065b 169 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
kadonotakashi 0:8fdf9a60065b 170
kadonotakashi 0:8fdf9a60065b 171 DSPI_Enable(base, true);
kadonotakashi 0:8fdf9a60065b 172 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 173
kadonotakashi 0:8fdf9a60065b 174 DSPI_SetMasterSlaveMode(base, kDSPI_Master);
kadonotakashi 0:8fdf9a60065b 175
kadonotakashi 0:8fdf9a60065b 176 temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK |
kadonotakashi 0:8fdf9a60065b 177 SPI_MCR_DIS_TXF_MASK | SPI_MCR_DIS_RXF_MASK));
kadonotakashi 0:8fdf9a60065b 178
kadonotakashi 0:8fdf9a60065b 179 base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) |
kadonotakashi 0:8fdf9a60065b 180 SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) |
kadonotakashi 0:8fdf9a60065b 181 SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) |
kadonotakashi 0:8fdf9a60065b 182 SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false);
kadonotakashi 0:8fdf9a60065b 183
kadonotakashi 0:8fdf9a60065b 184 DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow);
kadonotakashi 0:8fdf9a60065b 185
kadonotakashi 0:8fdf9a60065b 186 if (0 == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz))
kadonotakashi 0:8fdf9a60065b 187 {
kadonotakashi 0:8fdf9a60065b 188 assert(false);
kadonotakashi 0:8fdf9a60065b 189 }
kadonotakashi 0:8fdf9a60065b 190
kadonotakashi 0:8fdf9a60065b 191 temp = base->CTAR[masterConfig->whichCtar] &
kadonotakashi 0:8fdf9a60065b 192 ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK);
kadonotakashi 0:8fdf9a60065b 193
kadonotakashi 0:8fdf9a60065b 194 base->CTAR[masterConfig->whichCtar] =
kadonotakashi 0:8fdf9a60065b 195 temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1) | SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) |
kadonotakashi 0:8fdf9a60065b 196 SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) | SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction);
kadonotakashi 0:8fdf9a60065b 197
kadonotakashi 0:8fdf9a60065b 198 DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz,
kadonotakashi 0:8fdf9a60065b 199 masterConfig->ctarConfig.pcsToSckDelayInNanoSec);
kadonotakashi 0:8fdf9a60065b 200 DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz,
kadonotakashi 0:8fdf9a60065b 201 masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec);
kadonotakashi 0:8fdf9a60065b 202 DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz,
kadonotakashi 0:8fdf9a60065b 203 masterConfig->ctarConfig.betweenTransferDelayInNanoSec);
kadonotakashi 0:8fdf9a60065b 204
kadonotakashi 0:8fdf9a60065b 205 DSPI_StartTransfer(base);
kadonotakashi 0:8fdf9a60065b 206 }
kadonotakashi 0:8fdf9a60065b 207
kadonotakashi 0:8fdf9a60065b 208 void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig)
kadonotakashi 0:8fdf9a60065b 209 {
kadonotakashi 0:8fdf9a60065b 210 assert(masterConfig);
kadonotakashi 0:8fdf9a60065b 211
kadonotakashi 0:8fdf9a60065b 212 masterConfig->whichCtar = kDSPI_Ctar0;
kadonotakashi 0:8fdf9a60065b 213 masterConfig->ctarConfig.baudRate = 500000;
kadonotakashi 0:8fdf9a60065b 214 masterConfig->ctarConfig.bitsPerFrame = 8;
kadonotakashi 0:8fdf9a60065b 215 masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
kadonotakashi 0:8fdf9a60065b 216 masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge;
kadonotakashi 0:8fdf9a60065b 217 masterConfig->ctarConfig.direction = kDSPI_MsbFirst;
kadonotakashi 0:8fdf9a60065b 218
kadonotakashi 0:8fdf9a60065b 219 masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000;
kadonotakashi 0:8fdf9a60065b 220 masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000;
kadonotakashi 0:8fdf9a60065b 221 masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000;
kadonotakashi 0:8fdf9a60065b 222
kadonotakashi 0:8fdf9a60065b 223 masterConfig->whichPcs = kDSPI_Pcs0;
kadonotakashi 0:8fdf9a60065b 224 masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow;
kadonotakashi 0:8fdf9a60065b 225
kadonotakashi 0:8fdf9a60065b 226 masterConfig->enableContinuousSCK = false;
kadonotakashi 0:8fdf9a60065b 227 masterConfig->enableRxFifoOverWrite = false;
kadonotakashi 0:8fdf9a60065b 228 masterConfig->enableModifiedTimingFormat = false;
kadonotakashi 0:8fdf9a60065b 229 masterConfig->samplePoint = kDSPI_SckToSin0Clock;
kadonotakashi 0:8fdf9a60065b 230 }
kadonotakashi 0:8fdf9a60065b 231
kadonotakashi 0:8fdf9a60065b 232 void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig)
kadonotakashi 0:8fdf9a60065b 233 {
kadonotakashi 0:8fdf9a60065b 234 assert(slaveConfig);
kadonotakashi 0:8fdf9a60065b 235
kadonotakashi 0:8fdf9a60065b 236 uint32_t temp = 0;
kadonotakashi 0:8fdf9a60065b 237
kadonotakashi 0:8fdf9a60065b 238 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
kadonotakashi 0:8fdf9a60065b 239 /* enable DSPI clock */
kadonotakashi 0:8fdf9a60065b 240 CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]);
kadonotakashi 0:8fdf9a60065b 241 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
kadonotakashi 0:8fdf9a60065b 242
kadonotakashi 0:8fdf9a60065b 243 DSPI_Enable(base, true);
kadonotakashi 0:8fdf9a60065b 244 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 245
kadonotakashi 0:8fdf9a60065b 246 DSPI_SetMasterSlaveMode(base, kDSPI_Slave);
kadonotakashi 0:8fdf9a60065b 247
kadonotakashi 0:8fdf9a60065b 248 temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK |
kadonotakashi 0:8fdf9a60065b 249 SPI_MCR_DIS_TXF_MASK | SPI_MCR_DIS_RXF_MASK));
kadonotakashi 0:8fdf9a60065b 250
kadonotakashi 0:8fdf9a60065b 251 base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) |
kadonotakashi 0:8fdf9a60065b 252 SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) |
kadonotakashi 0:8fdf9a60065b 253 SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) |
kadonotakashi 0:8fdf9a60065b 254 SPI_MCR_DIS_TXF(false) | SPI_MCR_DIS_RXF(false);
kadonotakashi 0:8fdf9a60065b 255
kadonotakashi 0:8fdf9a60065b 256 DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow);
kadonotakashi 0:8fdf9a60065b 257
kadonotakashi 0:8fdf9a60065b 258 temp = base->CTAR[slaveConfig->whichCtar] &
kadonotakashi 0:8fdf9a60065b 259 ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK);
kadonotakashi 0:8fdf9a60065b 260
kadonotakashi 0:8fdf9a60065b 261 base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1) |
kadonotakashi 0:8fdf9a60065b 262 SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) |
kadonotakashi 0:8fdf9a60065b 263 SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha);
kadonotakashi 0:8fdf9a60065b 264
kadonotakashi 0:8fdf9a60065b 265 DSPI_StartTransfer(base);
kadonotakashi 0:8fdf9a60065b 266 }
kadonotakashi 0:8fdf9a60065b 267
kadonotakashi 0:8fdf9a60065b 268 void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig)
kadonotakashi 0:8fdf9a60065b 269 {
kadonotakashi 0:8fdf9a60065b 270 assert(slaveConfig);
kadonotakashi 0:8fdf9a60065b 271
kadonotakashi 0:8fdf9a60065b 272 slaveConfig->whichCtar = kDSPI_Ctar0;
kadonotakashi 0:8fdf9a60065b 273 slaveConfig->ctarConfig.bitsPerFrame = 8;
kadonotakashi 0:8fdf9a60065b 274 slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
kadonotakashi 0:8fdf9a60065b 275 slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge;
kadonotakashi 0:8fdf9a60065b 276
kadonotakashi 0:8fdf9a60065b 277 slaveConfig->enableContinuousSCK = false;
kadonotakashi 0:8fdf9a60065b 278 slaveConfig->enableRxFifoOverWrite = false;
kadonotakashi 0:8fdf9a60065b 279 slaveConfig->enableModifiedTimingFormat = false;
kadonotakashi 0:8fdf9a60065b 280 slaveConfig->samplePoint = kDSPI_SckToSin0Clock;
kadonotakashi 0:8fdf9a60065b 281 }
kadonotakashi 0:8fdf9a60065b 282
kadonotakashi 0:8fdf9a60065b 283 void DSPI_Deinit(SPI_Type *base)
kadonotakashi 0:8fdf9a60065b 284 {
kadonotakashi 0:8fdf9a60065b 285 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 286 DSPI_Enable(base, false);
kadonotakashi 0:8fdf9a60065b 287
kadonotakashi 0:8fdf9a60065b 288 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
kadonotakashi 0:8fdf9a60065b 289 /* disable DSPI clock */
kadonotakashi 0:8fdf9a60065b 290 CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]);
kadonotakashi 0:8fdf9a60065b 291 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
kadonotakashi 0:8fdf9a60065b 292 }
kadonotakashi 0:8fdf9a60065b 293
kadonotakashi 0:8fdf9a60065b 294 static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh)
kadonotakashi 0:8fdf9a60065b 295 {
kadonotakashi 0:8fdf9a60065b 296 uint32_t temp;
kadonotakashi 0:8fdf9a60065b 297
kadonotakashi 0:8fdf9a60065b 298 temp = base->MCR;
kadonotakashi 0:8fdf9a60065b 299
kadonotakashi 0:8fdf9a60065b 300 if (activeLowOrHigh == kDSPI_PcsActiveLow)
kadonotakashi 0:8fdf9a60065b 301 {
kadonotakashi 0:8fdf9a60065b 302 temp |= SPI_MCR_PCSIS(pcs);
kadonotakashi 0:8fdf9a60065b 303 }
kadonotakashi 0:8fdf9a60065b 304 else
kadonotakashi 0:8fdf9a60065b 305 {
kadonotakashi 0:8fdf9a60065b 306 temp &= ~SPI_MCR_PCSIS(pcs);
kadonotakashi 0:8fdf9a60065b 307 }
kadonotakashi 0:8fdf9a60065b 308
kadonotakashi 0:8fdf9a60065b 309 base->MCR = temp;
kadonotakashi 0:8fdf9a60065b 310 }
kadonotakashi 0:8fdf9a60065b 311
kadonotakashi 0:8fdf9a60065b 312 uint32_t DSPI_MasterSetBaudRate(SPI_Type *base,
kadonotakashi 0:8fdf9a60065b 313 dspi_ctar_selection_t whichCtar,
kadonotakashi 0:8fdf9a60065b 314 uint32_t baudRate_Bps,
kadonotakashi 0:8fdf9a60065b 315 uint32_t srcClock_Hz)
kadonotakashi 0:8fdf9a60065b 316 {
kadonotakashi 0:8fdf9a60065b 317 /* for master mode configuration, if slave mode detected, return 0*/
kadonotakashi 0:8fdf9a60065b 318 if (!DSPI_IsMaster(base))
kadonotakashi 0:8fdf9a60065b 319 {
kadonotakashi 0:8fdf9a60065b 320 return 0;
kadonotakashi 0:8fdf9a60065b 321 }
kadonotakashi 0:8fdf9a60065b 322 uint32_t temp;
kadonotakashi 0:8fdf9a60065b 323 uint32_t prescaler, bestPrescaler;
kadonotakashi 0:8fdf9a60065b 324 uint32_t scaler, bestScaler;
kadonotakashi 0:8fdf9a60065b 325 uint32_t dbr, bestDbr;
kadonotakashi 0:8fdf9a60065b 326 uint32_t realBaudrate, bestBaudrate;
kadonotakashi 0:8fdf9a60065b 327 uint32_t diff, min_diff;
kadonotakashi 0:8fdf9a60065b 328 uint32_t baudrate = baudRate_Bps;
kadonotakashi 0:8fdf9a60065b 329
kadonotakashi 0:8fdf9a60065b 330 /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */
kadonotakashi 0:8fdf9a60065b 331 min_diff = 0xFFFFFFFFU;
kadonotakashi 0:8fdf9a60065b 332 bestPrescaler = 0;
kadonotakashi 0:8fdf9a60065b 333 bestScaler = 0;
kadonotakashi 0:8fdf9a60065b 334 bestDbr = 1;
kadonotakashi 0:8fdf9a60065b 335 bestBaudrate = 0; /* required to avoid compilation warning */
kadonotakashi 0:8fdf9a60065b 336
kadonotakashi 0:8fdf9a60065b 337 /* In all for loops, if min_diff = 0, the exit for loop*/
kadonotakashi 0:8fdf9a60065b 338 for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++)
kadonotakashi 0:8fdf9a60065b 339 {
kadonotakashi 0:8fdf9a60065b 340 for (scaler = 0; (scaler < 16) && min_diff; scaler++)
kadonotakashi 0:8fdf9a60065b 341 {
kadonotakashi 0:8fdf9a60065b 342 for (dbr = 1; (dbr < 3) && min_diff; dbr++)
kadonotakashi 0:8fdf9a60065b 343 {
kadonotakashi 0:8fdf9a60065b 344 realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler])));
kadonotakashi 0:8fdf9a60065b 345
kadonotakashi 0:8fdf9a60065b 346 /* calculate the baud rate difference based on the conditional statement that states that the calculated
kadonotakashi 0:8fdf9a60065b 347 * baud rate must not exceed the desired baud rate.
kadonotakashi 0:8fdf9a60065b 348 */
kadonotakashi 0:8fdf9a60065b 349 if (baudrate >= realBaudrate)
kadonotakashi 0:8fdf9a60065b 350 {
kadonotakashi 0:8fdf9a60065b 351 diff = baudrate - realBaudrate;
kadonotakashi 0:8fdf9a60065b 352 if (min_diff > diff)
kadonotakashi 0:8fdf9a60065b 353 {
kadonotakashi 0:8fdf9a60065b 354 /* a better match found */
kadonotakashi 0:8fdf9a60065b 355 min_diff = diff;
kadonotakashi 0:8fdf9a60065b 356 bestPrescaler = prescaler;
kadonotakashi 0:8fdf9a60065b 357 bestScaler = scaler;
kadonotakashi 0:8fdf9a60065b 358 bestBaudrate = realBaudrate;
kadonotakashi 0:8fdf9a60065b 359 bestDbr = dbr;
kadonotakashi 0:8fdf9a60065b 360 }
kadonotakashi 0:8fdf9a60065b 361 }
kadonotakashi 0:8fdf9a60065b 362 }
kadonotakashi 0:8fdf9a60065b 363 }
kadonotakashi 0:8fdf9a60065b 364 }
kadonotakashi 0:8fdf9a60065b 365
kadonotakashi 0:8fdf9a60065b 366 /* write the best dbr, prescalar, and baud rate scalar to the CTAR */
kadonotakashi 0:8fdf9a60065b 367 temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK);
kadonotakashi 0:8fdf9a60065b 368
kadonotakashi 0:8fdf9a60065b 369 base->CTAR[whichCtar] = temp | ((bestDbr - 1) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) |
kadonotakashi 0:8fdf9a60065b 370 (bestScaler << SPI_CTAR_BR_SHIFT);
kadonotakashi 0:8fdf9a60065b 371
kadonotakashi 0:8fdf9a60065b 372 /* return the actual calculated baud rate */
kadonotakashi 0:8fdf9a60065b 373 return bestBaudrate;
kadonotakashi 0:8fdf9a60065b 374 }
kadonotakashi 0:8fdf9a60065b 375
kadonotakashi 0:8fdf9a60065b 376 void DSPI_MasterSetDelayScaler(
kadonotakashi 0:8fdf9a60065b 377 SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay)
kadonotakashi 0:8fdf9a60065b 378 {
kadonotakashi 0:8fdf9a60065b 379 /* these settings are only relevant in master mode */
kadonotakashi 0:8fdf9a60065b 380 if (DSPI_IsMaster(base))
kadonotakashi 0:8fdf9a60065b 381 {
kadonotakashi 0:8fdf9a60065b 382 switch (whichDelay)
kadonotakashi 0:8fdf9a60065b 383 {
kadonotakashi 0:8fdf9a60065b 384 case kDSPI_PcsToSck:
kadonotakashi 0:8fdf9a60065b 385 base->CTAR[whichCtar] = (base->CTAR[whichCtar] & (~SPI_CTAR_PCSSCK_MASK) & (~SPI_CTAR_CSSCK_MASK)) |
kadonotakashi 0:8fdf9a60065b 386 SPI_CTAR_PCSSCK(prescaler) | SPI_CTAR_CSSCK(scaler);
kadonotakashi 0:8fdf9a60065b 387 break;
kadonotakashi 0:8fdf9a60065b 388 case kDSPI_LastSckToPcs:
kadonotakashi 0:8fdf9a60065b 389 base->CTAR[whichCtar] = (base->CTAR[whichCtar] & (~SPI_CTAR_PASC_MASK) & (~SPI_CTAR_ASC_MASK)) |
kadonotakashi 0:8fdf9a60065b 390 SPI_CTAR_PASC(prescaler) | SPI_CTAR_ASC(scaler);
kadonotakashi 0:8fdf9a60065b 391 break;
kadonotakashi 0:8fdf9a60065b 392 case kDSPI_BetweenTransfer:
kadonotakashi 0:8fdf9a60065b 393 base->CTAR[whichCtar] = (base->CTAR[whichCtar] & (~SPI_CTAR_PDT_MASK) & (~SPI_CTAR_DT_MASK)) |
kadonotakashi 0:8fdf9a60065b 394 SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler);
kadonotakashi 0:8fdf9a60065b 395 break;
kadonotakashi 0:8fdf9a60065b 396 default:
kadonotakashi 0:8fdf9a60065b 397 break;
kadonotakashi 0:8fdf9a60065b 398 }
kadonotakashi 0:8fdf9a60065b 399 }
kadonotakashi 0:8fdf9a60065b 400 }
kadonotakashi 0:8fdf9a60065b 401
kadonotakashi 0:8fdf9a60065b 402 uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base,
kadonotakashi 0:8fdf9a60065b 403 dspi_ctar_selection_t whichCtar,
kadonotakashi 0:8fdf9a60065b 404 dspi_delay_type_t whichDelay,
kadonotakashi 0:8fdf9a60065b 405 uint32_t srcClock_Hz,
kadonotakashi 0:8fdf9a60065b 406 uint32_t delayTimeInNanoSec)
kadonotakashi 0:8fdf9a60065b 407 {
kadonotakashi 0:8fdf9a60065b 408 /* for master mode configuration, if slave mode detected, return 0 */
kadonotakashi 0:8fdf9a60065b 409 if (!DSPI_IsMaster(base))
kadonotakashi 0:8fdf9a60065b 410 {
kadonotakashi 0:8fdf9a60065b 411 return 0;
kadonotakashi 0:8fdf9a60065b 412 }
kadonotakashi 0:8fdf9a60065b 413
kadonotakashi 0:8fdf9a60065b 414 uint32_t prescaler, bestPrescaler;
kadonotakashi 0:8fdf9a60065b 415 uint32_t scaler, bestScaler;
kadonotakashi 0:8fdf9a60065b 416 uint32_t realDelay, bestDelay;
kadonotakashi 0:8fdf9a60065b 417 uint32_t diff, min_diff;
kadonotakashi 0:8fdf9a60065b 418 uint32_t initialDelayNanoSec;
kadonotakashi 0:8fdf9a60065b 419
kadonotakashi 0:8fdf9a60065b 420 /* find combination of prescaler and scaler resulting in the delay closest to the
kadonotakashi 0:8fdf9a60065b 421 * requested value
kadonotakashi 0:8fdf9a60065b 422 */
kadonotakashi 0:8fdf9a60065b 423 min_diff = 0xFFFFFFFFU;
kadonotakashi 0:8fdf9a60065b 424 /* Initialize prescaler and scaler to their max values to generate the max delay */
kadonotakashi 0:8fdf9a60065b 425 bestPrescaler = 0x3;
kadonotakashi 0:8fdf9a60065b 426 bestScaler = 0xF;
kadonotakashi 0:8fdf9a60065b 427 bestDelay = (((1000000000U * 4) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4;
kadonotakashi 0:8fdf9a60065b 428
kadonotakashi 0:8fdf9a60065b 429 /* First calculate the initial, default delay */
kadonotakashi 0:8fdf9a60065b 430 initialDelayNanoSec = 1000000000U / srcClock_Hz * 2;
kadonotakashi 0:8fdf9a60065b 431
kadonotakashi 0:8fdf9a60065b 432 /* If the initial, default delay is already greater than the desired delay, then
kadonotakashi 0:8fdf9a60065b 433 * set the delays to their initial value (0) and return the delay. In other words,
kadonotakashi 0:8fdf9a60065b 434 * there is no way to decrease the delay value further.
kadonotakashi 0:8fdf9a60065b 435 */
kadonotakashi 0:8fdf9a60065b 436 if (initialDelayNanoSec >= delayTimeInNanoSec)
kadonotakashi 0:8fdf9a60065b 437 {
kadonotakashi 0:8fdf9a60065b 438 DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay);
kadonotakashi 0:8fdf9a60065b 439 return initialDelayNanoSec;
kadonotakashi 0:8fdf9a60065b 440 }
kadonotakashi 0:8fdf9a60065b 441
kadonotakashi 0:8fdf9a60065b 442 /* In all for loops, if min_diff = 0, the exit for loop */
kadonotakashi 0:8fdf9a60065b 443 for (prescaler = 0; (prescaler < 4) && min_diff; prescaler++)
kadonotakashi 0:8fdf9a60065b 444 {
kadonotakashi 0:8fdf9a60065b 445 for (scaler = 0; (scaler < 16) && min_diff; scaler++)
kadonotakashi 0:8fdf9a60065b 446 {
kadonotakashi 0:8fdf9a60065b 447 realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4;
kadonotakashi 0:8fdf9a60065b 448
kadonotakashi 0:8fdf9a60065b 449 /* calculate the delay difference based on the conditional statement
kadonotakashi 0:8fdf9a60065b 450 * that states that the calculated delay must not be less then the desired delay
kadonotakashi 0:8fdf9a60065b 451 */
kadonotakashi 0:8fdf9a60065b 452 if (realDelay >= delayTimeInNanoSec)
kadonotakashi 0:8fdf9a60065b 453 {
kadonotakashi 0:8fdf9a60065b 454 diff = realDelay - delayTimeInNanoSec;
kadonotakashi 0:8fdf9a60065b 455 if (min_diff > diff)
kadonotakashi 0:8fdf9a60065b 456 {
kadonotakashi 0:8fdf9a60065b 457 /* a better match found */
kadonotakashi 0:8fdf9a60065b 458 min_diff = diff;
kadonotakashi 0:8fdf9a60065b 459 bestPrescaler = prescaler;
kadonotakashi 0:8fdf9a60065b 460 bestScaler = scaler;
kadonotakashi 0:8fdf9a60065b 461 bestDelay = realDelay;
kadonotakashi 0:8fdf9a60065b 462 }
kadonotakashi 0:8fdf9a60065b 463 }
kadonotakashi 0:8fdf9a60065b 464 }
kadonotakashi 0:8fdf9a60065b 465 }
kadonotakashi 0:8fdf9a60065b 466
kadonotakashi 0:8fdf9a60065b 467 /* write the best dbr, prescalar, and baud rate scalar to the CTAR */
kadonotakashi 0:8fdf9a60065b 468 DSPI_MasterSetDelayScaler(base, whichCtar, bestPrescaler, bestScaler, whichDelay);
kadonotakashi 0:8fdf9a60065b 469
kadonotakashi 0:8fdf9a60065b 470 /* return the actual calculated baud rate */
kadonotakashi 0:8fdf9a60065b 471 return bestDelay;
kadonotakashi 0:8fdf9a60065b 472 }
kadonotakashi 0:8fdf9a60065b 473
kadonotakashi 0:8fdf9a60065b 474 void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command)
kadonotakashi 0:8fdf9a60065b 475 {
kadonotakashi 0:8fdf9a60065b 476 assert(command);
kadonotakashi 0:8fdf9a60065b 477
kadonotakashi 0:8fdf9a60065b 478 command->isPcsContinuous = false;
kadonotakashi 0:8fdf9a60065b 479 command->whichCtar = kDSPI_Ctar0;
kadonotakashi 0:8fdf9a60065b 480 command->whichPcs = kDSPI_Pcs0;
kadonotakashi 0:8fdf9a60065b 481 command->isEndOfQueue = false;
kadonotakashi 0:8fdf9a60065b 482 command->clearTransferCount = false;
kadonotakashi 0:8fdf9a60065b 483 }
kadonotakashi 0:8fdf9a60065b 484
kadonotakashi 0:8fdf9a60065b 485 void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data)
kadonotakashi 0:8fdf9a60065b 486 {
kadonotakashi 0:8fdf9a60065b 487 assert(command);
kadonotakashi 0:8fdf9a60065b 488
kadonotakashi 0:8fdf9a60065b 489 /* First, clear Transmit Complete Flag (TCF) */
kadonotakashi 0:8fdf9a60065b 490 DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag);
kadonotakashi 0:8fdf9a60065b 491
kadonotakashi 0:8fdf9a60065b 492 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag))
kadonotakashi 0:8fdf9a60065b 493 {
kadonotakashi 0:8fdf9a60065b 494 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 495 }
kadonotakashi 0:8fdf9a60065b 496
kadonotakashi 0:8fdf9a60065b 497 base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) |
kadonotakashi 0:8fdf9a60065b 498 SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) |
kadonotakashi 0:8fdf9a60065b 499 SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data);
kadonotakashi 0:8fdf9a60065b 500 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 501
kadonotakashi 0:8fdf9a60065b 502 /* Wait till TCF sets */
kadonotakashi 0:8fdf9a60065b 503 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag))
kadonotakashi 0:8fdf9a60065b 504 {
kadonotakashi 0:8fdf9a60065b 505 }
kadonotakashi 0:8fdf9a60065b 506 }
kadonotakashi 0:8fdf9a60065b 507
kadonotakashi 0:8fdf9a60065b 508 void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data)
kadonotakashi 0:8fdf9a60065b 509 {
kadonotakashi 0:8fdf9a60065b 510 /* First, clear Transmit Complete Flag (TCF) */
kadonotakashi 0:8fdf9a60065b 511 DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag);
kadonotakashi 0:8fdf9a60065b 512
kadonotakashi 0:8fdf9a60065b 513 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag))
kadonotakashi 0:8fdf9a60065b 514 {
kadonotakashi 0:8fdf9a60065b 515 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 516 }
kadonotakashi 0:8fdf9a60065b 517
kadonotakashi 0:8fdf9a60065b 518 base->PUSHR = data;
kadonotakashi 0:8fdf9a60065b 519
kadonotakashi 0:8fdf9a60065b 520 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 521
kadonotakashi 0:8fdf9a60065b 522 /* Wait till TCF sets */
kadonotakashi 0:8fdf9a60065b 523 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag))
kadonotakashi 0:8fdf9a60065b 524 {
kadonotakashi 0:8fdf9a60065b 525 }
kadonotakashi 0:8fdf9a60065b 526 }
kadonotakashi 0:8fdf9a60065b 527
kadonotakashi 0:8fdf9a60065b 528 void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data)
kadonotakashi 0:8fdf9a60065b 529 {
kadonotakashi 0:8fdf9a60065b 530 /* First, clear Transmit Complete Flag (TCF) */
kadonotakashi 0:8fdf9a60065b 531 DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag);
kadonotakashi 0:8fdf9a60065b 532
kadonotakashi 0:8fdf9a60065b 533 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag))
kadonotakashi 0:8fdf9a60065b 534 {
kadonotakashi 0:8fdf9a60065b 535 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 536 }
kadonotakashi 0:8fdf9a60065b 537
kadonotakashi 0:8fdf9a60065b 538 base->PUSHR_SLAVE = data;
kadonotakashi 0:8fdf9a60065b 539
kadonotakashi 0:8fdf9a60065b 540 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 541
kadonotakashi 0:8fdf9a60065b 542 /* Wait till TCF sets */
kadonotakashi 0:8fdf9a60065b 543 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxCompleteFlag))
kadonotakashi 0:8fdf9a60065b 544 {
kadonotakashi 0:8fdf9a60065b 545 }
kadonotakashi 0:8fdf9a60065b 546 }
kadonotakashi 0:8fdf9a60065b 547
kadonotakashi 0:8fdf9a60065b 548 void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
kadonotakashi 0:8fdf9a60065b 549 {
kadonotakashi 0:8fdf9a60065b 550 if (mask & SPI_RSER_TFFF_RE_MASK)
kadonotakashi 0:8fdf9a60065b 551 {
kadonotakashi 0:8fdf9a60065b 552 base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK;
kadonotakashi 0:8fdf9a60065b 553 }
kadonotakashi 0:8fdf9a60065b 554 if (mask & SPI_RSER_RFDF_RE_MASK)
kadonotakashi 0:8fdf9a60065b 555 {
kadonotakashi 0:8fdf9a60065b 556 base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK;
kadonotakashi 0:8fdf9a60065b 557 }
kadonotakashi 0:8fdf9a60065b 558 base->RSER |= mask;
kadonotakashi 0:8fdf9a60065b 559 }
kadonotakashi 0:8fdf9a60065b 560
kadonotakashi 0:8fdf9a60065b 561 /*Transactional APIs -- Master*/
kadonotakashi 0:8fdf9a60065b 562
kadonotakashi 0:8fdf9a60065b 563 void DSPI_MasterTransferCreateHandle(SPI_Type *base,
kadonotakashi 0:8fdf9a60065b 564 dspi_master_handle_t *handle,
kadonotakashi 0:8fdf9a60065b 565 dspi_master_transfer_callback_t callback,
kadonotakashi 0:8fdf9a60065b 566 void *userData)
kadonotakashi 0:8fdf9a60065b 567 {
kadonotakashi 0:8fdf9a60065b 568 assert(handle);
kadonotakashi 0:8fdf9a60065b 569
kadonotakashi 0:8fdf9a60065b 570 /* Zero the handle. */
kadonotakashi 0:8fdf9a60065b 571 memset(handle, 0, sizeof(*handle));
kadonotakashi 0:8fdf9a60065b 572
kadonotakashi 0:8fdf9a60065b 573 g_dspiHandle[DSPI_GetInstance(base)] = handle;
kadonotakashi 0:8fdf9a60065b 574
kadonotakashi 0:8fdf9a60065b 575 handle->callback = callback;
kadonotakashi 0:8fdf9a60065b 576 handle->userData = userData;
kadonotakashi 0:8fdf9a60065b 577 }
kadonotakashi 0:8fdf9a60065b 578
kadonotakashi 0:8fdf9a60065b 579 status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer)
kadonotakashi 0:8fdf9a60065b 580 {
kadonotakashi 0:8fdf9a60065b 581 assert(transfer);
kadonotakashi 0:8fdf9a60065b 582
kadonotakashi 0:8fdf9a60065b 583 uint16_t wordToSend = 0;
kadonotakashi 0:8fdf9a60065b 584 uint16_t wordReceived = 0;
kadonotakashi 0:8fdf9a60065b 585 uint8_t dummyData = DSPI_DUMMY_DATA;
kadonotakashi 0:8fdf9a60065b 586 uint8_t bitsPerFrame;
kadonotakashi 0:8fdf9a60065b 587
kadonotakashi 0:8fdf9a60065b 588 uint32_t command;
kadonotakashi 0:8fdf9a60065b 589 uint32_t lastCommand;
kadonotakashi 0:8fdf9a60065b 590
kadonotakashi 0:8fdf9a60065b 591 uint8_t *txData;
kadonotakashi 0:8fdf9a60065b 592 uint8_t *rxData;
kadonotakashi 0:8fdf9a60065b 593 uint32_t remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 594 uint32_t remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 595
kadonotakashi 0:8fdf9a60065b 596 uint32_t fifoSize;
kadonotakashi 0:8fdf9a60065b 597 dspi_command_data_config_t commandStruct;
kadonotakashi 0:8fdf9a60065b 598
kadonotakashi 0:8fdf9a60065b 599 /* If the transfer count is zero, then return immediately.*/
kadonotakashi 0:8fdf9a60065b 600 if (transfer->dataSize == 0)
kadonotakashi 0:8fdf9a60065b 601 {
kadonotakashi 0:8fdf9a60065b 602 return kStatus_InvalidArgument;
kadonotakashi 0:8fdf9a60065b 603 }
kadonotakashi 0:8fdf9a60065b 604
kadonotakashi 0:8fdf9a60065b 605 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 606 DSPI_DisableInterrupts(base, kDSPI_AllInterruptEnable);
kadonotakashi 0:8fdf9a60065b 607 DSPI_FlushFifo(base, true, true);
kadonotakashi 0:8fdf9a60065b 608 DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag);
kadonotakashi 0:8fdf9a60065b 609
kadonotakashi 0:8fdf9a60065b 610 /*Calculate the command and lastCommand*/
kadonotakashi 0:8fdf9a60065b 611 commandStruct.whichPcs =
kadonotakashi 0:8fdf9a60065b 612 (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
kadonotakashi 0:8fdf9a60065b 613 commandStruct.isEndOfQueue = false;
kadonotakashi 0:8fdf9a60065b 614 commandStruct.clearTransferCount = false;
kadonotakashi 0:8fdf9a60065b 615 commandStruct.whichCtar =
kadonotakashi 0:8fdf9a60065b 616 (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
kadonotakashi 0:8fdf9a60065b 617 commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous);
kadonotakashi 0:8fdf9a60065b 618
kadonotakashi 0:8fdf9a60065b 619 command = DSPI_MasterGetFormattedCommand(&(commandStruct));
kadonotakashi 0:8fdf9a60065b 620
kadonotakashi 0:8fdf9a60065b 621 commandStruct.isEndOfQueue = true;
kadonotakashi 0:8fdf9a60065b 622 commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer);
kadonotakashi 0:8fdf9a60065b 623 lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
kadonotakashi 0:8fdf9a60065b 624
kadonotakashi 0:8fdf9a60065b 625 /*Calculate the bitsPerFrame*/
kadonotakashi 0:8fdf9a60065b 626 bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1;
kadonotakashi 0:8fdf9a60065b 627
kadonotakashi 0:8fdf9a60065b 628 txData = transfer->txData;
kadonotakashi 0:8fdf9a60065b 629 rxData = transfer->rxData;
kadonotakashi 0:8fdf9a60065b 630 remainingSendByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 631 remainingReceiveByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 632
kadonotakashi 0:8fdf9a60065b 633 if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK))
kadonotakashi 0:8fdf9a60065b 634 {
kadonotakashi 0:8fdf9a60065b 635 fifoSize = 1;
kadonotakashi 0:8fdf9a60065b 636 }
kadonotakashi 0:8fdf9a60065b 637 else
kadonotakashi 0:8fdf9a60065b 638 {
kadonotakashi 0:8fdf9a60065b 639 fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base);
kadonotakashi 0:8fdf9a60065b 640 }
kadonotakashi 0:8fdf9a60065b 641
kadonotakashi 0:8fdf9a60065b 642 DSPI_StartTransfer(base);
kadonotakashi 0:8fdf9a60065b 643
kadonotakashi 0:8fdf9a60065b 644 if (bitsPerFrame <= 8)
kadonotakashi 0:8fdf9a60065b 645 {
kadonotakashi 0:8fdf9a60065b 646 while (remainingSendByteCount > 0)
kadonotakashi 0:8fdf9a60065b 647 {
kadonotakashi 0:8fdf9a60065b 648 if (remainingSendByteCount == 1)
kadonotakashi 0:8fdf9a60065b 649 {
kadonotakashi 0:8fdf9a60065b 650 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag))
kadonotakashi 0:8fdf9a60065b 651 {
kadonotakashi 0:8fdf9a60065b 652 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 653 }
kadonotakashi 0:8fdf9a60065b 654
kadonotakashi 0:8fdf9a60065b 655 if (txData != NULL)
kadonotakashi 0:8fdf9a60065b 656 {
kadonotakashi 0:8fdf9a60065b 657 base->PUSHR = (*txData) | (lastCommand);
kadonotakashi 0:8fdf9a60065b 658 txData++;
kadonotakashi 0:8fdf9a60065b 659 }
kadonotakashi 0:8fdf9a60065b 660 else
kadonotakashi 0:8fdf9a60065b 661 {
kadonotakashi 0:8fdf9a60065b 662 base->PUSHR = (lastCommand) | (dummyData);
kadonotakashi 0:8fdf9a60065b 663 }
kadonotakashi 0:8fdf9a60065b 664 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 665 remainingSendByteCount--;
kadonotakashi 0:8fdf9a60065b 666
kadonotakashi 0:8fdf9a60065b 667 while (remainingReceiveByteCount > 0)
kadonotakashi 0:8fdf9a60065b 668 {
kadonotakashi 0:8fdf9a60065b 669 if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag)
kadonotakashi 0:8fdf9a60065b 670 {
kadonotakashi 0:8fdf9a60065b 671 if (rxData != NULL)
kadonotakashi 0:8fdf9a60065b 672 {
kadonotakashi 0:8fdf9a60065b 673 /* Read data from POPR*/
kadonotakashi 0:8fdf9a60065b 674 *(rxData) = DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 675 rxData++;
kadonotakashi 0:8fdf9a60065b 676 }
kadonotakashi 0:8fdf9a60065b 677 else
kadonotakashi 0:8fdf9a60065b 678 {
kadonotakashi 0:8fdf9a60065b 679 DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 680 }
kadonotakashi 0:8fdf9a60065b 681 remainingReceiveByteCount--;
kadonotakashi 0:8fdf9a60065b 682
kadonotakashi 0:8fdf9a60065b 683 DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag);
kadonotakashi 0:8fdf9a60065b 684 }
kadonotakashi 0:8fdf9a60065b 685 }
kadonotakashi 0:8fdf9a60065b 686 }
kadonotakashi 0:8fdf9a60065b 687 else
kadonotakashi 0:8fdf9a60065b 688 {
kadonotakashi 0:8fdf9a60065b 689 /*Wait until Tx Fifo is not full*/
kadonotakashi 0:8fdf9a60065b 690 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag))
kadonotakashi 0:8fdf9a60065b 691 {
kadonotakashi 0:8fdf9a60065b 692 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 693 }
kadonotakashi 0:8fdf9a60065b 694 if (txData != NULL)
kadonotakashi 0:8fdf9a60065b 695 {
kadonotakashi 0:8fdf9a60065b 696 base->PUSHR = command | (uint16_t)(*txData);
kadonotakashi 0:8fdf9a60065b 697 txData++;
kadonotakashi 0:8fdf9a60065b 698 }
kadonotakashi 0:8fdf9a60065b 699 else
kadonotakashi 0:8fdf9a60065b 700 {
kadonotakashi 0:8fdf9a60065b 701 base->PUSHR = command | dummyData;
kadonotakashi 0:8fdf9a60065b 702 }
kadonotakashi 0:8fdf9a60065b 703 remainingSendByteCount--;
kadonotakashi 0:8fdf9a60065b 704
kadonotakashi 0:8fdf9a60065b 705 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 706
kadonotakashi 0:8fdf9a60065b 707 while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize)
kadonotakashi 0:8fdf9a60065b 708 {
kadonotakashi 0:8fdf9a60065b 709 if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag)
kadonotakashi 0:8fdf9a60065b 710 {
kadonotakashi 0:8fdf9a60065b 711 if (rxData != NULL)
kadonotakashi 0:8fdf9a60065b 712 {
kadonotakashi 0:8fdf9a60065b 713 *(rxData) = DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 714 rxData++;
kadonotakashi 0:8fdf9a60065b 715 }
kadonotakashi 0:8fdf9a60065b 716 else
kadonotakashi 0:8fdf9a60065b 717 {
kadonotakashi 0:8fdf9a60065b 718 DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 719 }
kadonotakashi 0:8fdf9a60065b 720 remainingReceiveByteCount--;
kadonotakashi 0:8fdf9a60065b 721
kadonotakashi 0:8fdf9a60065b 722 DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag);
kadonotakashi 0:8fdf9a60065b 723 }
kadonotakashi 0:8fdf9a60065b 724 }
kadonotakashi 0:8fdf9a60065b 725 }
kadonotakashi 0:8fdf9a60065b 726 }
kadonotakashi 0:8fdf9a60065b 727 }
kadonotakashi 0:8fdf9a60065b 728 else
kadonotakashi 0:8fdf9a60065b 729 {
kadonotakashi 0:8fdf9a60065b 730 while (remainingSendByteCount > 0)
kadonotakashi 0:8fdf9a60065b 731 {
kadonotakashi 0:8fdf9a60065b 732 if (remainingSendByteCount <= 2)
kadonotakashi 0:8fdf9a60065b 733 {
kadonotakashi 0:8fdf9a60065b 734 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag))
kadonotakashi 0:8fdf9a60065b 735 {
kadonotakashi 0:8fdf9a60065b 736 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 737 }
kadonotakashi 0:8fdf9a60065b 738
kadonotakashi 0:8fdf9a60065b 739 if (txData != NULL)
kadonotakashi 0:8fdf9a60065b 740 {
kadonotakashi 0:8fdf9a60065b 741 wordToSend = *(txData);
kadonotakashi 0:8fdf9a60065b 742 ++txData;
kadonotakashi 0:8fdf9a60065b 743
kadonotakashi 0:8fdf9a60065b 744 if (remainingSendByteCount > 1)
kadonotakashi 0:8fdf9a60065b 745 {
kadonotakashi 0:8fdf9a60065b 746 wordToSend |= (unsigned)(*(txData)) << 8U;
kadonotakashi 0:8fdf9a60065b 747 ++txData;
kadonotakashi 0:8fdf9a60065b 748 }
kadonotakashi 0:8fdf9a60065b 749 }
kadonotakashi 0:8fdf9a60065b 750 else
kadonotakashi 0:8fdf9a60065b 751 {
kadonotakashi 0:8fdf9a60065b 752 wordToSend = dummyData;
kadonotakashi 0:8fdf9a60065b 753 }
kadonotakashi 0:8fdf9a60065b 754
kadonotakashi 0:8fdf9a60065b 755 base->PUSHR = lastCommand | wordToSend;
kadonotakashi 0:8fdf9a60065b 756
kadonotakashi 0:8fdf9a60065b 757 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 758 remainingSendByteCount = 0;
kadonotakashi 0:8fdf9a60065b 759
kadonotakashi 0:8fdf9a60065b 760 while (remainingReceiveByteCount > 0)
kadonotakashi 0:8fdf9a60065b 761 {
kadonotakashi 0:8fdf9a60065b 762 if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag)
kadonotakashi 0:8fdf9a60065b 763 {
kadonotakashi 0:8fdf9a60065b 764 wordReceived = DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 765
kadonotakashi 0:8fdf9a60065b 766 if (remainingReceiveByteCount != 1)
kadonotakashi 0:8fdf9a60065b 767 {
kadonotakashi 0:8fdf9a60065b 768 if (rxData != NULL)
kadonotakashi 0:8fdf9a60065b 769 {
kadonotakashi 0:8fdf9a60065b 770 *(rxData) = wordReceived;
kadonotakashi 0:8fdf9a60065b 771 ++rxData;
kadonotakashi 0:8fdf9a60065b 772 *(rxData) = wordReceived >> 8;
kadonotakashi 0:8fdf9a60065b 773 ++rxData;
kadonotakashi 0:8fdf9a60065b 774 }
kadonotakashi 0:8fdf9a60065b 775 remainingReceiveByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 776 }
kadonotakashi 0:8fdf9a60065b 777 else
kadonotakashi 0:8fdf9a60065b 778 {
kadonotakashi 0:8fdf9a60065b 779 if (rxData != NULL)
kadonotakashi 0:8fdf9a60065b 780 {
kadonotakashi 0:8fdf9a60065b 781 *(rxData) = wordReceived;
kadonotakashi 0:8fdf9a60065b 782 ++rxData;
kadonotakashi 0:8fdf9a60065b 783 }
kadonotakashi 0:8fdf9a60065b 784 remainingReceiveByteCount--;
kadonotakashi 0:8fdf9a60065b 785 }
kadonotakashi 0:8fdf9a60065b 786 DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag);
kadonotakashi 0:8fdf9a60065b 787 }
kadonotakashi 0:8fdf9a60065b 788 }
kadonotakashi 0:8fdf9a60065b 789 }
kadonotakashi 0:8fdf9a60065b 790 else
kadonotakashi 0:8fdf9a60065b 791 {
kadonotakashi 0:8fdf9a60065b 792 /*Wait until Tx Fifo is not full*/
kadonotakashi 0:8fdf9a60065b 793 while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag))
kadonotakashi 0:8fdf9a60065b 794 {
kadonotakashi 0:8fdf9a60065b 795 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 796 }
kadonotakashi 0:8fdf9a60065b 797
kadonotakashi 0:8fdf9a60065b 798 if (txData != NULL)
kadonotakashi 0:8fdf9a60065b 799 {
kadonotakashi 0:8fdf9a60065b 800 wordToSend = *(txData);
kadonotakashi 0:8fdf9a60065b 801 ++txData;
kadonotakashi 0:8fdf9a60065b 802 wordToSend |= (unsigned)(*(txData)) << 8U;
kadonotakashi 0:8fdf9a60065b 803 ++txData;
kadonotakashi 0:8fdf9a60065b 804 }
kadonotakashi 0:8fdf9a60065b 805 else
kadonotakashi 0:8fdf9a60065b 806 {
kadonotakashi 0:8fdf9a60065b 807 wordToSend = dummyData;
kadonotakashi 0:8fdf9a60065b 808 }
kadonotakashi 0:8fdf9a60065b 809 base->PUSHR = command | wordToSend;
kadonotakashi 0:8fdf9a60065b 810 remainingSendByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 811
kadonotakashi 0:8fdf9a60065b 812 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 813
kadonotakashi 0:8fdf9a60065b 814 while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize)
kadonotakashi 0:8fdf9a60065b 815 {
kadonotakashi 0:8fdf9a60065b 816 if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag)
kadonotakashi 0:8fdf9a60065b 817 {
kadonotakashi 0:8fdf9a60065b 818 wordReceived = DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 819
kadonotakashi 0:8fdf9a60065b 820 if (rxData != NULL)
kadonotakashi 0:8fdf9a60065b 821 {
kadonotakashi 0:8fdf9a60065b 822 *rxData = wordReceived;
kadonotakashi 0:8fdf9a60065b 823 ++rxData;
kadonotakashi 0:8fdf9a60065b 824 *rxData = wordReceived >> 8;
kadonotakashi 0:8fdf9a60065b 825 ++rxData;
kadonotakashi 0:8fdf9a60065b 826 }
kadonotakashi 0:8fdf9a60065b 827 remainingReceiveByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 828
kadonotakashi 0:8fdf9a60065b 829 DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag);
kadonotakashi 0:8fdf9a60065b 830 }
kadonotakashi 0:8fdf9a60065b 831 }
kadonotakashi 0:8fdf9a60065b 832 }
kadonotakashi 0:8fdf9a60065b 833 }
kadonotakashi 0:8fdf9a60065b 834 }
kadonotakashi 0:8fdf9a60065b 835
kadonotakashi 0:8fdf9a60065b 836 return kStatus_Success;
kadonotakashi 0:8fdf9a60065b 837 }
kadonotakashi 0:8fdf9a60065b 838
kadonotakashi 0:8fdf9a60065b 839 static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer)
kadonotakashi 0:8fdf9a60065b 840 {
kadonotakashi 0:8fdf9a60065b 841 assert(handle);
kadonotakashi 0:8fdf9a60065b 842 assert(transfer);
kadonotakashi 0:8fdf9a60065b 843
kadonotakashi 0:8fdf9a60065b 844 dspi_command_data_config_t commandStruct;
kadonotakashi 0:8fdf9a60065b 845
kadonotakashi 0:8fdf9a60065b 846 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 847 DSPI_FlushFifo(base, true, true);
kadonotakashi 0:8fdf9a60065b 848 DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag);
kadonotakashi 0:8fdf9a60065b 849
kadonotakashi 0:8fdf9a60065b 850 commandStruct.whichPcs =
kadonotakashi 0:8fdf9a60065b 851 (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
kadonotakashi 0:8fdf9a60065b 852 commandStruct.isEndOfQueue = false;
kadonotakashi 0:8fdf9a60065b 853 commandStruct.clearTransferCount = false;
kadonotakashi 0:8fdf9a60065b 854 commandStruct.whichCtar =
kadonotakashi 0:8fdf9a60065b 855 (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
kadonotakashi 0:8fdf9a60065b 856 commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous);
kadonotakashi 0:8fdf9a60065b 857 handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct));
kadonotakashi 0:8fdf9a60065b 858
kadonotakashi 0:8fdf9a60065b 859 commandStruct.isEndOfQueue = true;
kadonotakashi 0:8fdf9a60065b 860 commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer);
kadonotakashi 0:8fdf9a60065b 861 handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
kadonotakashi 0:8fdf9a60065b 862
kadonotakashi 0:8fdf9a60065b 863 handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1;
kadonotakashi 0:8fdf9a60065b 864
kadonotakashi 0:8fdf9a60065b 865 if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK))
kadonotakashi 0:8fdf9a60065b 866 {
kadonotakashi 0:8fdf9a60065b 867 handle->fifoSize = 1;
kadonotakashi 0:8fdf9a60065b 868 }
kadonotakashi 0:8fdf9a60065b 869 else
kadonotakashi 0:8fdf9a60065b 870 {
kadonotakashi 0:8fdf9a60065b 871 handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base);
kadonotakashi 0:8fdf9a60065b 872 }
kadonotakashi 0:8fdf9a60065b 873 handle->txData = transfer->txData;
kadonotakashi 0:8fdf9a60065b 874 handle->rxData = transfer->rxData;
kadonotakashi 0:8fdf9a60065b 875 handle->remainingSendByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 876 handle->remainingReceiveByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 877 handle->totalByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 878 }
kadonotakashi 0:8fdf9a60065b 879
kadonotakashi 0:8fdf9a60065b 880 status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer)
kadonotakashi 0:8fdf9a60065b 881 {
kadonotakashi 0:8fdf9a60065b 882 assert(handle);
kadonotakashi 0:8fdf9a60065b 883 assert(transfer);
kadonotakashi 0:8fdf9a60065b 884
kadonotakashi 0:8fdf9a60065b 885 /* If the transfer count is zero, then return immediately.*/
kadonotakashi 0:8fdf9a60065b 886 if (transfer->dataSize == 0)
kadonotakashi 0:8fdf9a60065b 887 {
kadonotakashi 0:8fdf9a60065b 888 return kStatus_InvalidArgument;
kadonotakashi 0:8fdf9a60065b 889 }
kadonotakashi 0:8fdf9a60065b 890
kadonotakashi 0:8fdf9a60065b 891 /* Check that we're not busy.*/
kadonotakashi 0:8fdf9a60065b 892 if (handle->state == kDSPI_Busy)
kadonotakashi 0:8fdf9a60065b 893 {
kadonotakashi 0:8fdf9a60065b 894 return kStatus_DSPI_Busy;
kadonotakashi 0:8fdf9a60065b 895 }
kadonotakashi 0:8fdf9a60065b 896
kadonotakashi 0:8fdf9a60065b 897 handle->state = kDSPI_Busy;
kadonotakashi 0:8fdf9a60065b 898
kadonotakashi 0:8fdf9a60065b 899 DSPI_MasterTransferPrepare(base, handle, transfer);
kadonotakashi 0:8fdf9a60065b 900 DSPI_StartTransfer(base);
kadonotakashi 0:8fdf9a60065b 901
kadonotakashi 0:8fdf9a60065b 902 /* Enable the NVIC for DSPI peripheral. */
kadonotakashi 0:8fdf9a60065b 903 EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]);
kadonotakashi 0:8fdf9a60065b 904
kadonotakashi 0:8fdf9a60065b 905 DSPI_MasterTransferFillUpTxFifo(base, handle);
kadonotakashi 0:8fdf9a60065b 906
kadonotakashi 0:8fdf9a60065b 907 /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt
kadonotakashi 0:8fdf9a60065b 908 * Since SPI is a synchronous interface, we only need to enable the RX interrupt.
kadonotakashi 0:8fdf9a60065b 909 * The IRQ handler will get the status of RX and TX interrupt flags.
kadonotakashi 0:8fdf9a60065b 910 */
kadonotakashi 0:8fdf9a60065b 911 s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ;
kadonotakashi 0:8fdf9a60065b 912
kadonotakashi 0:8fdf9a60065b 913 DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable);
kadonotakashi 0:8fdf9a60065b 914
kadonotakashi 0:8fdf9a60065b 915 return kStatus_Success;
kadonotakashi 0:8fdf9a60065b 916 }
kadonotakashi 0:8fdf9a60065b 917
kadonotakashi 0:8fdf9a60065b 918 status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count)
kadonotakashi 0:8fdf9a60065b 919 {
kadonotakashi 0:8fdf9a60065b 920 assert(handle);
kadonotakashi 0:8fdf9a60065b 921
kadonotakashi 0:8fdf9a60065b 922 if (!count)
kadonotakashi 0:8fdf9a60065b 923 {
kadonotakashi 0:8fdf9a60065b 924 return kStatus_InvalidArgument;
kadonotakashi 0:8fdf9a60065b 925 }
kadonotakashi 0:8fdf9a60065b 926
kadonotakashi 0:8fdf9a60065b 927 /* Catch when there is not an active transfer. */
kadonotakashi 0:8fdf9a60065b 928 if (handle->state != kDSPI_Busy)
kadonotakashi 0:8fdf9a60065b 929 {
kadonotakashi 0:8fdf9a60065b 930 *count = 0;
kadonotakashi 0:8fdf9a60065b 931 return kStatus_NoTransferInProgress;
kadonotakashi 0:8fdf9a60065b 932 }
kadonotakashi 0:8fdf9a60065b 933
kadonotakashi 0:8fdf9a60065b 934 *count = handle->totalByteCount - handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 935 return kStatus_Success;
kadonotakashi 0:8fdf9a60065b 936 }
kadonotakashi 0:8fdf9a60065b 937
kadonotakashi 0:8fdf9a60065b 938 static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 939 {
kadonotakashi 0:8fdf9a60065b 940 assert(handle);
kadonotakashi 0:8fdf9a60065b 941
kadonotakashi 0:8fdf9a60065b 942 /* Disable interrupt requests*/
kadonotakashi 0:8fdf9a60065b 943 DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable);
kadonotakashi 0:8fdf9a60065b 944
kadonotakashi 0:8fdf9a60065b 945 status_t status = 0;
kadonotakashi 0:8fdf9a60065b 946 if (handle->state == kDSPI_Error)
kadonotakashi 0:8fdf9a60065b 947 {
kadonotakashi 0:8fdf9a60065b 948 status = kStatus_DSPI_Error;
kadonotakashi 0:8fdf9a60065b 949 }
kadonotakashi 0:8fdf9a60065b 950 else
kadonotakashi 0:8fdf9a60065b 951 {
kadonotakashi 0:8fdf9a60065b 952 status = kStatus_Success;
kadonotakashi 0:8fdf9a60065b 953 }
kadonotakashi 0:8fdf9a60065b 954
kadonotakashi 0:8fdf9a60065b 955 if (handle->callback)
kadonotakashi 0:8fdf9a60065b 956 {
kadonotakashi 0:8fdf9a60065b 957 handle->callback(base, handle, status, handle->userData);
kadonotakashi 0:8fdf9a60065b 958 }
kadonotakashi 0:8fdf9a60065b 959
kadonotakashi 0:8fdf9a60065b 960 /* The transfer is complete.*/
kadonotakashi 0:8fdf9a60065b 961 handle->state = kDSPI_Idle;
kadonotakashi 0:8fdf9a60065b 962 }
kadonotakashi 0:8fdf9a60065b 963
kadonotakashi 0:8fdf9a60065b 964 static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 965 {
kadonotakashi 0:8fdf9a60065b 966 assert(handle);
kadonotakashi 0:8fdf9a60065b 967
kadonotakashi 0:8fdf9a60065b 968 uint16_t wordToSend = 0;
kadonotakashi 0:8fdf9a60065b 969 uint8_t dummyData = DSPI_DUMMY_DATA;
kadonotakashi 0:8fdf9a60065b 970
kadonotakashi 0:8fdf9a60065b 971 /* If bits/frame is greater than one byte */
kadonotakashi 0:8fdf9a60065b 972 if (handle->bitsPerFrame > 8)
kadonotakashi 0:8fdf9a60065b 973 {
kadonotakashi 0:8fdf9a60065b 974 /* Fill the fifo until it is full or until the send word count is 0 or until the difference
kadonotakashi 0:8fdf9a60065b 975 * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth.
kadonotakashi 0:8fdf9a60065b 976 * The reason for checking the difference is to ensure we only send as much as the
kadonotakashi 0:8fdf9a60065b 977 * RX FIFO can receive.
kadonotakashi 0:8fdf9a60065b 978 * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the
kadonotakashi 0:8fdf9a60065b 979 * send data, hence the difference between the remainingReceiveByteCount and
kadonotakashi 0:8fdf9a60065b 980 * remainingSendByteCount must be divided by 2 to convert this difference into a
kadonotakashi 0:8fdf9a60065b 981 * 16-bit (2 byte) value.
kadonotakashi 0:8fdf9a60065b 982 */
kadonotakashi 0:8fdf9a60065b 983 while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) &&
kadonotakashi 0:8fdf9a60065b 984 ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) / 2 < handle->fifoSize))
kadonotakashi 0:8fdf9a60065b 985 {
kadonotakashi 0:8fdf9a60065b 986 if (handle->remainingSendByteCount <= 2)
kadonotakashi 0:8fdf9a60065b 987 {
kadonotakashi 0:8fdf9a60065b 988 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 989 {
kadonotakashi 0:8fdf9a60065b 990 if (handle->remainingSendByteCount == 1)
kadonotakashi 0:8fdf9a60065b 991 {
kadonotakashi 0:8fdf9a60065b 992 wordToSend = *(handle->txData);
kadonotakashi 0:8fdf9a60065b 993 }
kadonotakashi 0:8fdf9a60065b 994 else
kadonotakashi 0:8fdf9a60065b 995 {
kadonotakashi 0:8fdf9a60065b 996 wordToSend = *(handle->txData);
kadonotakashi 0:8fdf9a60065b 997 ++handle->txData; /* increment to next data byte */
kadonotakashi 0:8fdf9a60065b 998 wordToSend |= (unsigned)(*(handle->txData)) << 8U;
kadonotakashi 0:8fdf9a60065b 999 }
kadonotakashi 0:8fdf9a60065b 1000 }
kadonotakashi 0:8fdf9a60065b 1001 else
kadonotakashi 0:8fdf9a60065b 1002 {
kadonotakashi 0:8fdf9a60065b 1003 wordToSend = dummyData;
kadonotakashi 0:8fdf9a60065b 1004 }
kadonotakashi 0:8fdf9a60065b 1005 handle->remainingSendByteCount = 0;
kadonotakashi 0:8fdf9a60065b 1006 base->PUSHR = handle->lastCommand | wordToSend;
kadonotakashi 0:8fdf9a60065b 1007 }
kadonotakashi 0:8fdf9a60065b 1008 /* For all words except the last word */
kadonotakashi 0:8fdf9a60065b 1009 else
kadonotakashi 0:8fdf9a60065b 1010 {
kadonotakashi 0:8fdf9a60065b 1011 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1012 {
kadonotakashi 0:8fdf9a60065b 1013 wordToSend = *(handle->txData);
kadonotakashi 0:8fdf9a60065b 1014 ++handle->txData; /* increment to next data byte */
kadonotakashi 0:8fdf9a60065b 1015 wordToSend |= (unsigned)(*(handle->txData)) << 8U;
kadonotakashi 0:8fdf9a60065b 1016 ++handle->txData; /* increment to next data byte */
kadonotakashi 0:8fdf9a60065b 1017 }
kadonotakashi 0:8fdf9a60065b 1018 else
kadonotakashi 0:8fdf9a60065b 1019 {
kadonotakashi 0:8fdf9a60065b 1020 wordToSend = dummyData;
kadonotakashi 0:8fdf9a60065b 1021 }
kadonotakashi 0:8fdf9a60065b 1022 handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */
kadonotakashi 0:8fdf9a60065b 1023 base->PUSHR = handle->command | wordToSend;
kadonotakashi 0:8fdf9a60065b 1024 }
kadonotakashi 0:8fdf9a60065b 1025
kadonotakashi 0:8fdf9a60065b 1026 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
kadonotakashi 0:8fdf9a60065b 1027 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 1028
kadonotakashi 0:8fdf9a60065b 1029 /* exit loop if send count is zero, else update local variables for next loop */
kadonotakashi 0:8fdf9a60065b 1030 if (handle->remainingSendByteCount == 0)
kadonotakashi 0:8fdf9a60065b 1031 {
kadonotakashi 0:8fdf9a60065b 1032 break;
kadonotakashi 0:8fdf9a60065b 1033 }
kadonotakashi 0:8fdf9a60065b 1034 } /* End of TX FIFO fill while loop */
kadonotakashi 0:8fdf9a60065b 1035 }
kadonotakashi 0:8fdf9a60065b 1036 /* Optimized for bits/frame less than or equal to one byte. */
kadonotakashi 0:8fdf9a60065b 1037 else
kadonotakashi 0:8fdf9a60065b 1038 {
kadonotakashi 0:8fdf9a60065b 1039 /* Fill the fifo until it is full or until the send word count is 0 or until the difference
kadonotakashi 0:8fdf9a60065b 1040 * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth.
kadonotakashi 0:8fdf9a60065b 1041 * The reason for checking the difference is to ensure we only send as much as the
kadonotakashi 0:8fdf9a60065b 1042 * RX FIFO can receive.
kadonotakashi 0:8fdf9a60065b 1043 */
kadonotakashi 0:8fdf9a60065b 1044 while ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag) &&
kadonotakashi 0:8fdf9a60065b 1045 ((handle->remainingReceiveByteCount - handle->remainingSendByteCount) < handle->fifoSize))
kadonotakashi 0:8fdf9a60065b 1046 {
kadonotakashi 0:8fdf9a60065b 1047 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1048 {
kadonotakashi 0:8fdf9a60065b 1049 wordToSend = *(handle->txData);
kadonotakashi 0:8fdf9a60065b 1050 ++handle->txData;
kadonotakashi 0:8fdf9a60065b 1051 }
kadonotakashi 0:8fdf9a60065b 1052 else
kadonotakashi 0:8fdf9a60065b 1053 {
kadonotakashi 0:8fdf9a60065b 1054 wordToSend = dummyData;
kadonotakashi 0:8fdf9a60065b 1055 }
kadonotakashi 0:8fdf9a60065b 1056
kadonotakashi 0:8fdf9a60065b 1057 if (handle->remainingSendByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1058 {
kadonotakashi 0:8fdf9a60065b 1059 base->PUSHR = handle->lastCommand | wordToSend;
kadonotakashi 0:8fdf9a60065b 1060 }
kadonotakashi 0:8fdf9a60065b 1061 else
kadonotakashi 0:8fdf9a60065b 1062 {
kadonotakashi 0:8fdf9a60065b 1063 base->PUSHR = handle->command | wordToSend;
kadonotakashi 0:8fdf9a60065b 1064 }
kadonotakashi 0:8fdf9a60065b 1065
kadonotakashi 0:8fdf9a60065b 1066 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
kadonotakashi 0:8fdf9a60065b 1067 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 1068
kadonotakashi 0:8fdf9a60065b 1069 --handle->remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 1070
kadonotakashi 0:8fdf9a60065b 1071 /* exit loop if send count is zero, else update local variables for next loop */
kadonotakashi 0:8fdf9a60065b 1072 if (handle->remainingSendByteCount == 0)
kadonotakashi 0:8fdf9a60065b 1073 {
kadonotakashi 0:8fdf9a60065b 1074 break;
kadonotakashi 0:8fdf9a60065b 1075 }
kadonotakashi 0:8fdf9a60065b 1076 }
kadonotakashi 0:8fdf9a60065b 1077 }
kadonotakashi 0:8fdf9a60065b 1078 }
kadonotakashi 0:8fdf9a60065b 1079
kadonotakashi 0:8fdf9a60065b 1080 void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 1081 {
kadonotakashi 0:8fdf9a60065b 1082 assert(handle);
kadonotakashi 0:8fdf9a60065b 1083
kadonotakashi 0:8fdf9a60065b 1084 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 1085
kadonotakashi 0:8fdf9a60065b 1086 /* Disable interrupt requests*/
kadonotakashi 0:8fdf9a60065b 1087 DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable);
kadonotakashi 0:8fdf9a60065b 1088
kadonotakashi 0:8fdf9a60065b 1089 handle->state = kDSPI_Idle;
kadonotakashi 0:8fdf9a60065b 1090 }
kadonotakashi 0:8fdf9a60065b 1091
kadonotakashi 0:8fdf9a60065b 1092 void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 1093 {
kadonotakashi 0:8fdf9a60065b 1094 assert(handle);
kadonotakashi 0:8fdf9a60065b 1095
kadonotakashi 0:8fdf9a60065b 1096 /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */
kadonotakashi 0:8fdf9a60065b 1097 if (handle->remainingReceiveByteCount)
kadonotakashi 0:8fdf9a60065b 1098 {
kadonotakashi 0:8fdf9a60065b 1099 /* Check read buffer.*/
kadonotakashi 0:8fdf9a60065b 1100 uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */
kadonotakashi 0:8fdf9a60065b 1101
kadonotakashi 0:8fdf9a60065b 1102 /* If bits/frame is greater than one byte */
kadonotakashi 0:8fdf9a60065b 1103 if (handle->bitsPerFrame > 8)
kadonotakashi 0:8fdf9a60065b 1104 {
kadonotakashi 0:8fdf9a60065b 1105 while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag)
kadonotakashi 0:8fdf9a60065b 1106 {
kadonotakashi 0:8fdf9a60065b 1107 wordReceived = DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 1108 /* clear the rx fifo drain request, needed for non-DMA applications as this flag
kadonotakashi 0:8fdf9a60065b 1109 * will remain set even if the rx fifo is empty. By manually clearing this flag, it
kadonotakashi 0:8fdf9a60065b 1110 * either remain clear if no more data is in the fifo, or it will set if there is
kadonotakashi 0:8fdf9a60065b 1111 * more data in the fifo.
kadonotakashi 0:8fdf9a60065b 1112 */
kadonotakashi 0:8fdf9a60065b 1113 DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag);
kadonotakashi 0:8fdf9a60065b 1114
kadonotakashi 0:8fdf9a60065b 1115 /* Store read bytes into rx buffer only if a buffer pointer was provided */
kadonotakashi 0:8fdf9a60065b 1116 if (handle->rxData)
kadonotakashi 0:8fdf9a60065b 1117 {
kadonotakashi 0:8fdf9a60065b 1118 /* For the last word received, if there is an extra byte due to the odd transfer
kadonotakashi 0:8fdf9a60065b 1119 * byte count, only save the the last byte and discard the upper byte
kadonotakashi 0:8fdf9a60065b 1120 */
kadonotakashi 0:8fdf9a60065b 1121 if (handle->remainingReceiveByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1122 {
kadonotakashi 0:8fdf9a60065b 1123 *handle->rxData = wordReceived; /* Write first data byte */
kadonotakashi 0:8fdf9a60065b 1124 --handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 1125 }
kadonotakashi 0:8fdf9a60065b 1126 else
kadonotakashi 0:8fdf9a60065b 1127 {
kadonotakashi 0:8fdf9a60065b 1128 *handle->rxData = wordReceived; /* Write first data byte */
kadonotakashi 0:8fdf9a60065b 1129 ++handle->rxData; /* increment to next data byte */
kadonotakashi 0:8fdf9a60065b 1130 *handle->rxData = wordReceived >> 8; /* Write second data byte */
kadonotakashi 0:8fdf9a60065b 1131 ++handle->rxData; /* increment to next data byte */
kadonotakashi 0:8fdf9a60065b 1132 handle->remainingReceiveByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1133 }
kadonotakashi 0:8fdf9a60065b 1134 }
kadonotakashi 0:8fdf9a60065b 1135 else
kadonotakashi 0:8fdf9a60065b 1136 {
kadonotakashi 0:8fdf9a60065b 1137 if (handle->remainingReceiveByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1138 {
kadonotakashi 0:8fdf9a60065b 1139 --handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 1140 }
kadonotakashi 0:8fdf9a60065b 1141 else
kadonotakashi 0:8fdf9a60065b 1142 {
kadonotakashi 0:8fdf9a60065b 1143 handle->remainingReceiveByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1144 }
kadonotakashi 0:8fdf9a60065b 1145 }
kadonotakashi 0:8fdf9a60065b 1146 if (handle->remainingReceiveByteCount == 0)
kadonotakashi 0:8fdf9a60065b 1147 {
kadonotakashi 0:8fdf9a60065b 1148 break;
kadonotakashi 0:8fdf9a60065b 1149 }
kadonotakashi 0:8fdf9a60065b 1150 } /* End of RX FIFO drain while loop */
kadonotakashi 0:8fdf9a60065b 1151 }
kadonotakashi 0:8fdf9a60065b 1152 /* Optimized for bits/frame less than or equal to one byte. */
kadonotakashi 0:8fdf9a60065b 1153 else
kadonotakashi 0:8fdf9a60065b 1154 {
kadonotakashi 0:8fdf9a60065b 1155 while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag)
kadonotakashi 0:8fdf9a60065b 1156 {
kadonotakashi 0:8fdf9a60065b 1157 wordReceived = DSPI_ReadData(base);
kadonotakashi 0:8fdf9a60065b 1158 /* clear the rx fifo drain request, needed for non-DMA applications as this flag
kadonotakashi 0:8fdf9a60065b 1159 * will remain set even if the rx fifo is empty. By manually clearing this flag, it
kadonotakashi 0:8fdf9a60065b 1160 * either remain clear if no more data is in the fifo, or it will set if there is
kadonotakashi 0:8fdf9a60065b 1161 * more data in the fifo.
kadonotakashi 0:8fdf9a60065b 1162 */
kadonotakashi 0:8fdf9a60065b 1163 DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag);
kadonotakashi 0:8fdf9a60065b 1164
kadonotakashi 0:8fdf9a60065b 1165 /* Store read bytes into rx buffer only if a buffer pointer was provided */
kadonotakashi 0:8fdf9a60065b 1166 if (handle->rxData)
kadonotakashi 0:8fdf9a60065b 1167 {
kadonotakashi 0:8fdf9a60065b 1168 *handle->rxData = wordReceived;
kadonotakashi 0:8fdf9a60065b 1169 ++handle->rxData;
kadonotakashi 0:8fdf9a60065b 1170 }
kadonotakashi 0:8fdf9a60065b 1171
kadonotakashi 0:8fdf9a60065b 1172 --handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 1173
kadonotakashi 0:8fdf9a60065b 1174 if (handle->remainingReceiveByteCount == 0)
kadonotakashi 0:8fdf9a60065b 1175 {
kadonotakashi 0:8fdf9a60065b 1176 break;
kadonotakashi 0:8fdf9a60065b 1177 }
kadonotakashi 0:8fdf9a60065b 1178 } /* End of RX FIFO drain while loop */
kadonotakashi 0:8fdf9a60065b 1179 }
kadonotakashi 0:8fdf9a60065b 1180 }
kadonotakashi 0:8fdf9a60065b 1181
kadonotakashi 0:8fdf9a60065b 1182 /* Check write buffer. We always have to send a word in order to keep the transfer
kadonotakashi 0:8fdf9a60065b 1183 * moving. So if the caller didn't provide a send buffer, we just send a zero.
kadonotakashi 0:8fdf9a60065b 1184 */
kadonotakashi 0:8fdf9a60065b 1185 if (handle->remainingSendByteCount)
kadonotakashi 0:8fdf9a60065b 1186 {
kadonotakashi 0:8fdf9a60065b 1187 DSPI_MasterTransferFillUpTxFifo(base, handle);
kadonotakashi 0:8fdf9a60065b 1188 }
kadonotakashi 0:8fdf9a60065b 1189
kadonotakashi 0:8fdf9a60065b 1190 /* Check if we're done with this transfer.*/
kadonotakashi 0:8fdf9a60065b 1191 if ((handle->remainingSendByteCount == 0) && (handle->remainingReceiveByteCount == 0))
kadonotakashi 0:8fdf9a60065b 1192 {
kadonotakashi 0:8fdf9a60065b 1193 /* Complete the transfer and disable the interrupts */
kadonotakashi 0:8fdf9a60065b 1194 DSPI_MasterTransferComplete(base, handle);
kadonotakashi 0:8fdf9a60065b 1195 }
kadonotakashi 0:8fdf9a60065b 1196 }
kadonotakashi 0:8fdf9a60065b 1197
kadonotakashi 0:8fdf9a60065b 1198 /*Transactional APIs -- Slave*/
kadonotakashi 0:8fdf9a60065b 1199 void DSPI_SlaveTransferCreateHandle(SPI_Type *base,
kadonotakashi 0:8fdf9a60065b 1200 dspi_slave_handle_t *handle,
kadonotakashi 0:8fdf9a60065b 1201 dspi_slave_transfer_callback_t callback,
kadonotakashi 0:8fdf9a60065b 1202 void *userData)
kadonotakashi 0:8fdf9a60065b 1203 {
kadonotakashi 0:8fdf9a60065b 1204 assert(handle);
kadonotakashi 0:8fdf9a60065b 1205
kadonotakashi 0:8fdf9a60065b 1206 /* Zero the handle. */
kadonotakashi 0:8fdf9a60065b 1207 memset(handle, 0, sizeof(*handle));
kadonotakashi 0:8fdf9a60065b 1208
kadonotakashi 0:8fdf9a60065b 1209 g_dspiHandle[DSPI_GetInstance(base)] = handle;
kadonotakashi 0:8fdf9a60065b 1210
kadonotakashi 0:8fdf9a60065b 1211 handle->callback = callback;
kadonotakashi 0:8fdf9a60065b 1212 handle->userData = userData;
kadonotakashi 0:8fdf9a60065b 1213 }
kadonotakashi 0:8fdf9a60065b 1214
kadonotakashi 0:8fdf9a60065b 1215 status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer)
kadonotakashi 0:8fdf9a60065b 1216 {
kadonotakashi 0:8fdf9a60065b 1217 assert(handle);
kadonotakashi 0:8fdf9a60065b 1218 assert(transfer);
kadonotakashi 0:8fdf9a60065b 1219
kadonotakashi 0:8fdf9a60065b 1220 /* If receive length is zero */
kadonotakashi 0:8fdf9a60065b 1221 if (transfer->dataSize == 0)
kadonotakashi 0:8fdf9a60065b 1222 {
kadonotakashi 0:8fdf9a60065b 1223 return kStatus_InvalidArgument;
kadonotakashi 0:8fdf9a60065b 1224 }
kadonotakashi 0:8fdf9a60065b 1225
kadonotakashi 0:8fdf9a60065b 1226 /* If both send buffer and receive buffer is null */
kadonotakashi 0:8fdf9a60065b 1227 if ((!(transfer->txData)) && (!(transfer->rxData)))
kadonotakashi 0:8fdf9a60065b 1228 {
kadonotakashi 0:8fdf9a60065b 1229 return kStatus_InvalidArgument;
kadonotakashi 0:8fdf9a60065b 1230 }
kadonotakashi 0:8fdf9a60065b 1231
kadonotakashi 0:8fdf9a60065b 1232 /* Check that we're not busy.*/
kadonotakashi 0:8fdf9a60065b 1233 if (handle->state == kDSPI_Busy)
kadonotakashi 0:8fdf9a60065b 1234 {
kadonotakashi 0:8fdf9a60065b 1235 return kStatus_DSPI_Busy;
kadonotakashi 0:8fdf9a60065b 1236 }
kadonotakashi 0:8fdf9a60065b 1237 handle->state = kDSPI_Busy;
kadonotakashi 0:8fdf9a60065b 1238
kadonotakashi 0:8fdf9a60065b 1239 /* Enable the NVIC for DSPI peripheral. */
kadonotakashi 0:8fdf9a60065b 1240 EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]);
kadonotakashi 0:8fdf9a60065b 1241
kadonotakashi 0:8fdf9a60065b 1242 /* Store transfer information */
kadonotakashi 0:8fdf9a60065b 1243 handle->txData = transfer->txData;
kadonotakashi 0:8fdf9a60065b 1244 handle->rxData = transfer->rxData;
kadonotakashi 0:8fdf9a60065b 1245 handle->remainingSendByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 1246 handle->remainingReceiveByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 1247 handle->totalByteCount = transfer->dataSize;
kadonotakashi 0:8fdf9a60065b 1248
kadonotakashi 0:8fdf9a60065b 1249 handle->errorCount = 0;
kadonotakashi 0:8fdf9a60065b 1250
kadonotakashi 0:8fdf9a60065b 1251 uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT;
kadonotakashi 0:8fdf9a60065b 1252 handle->bitsPerFrame =
kadonotakashi 0:8fdf9a60065b 1253 (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1;
kadonotakashi 0:8fdf9a60065b 1254
kadonotakashi 0:8fdf9a60065b 1255 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 1256
kadonotakashi 0:8fdf9a60065b 1257 DSPI_FlushFifo(base, true, true);
kadonotakashi 0:8fdf9a60065b 1258 DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag);
kadonotakashi 0:8fdf9a60065b 1259
kadonotakashi 0:8fdf9a60065b 1260 DSPI_StartTransfer(base);
kadonotakashi 0:8fdf9a60065b 1261
kadonotakashi 0:8fdf9a60065b 1262 /* Prepare data to transmit */
kadonotakashi 0:8fdf9a60065b 1263 DSPI_SlaveTransferFillUpTxFifo(base, handle);
kadonotakashi 0:8fdf9a60065b 1264
kadonotakashi 0:8fdf9a60065b 1265 s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ;
kadonotakashi 0:8fdf9a60065b 1266
kadonotakashi 0:8fdf9a60065b 1267 /* Enable RX FIFO drain request, the slave only use this interrupt */
kadonotakashi 0:8fdf9a60065b 1268 DSPI_EnableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable);
kadonotakashi 0:8fdf9a60065b 1269
kadonotakashi 0:8fdf9a60065b 1270 if (handle->rxData)
kadonotakashi 0:8fdf9a60065b 1271 {
kadonotakashi 0:8fdf9a60065b 1272 /* RX FIFO overflow request enable */
kadonotakashi 0:8fdf9a60065b 1273 DSPI_EnableInterrupts(base, kDSPI_RxFifoOverflowInterruptEnable);
kadonotakashi 0:8fdf9a60065b 1274 }
kadonotakashi 0:8fdf9a60065b 1275 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1276 {
kadonotakashi 0:8fdf9a60065b 1277 /* TX FIFO underflow request enable */
kadonotakashi 0:8fdf9a60065b 1278 DSPI_EnableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable);
kadonotakashi 0:8fdf9a60065b 1279 }
kadonotakashi 0:8fdf9a60065b 1280
kadonotakashi 0:8fdf9a60065b 1281 return kStatus_Success;
kadonotakashi 0:8fdf9a60065b 1282 }
kadonotakashi 0:8fdf9a60065b 1283
kadonotakashi 0:8fdf9a60065b 1284 status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count)
kadonotakashi 0:8fdf9a60065b 1285 {
kadonotakashi 0:8fdf9a60065b 1286 assert(handle);
kadonotakashi 0:8fdf9a60065b 1287
kadonotakashi 0:8fdf9a60065b 1288 if (!count)
kadonotakashi 0:8fdf9a60065b 1289 {
kadonotakashi 0:8fdf9a60065b 1290 return kStatus_InvalidArgument;
kadonotakashi 0:8fdf9a60065b 1291 }
kadonotakashi 0:8fdf9a60065b 1292
kadonotakashi 0:8fdf9a60065b 1293 /* Catch when there is not an active transfer. */
kadonotakashi 0:8fdf9a60065b 1294 if (handle->state != kDSPI_Busy)
kadonotakashi 0:8fdf9a60065b 1295 {
kadonotakashi 0:8fdf9a60065b 1296 *count = 0;
kadonotakashi 0:8fdf9a60065b 1297 return kStatus_NoTransferInProgress;
kadonotakashi 0:8fdf9a60065b 1298 }
kadonotakashi 0:8fdf9a60065b 1299
kadonotakashi 0:8fdf9a60065b 1300 *count = handle->totalByteCount - handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 1301 return kStatus_Success;
kadonotakashi 0:8fdf9a60065b 1302 }
kadonotakashi 0:8fdf9a60065b 1303
kadonotakashi 0:8fdf9a60065b 1304 static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 1305 {
kadonotakashi 0:8fdf9a60065b 1306 assert(handle);
kadonotakashi 0:8fdf9a60065b 1307
kadonotakashi 0:8fdf9a60065b 1308 uint16_t transmitData = 0;
kadonotakashi 0:8fdf9a60065b 1309 uint8_t dummyPattern = DSPI_DUMMY_DATA;
kadonotakashi 0:8fdf9a60065b 1310
kadonotakashi 0:8fdf9a60065b 1311 /* Service the transmitter, if transmit buffer provided, transmit the data,
kadonotakashi 0:8fdf9a60065b 1312 * else transmit dummy pattern
kadonotakashi 0:8fdf9a60065b 1313 */
kadonotakashi 0:8fdf9a60065b 1314 while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
kadonotakashi 0:8fdf9a60065b 1315 {
kadonotakashi 0:8fdf9a60065b 1316 /* Transmit data */
kadonotakashi 0:8fdf9a60065b 1317 if (handle->remainingSendByteCount > 0)
kadonotakashi 0:8fdf9a60065b 1318 {
kadonotakashi 0:8fdf9a60065b 1319 /* Have data to transmit, update the transmit data and push to FIFO */
kadonotakashi 0:8fdf9a60065b 1320 if (handle->bitsPerFrame <= 8)
kadonotakashi 0:8fdf9a60065b 1321 {
kadonotakashi 0:8fdf9a60065b 1322 /* bits/frame is 1 byte */
kadonotakashi 0:8fdf9a60065b 1323 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1324 {
kadonotakashi 0:8fdf9a60065b 1325 /* Update transmit data and transmit pointer */
kadonotakashi 0:8fdf9a60065b 1326 transmitData = *handle->txData;
kadonotakashi 0:8fdf9a60065b 1327 handle->txData++;
kadonotakashi 0:8fdf9a60065b 1328 }
kadonotakashi 0:8fdf9a60065b 1329 else
kadonotakashi 0:8fdf9a60065b 1330 {
kadonotakashi 0:8fdf9a60065b 1331 transmitData = dummyPattern;
kadonotakashi 0:8fdf9a60065b 1332 }
kadonotakashi 0:8fdf9a60065b 1333
kadonotakashi 0:8fdf9a60065b 1334 /* Decrease remaining dataSize */
kadonotakashi 0:8fdf9a60065b 1335 --handle->remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 1336 }
kadonotakashi 0:8fdf9a60065b 1337 /* bits/frame is 2 bytes */
kadonotakashi 0:8fdf9a60065b 1338 else
kadonotakashi 0:8fdf9a60065b 1339 {
kadonotakashi 0:8fdf9a60065b 1340 /* With multibytes per frame transmission, the transmit frame contains data from
kadonotakashi 0:8fdf9a60065b 1341 * transmit buffer until sent dataSize matches user request. Other bytes will set to
kadonotakashi 0:8fdf9a60065b 1342 * dummy pattern value.
kadonotakashi 0:8fdf9a60065b 1343 */
kadonotakashi 0:8fdf9a60065b 1344 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1345 {
kadonotakashi 0:8fdf9a60065b 1346 /* Update first byte of transmit data and transmit pointer */
kadonotakashi 0:8fdf9a60065b 1347 transmitData = *handle->txData;
kadonotakashi 0:8fdf9a60065b 1348 handle->txData++;
kadonotakashi 0:8fdf9a60065b 1349
kadonotakashi 0:8fdf9a60065b 1350 if (handle->remainingSendByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1351 {
kadonotakashi 0:8fdf9a60065b 1352 /* Decrease remaining dataSize */
kadonotakashi 0:8fdf9a60065b 1353 --handle->remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 1354 /* Update second byte of transmit data to second byte of dummy pattern */
kadonotakashi 0:8fdf9a60065b 1355 transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8);
kadonotakashi 0:8fdf9a60065b 1356 }
kadonotakashi 0:8fdf9a60065b 1357 else
kadonotakashi 0:8fdf9a60065b 1358 {
kadonotakashi 0:8fdf9a60065b 1359 /* Update second byte of transmit data and transmit pointer */
kadonotakashi 0:8fdf9a60065b 1360 transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8);
kadonotakashi 0:8fdf9a60065b 1361 handle->txData++;
kadonotakashi 0:8fdf9a60065b 1362 handle->remainingSendByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1363 }
kadonotakashi 0:8fdf9a60065b 1364 }
kadonotakashi 0:8fdf9a60065b 1365 else
kadonotakashi 0:8fdf9a60065b 1366 {
kadonotakashi 0:8fdf9a60065b 1367 if (handle->remainingSendByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1368 {
kadonotakashi 0:8fdf9a60065b 1369 --handle->remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 1370 }
kadonotakashi 0:8fdf9a60065b 1371 else
kadonotakashi 0:8fdf9a60065b 1372 {
kadonotakashi 0:8fdf9a60065b 1373 handle->remainingSendByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1374 }
kadonotakashi 0:8fdf9a60065b 1375 transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern;
kadonotakashi 0:8fdf9a60065b 1376 }
kadonotakashi 0:8fdf9a60065b 1377 }
kadonotakashi 0:8fdf9a60065b 1378 }
kadonotakashi 0:8fdf9a60065b 1379 else
kadonotakashi 0:8fdf9a60065b 1380 {
kadonotakashi 0:8fdf9a60065b 1381 break;
kadonotakashi 0:8fdf9a60065b 1382 }
kadonotakashi 0:8fdf9a60065b 1383
kadonotakashi 0:8fdf9a60065b 1384 /* Write the data to the DSPI data register */
kadonotakashi 0:8fdf9a60065b 1385 base->PUSHR_SLAVE = transmitData;
kadonotakashi 0:8fdf9a60065b 1386
kadonotakashi 0:8fdf9a60065b 1387 /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */
kadonotakashi 0:8fdf9a60065b 1388 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 1389 }
kadonotakashi 0:8fdf9a60065b 1390 }
kadonotakashi 0:8fdf9a60065b 1391
kadonotakashi 0:8fdf9a60065b 1392 static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 1393 {
kadonotakashi 0:8fdf9a60065b 1394 assert(handle);
kadonotakashi 0:8fdf9a60065b 1395
kadonotakashi 0:8fdf9a60065b 1396 /* Disable interrupt requests */
kadonotakashi 0:8fdf9a60065b 1397 DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable |
kadonotakashi 0:8fdf9a60065b 1398 kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable);
kadonotakashi 0:8fdf9a60065b 1399
kadonotakashi 0:8fdf9a60065b 1400 /* The transfer is complete. */
kadonotakashi 0:8fdf9a60065b 1401 handle->txData = NULL;
kadonotakashi 0:8fdf9a60065b 1402 handle->rxData = NULL;
kadonotakashi 0:8fdf9a60065b 1403 handle->remainingReceiveByteCount = 0;
kadonotakashi 0:8fdf9a60065b 1404 handle->remainingSendByteCount = 0;
kadonotakashi 0:8fdf9a60065b 1405
kadonotakashi 0:8fdf9a60065b 1406 status_t status = 0;
kadonotakashi 0:8fdf9a60065b 1407 if (handle->state == kDSPI_Error)
kadonotakashi 0:8fdf9a60065b 1408 {
kadonotakashi 0:8fdf9a60065b 1409 status = kStatus_DSPI_Error;
kadonotakashi 0:8fdf9a60065b 1410 }
kadonotakashi 0:8fdf9a60065b 1411 else
kadonotakashi 0:8fdf9a60065b 1412 {
kadonotakashi 0:8fdf9a60065b 1413 status = kStatus_Success;
kadonotakashi 0:8fdf9a60065b 1414 }
kadonotakashi 0:8fdf9a60065b 1415
kadonotakashi 0:8fdf9a60065b 1416 if (handle->callback)
kadonotakashi 0:8fdf9a60065b 1417 {
kadonotakashi 0:8fdf9a60065b 1418 handle->callback(base, handle, status, handle->userData);
kadonotakashi 0:8fdf9a60065b 1419 }
kadonotakashi 0:8fdf9a60065b 1420
kadonotakashi 0:8fdf9a60065b 1421 handle->state = kDSPI_Idle;
kadonotakashi 0:8fdf9a60065b 1422 }
kadonotakashi 0:8fdf9a60065b 1423
kadonotakashi 0:8fdf9a60065b 1424 void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 1425 {
kadonotakashi 0:8fdf9a60065b 1426 assert(handle);
kadonotakashi 0:8fdf9a60065b 1427
kadonotakashi 0:8fdf9a60065b 1428 DSPI_StopTransfer(base);
kadonotakashi 0:8fdf9a60065b 1429
kadonotakashi 0:8fdf9a60065b 1430 /* Disable interrupt requests */
kadonotakashi 0:8fdf9a60065b 1431 DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable |
kadonotakashi 0:8fdf9a60065b 1432 kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable);
kadonotakashi 0:8fdf9a60065b 1433
kadonotakashi 0:8fdf9a60065b 1434 handle->state = kDSPI_Idle;
kadonotakashi 0:8fdf9a60065b 1435 handle->remainingSendByteCount = 0;
kadonotakashi 0:8fdf9a60065b 1436 handle->remainingReceiveByteCount = 0;
kadonotakashi 0:8fdf9a60065b 1437 }
kadonotakashi 0:8fdf9a60065b 1438
kadonotakashi 0:8fdf9a60065b 1439 void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle)
kadonotakashi 0:8fdf9a60065b 1440 {
kadonotakashi 0:8fdf9a60065b 1441 assert(handle);
kadonotakashi 0:8fdf9a60065b 1442
kadonotakashi 0:8fdf9a60065b 1443 uint8_t dummyPattern = DSPI_DUMMY_DATA;
kadonotakashi 0:8fdf9a60065b 1444 uint32_t dataReceived;
kadonotakashi 0:8fdf9a60065b 1445 uint32_t dataSend = 0;
kadonotakashi 0:8fdf9a60065b 1446
kadonotakashi 0:8fdf9a60065b 1447 /* Because SPI protocol is synchronous, the number of bytes that that slave received from the
kadonotakashi 0:8fdf9a60065b 1448 * master is the actual number of bytes that the slave transmitted to the master. So we only
kadonotakashi 0:8fdf9a60065b 1449 * monitor the received dataSize to know when the transfer is complete.
kadonotakashi 0:8fdf9a60065b 1450 */
kadonotakashi 0:8fdf9a60065b 1451 if (handle->remainingReceiveByteCount > 0)
kadonotakashi 0:8fdf9a60065b 1452 {
kadonotakashi 0:8fdf9a60065b 1453 while (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag)
kadonotakashi 0:8fdf9a60065b 1454 {
kadonotakashi 0:8fdf9a60065b 1455 /* Have received data in the buffer. */
kadonotakashi 0:8fdf9a60065b 1456 dataReceived = base->POPR;
kadonotakashi 0:8fdf9a60065b 1457 /*Clear the rx fifo drain request, needed for non-DMA applications as this flag
kadonotakashi 0:8fdf9a60065b 1458 * will remain set even if the rx fifo is empty. By manually clearing this flag, it
kadonotakashi 0:8fdf9a60065b 1459 * either remain clear if no more data is in the fifo, or it will set if there is
kadonotakashi 0:8fdf9a60065b 1460 * more data in the fifo.
kadonotakashi 0:8fdf9a60065b 1461 */
kadonotakashi 0:8fdf9a60065b 1462 DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag);
kadonotakashi 0:8fdf9a60065b 1463
kadonotakashi 0:8fdf9a60065b 1464 /* If bits/frame is one byte */
kadonotakashi 0:8fdf9a60065b 1465 if (handle->bitsPerFrame <= 8)
kadonotakashi 0:8fdf9a60065b 1466 {
kadonotakashi 0:8fdf9a60065b 1467 if (handle->rxData)
kadonotakashi 0:8fdf9a60065b 1468 {
kadonotakashi 0:8fdf9a60065b 1469 /* Receive buffer is not null, store data into it */
kadonotakashi 0:8fdf9a60065b 1470 *handle->rxData = dataReceived;
kadonotakashi 0:8fdf9a60065b 1471 ++handle->rxData;
kadonotakashi 0:8fdf9a60065b 1472 }
kadonotakashi 0:8fdf9a60065b 1473 /* Descrease remaining receive byte count */
kadonotakashi 0:8fdf9a60065b 1474 --handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 1475
kadonotakashi 0:8fdf9a60065b 1476 if (handle->remainingSendByteCount > 0)
kadonotakashi 0:8fdf9a60065b 1477 {
kadonotakashi 0:8fdf9a60065b 1478 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1479 {
kadonotakashi 0:8fdf9a60065b 1480 dataSend = *handle->txData;
kadonotakashi 0:8fdf9a60065b 1481 ++handle->txData;
kadonotakashi 0:8fdf9a60065b 1482 }
kadonotakashi 0:8fdf9a60065b 1483 else
kadonotakashi 0:8fdf9a60065b 1484 {
kadonotakashi 0:8fdf9a60065b 1485 dataSend = dummyPattern;
kadonotakashi 0:8fdf9a60065b 1486 }
kadonotakashi 0:8fdf9a60065b 1487
kadonotakashi 0:8fdf9a60065b 1488 --handle->remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 1489 /* Write the data to the DSPI data register */
kadonotakashi 0:8fdf9a60065b 1490 base->PUSHR_SLAVE = dataSend;
kadonotakashi 0:8fdf9a60065b 1491 }
kadonotakashi 0:8fdf9a60065b 1492 }
kadonotakashi 0:8fdf9a60065b 1493 else /* If bits/frame is 2 bytes */
kadonotakashi 0:8fdf9a60065b 1494 {
kadonotakashi 0:8fdf9a60065b 1495 /* With multibytes frame receiving, we only receive till the received dataSize
kadonotakashi 0:8fdf9a60065b 1496 * matches user request. Other bytes will be ignored.
kadonotakashi 0:8fdf9a60065b 1497 */
kadonotakashi 0:8fdf9a60065b 1498 if (handle->rxData)
kadonotakashi 0:8fdf9a60065b 1499 {
kadonotakashi 0:8fdf9a60065b 1500 /* Receive buffer is not null, store first byte into it */
kadonotakashi 0:8fdf9a60065b 1501 *handle->rxData = dataReceived;
kadonotakashi 0:8fdf9a60065b 1502 ++handle->rxData;
kadonotakashi 0:8fdf9a60065b 1503
kadonotakashi 0:8fdf9a60065b 1504 if (handle->remainingReceiveByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1505 {
kadonotakashi 0:8fdf9a60065b 1506 /* Decrease remaining receive byte count */
kadonotakashi 0:8fdf9a60065b 1507 --handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 1508 }
kadonotakashi 0:8fdf9a60065b 1509 else
kadonotakashi 0:8fdf9a60065b 1510 {
kadonotakashi 0:8fdf9a60065b 1511 /* Receive buffer is not null, store second byte into it */
kadonotakashi 0:8fdf9a60065b 1512 *handle->rxData = dataReceived >> 8;
kadonotakashi 0:8fdf9a60065b 1513 ++handle->rxData;
kadonotakashi 0:8fdf9a60065b 1514 handle->remainingReceiveByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1515 }
kadonotakashi 0:8fdf9a60065b 1516 }
kadonotakashi 0:8fdf9a60065b 1517 /* If no handle->rxData*/
kadonotakashi 0:8fdf9a60065b 1518 else
kadonotakashi 0:8fdf9a60065b 1519 {
kadonotakashi 0:8fdf9a60065b 1520 if (handle->remainingReceiveByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1521 {
kadonotakashi 0:8fdf9a60065b 1522 /* Decrease remaining receive byte count */
kadonotakashi 0:8fdf9a60065b 1523 --handle->remainingReceiveByteCount;
kadonotakashi 0:8fdf9a60065b 1524 }
kadonotakashi 0:8fdf9a60065b 1525 else
kadonotakashi 0:8fdf9a60065b 1526 {
kadonotakashi 0:8fdf9a60065b 1527 handle->remainingReceiveByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1528 }
kadonotakashi 0:8fdf9a60065b 1529 }
kadonotakashi 0:8fdf9a60065b 1530
kadonotakashi 0:8fdf9a60065b 1531 if (handle->remainingSendByteCount > 0)
kadonotakashi 0:8fdf9a60065b 1532 {
kadonotakashi 0:8fdf9a60065b 1533 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1534 {
kadonotakashi 0:8fdf9a60065b 1535 dataSend = *handle->txData;
kadonotakashi 0:8fdf9a60065b 1536 ++handle->txData;
kadonotakashi 0:8fdf9a60065b 1537
kadonotakashi 0:8fdf9a60065b 1538 if (handle->remainingSendByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1539 {
kadonotakashi 0:8fdf9a60065b 1540 --handle->remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 1541 dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8);
kadonotakashi 0:8fdf9a60065b 1542 }
kadonotakashi 0:8fdf9a60065b 1543 else
kadonotakashi 0:8fdf9a60065b 1544 {
kadonotakashi 0:8fdf9a60065b 1545 dataSend |= (uint32_t)(*handle->txData) << 8;
kadonotakashi 0:8fdf9a60065b 1546 ++handle->txData;
kadonotakashi 0:8fdf9a60065b 1547 handle->remainingSendByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1548 }
kadonotakashi 0:8fdf9a60065b 1549 }
kadonotakashi 0:8fdf9a60065b 1550 /* If no handle->txData*/
kadonotakashi 0:8fdf9a60065b 1551 else
kadonotakashi 0:8fdf9a60065b 1552 {
kadonotakashi 0:8fdf9a60065b 1553 if (handle->remainingSendByteCount == 1)
kadonotakashi 0:8fdf9a60065b 1554 {
kadonotakashi 0:8fdf9a60065b 1555 --handle->remainingSendByteCount;
kadonotakashi 0:8fdf9a60065b 1556 }
kadonotakashi 0:8fdf9a60065b 1557 else
kadonotakashi 0:8fdf9a60065b 1558 {
kadonotakashi 0:8fdf9a60065b 1559 handle->remainingSendByteCount -= 2;
kadonotakashi 0:8fdf9a60065b 1560 }
kadonotakashi 0:8fdf9a60065b 1561 dataSend = (uint16_t)((uint16_t)(dummyPattern) << 8) | dummyPattern;
kadonotakashi 0:8fdf9a60065b 1562 }
kadonotakashi 0:8fdf9a60065b 1563 /* Write the data to the DSPI data register */
kadonotakashi 0:8fdf9a60065b 1564 base->PUSHR_SLAVE = dataSend;
kadonotakashi 0:8fdf9a60065b 1565 }
kadonotakashi 0:8fdf9a60065b 1566 }
kadonotakashi 0:8fdf9a60065b 1567 /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */
kadonotakashi 0:8fdf9a60065b 1568 DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
kadonotakashi 0:8fdf9a60065b 1569
kadonotakashi 0:8fdf9a60065b 1570 if (handle->remainingReceiveByteCount == 0)
kadonotakashi 0:8fdf9a60065b 1571 {
kadonotakashi 0:8fdf9a60065b 1572 break;
kadonotakashi 0:8fdf9a60065b 1573 }
kadonotakashi 0:8fdf9a60065b 1574 }
kadonotakashi 0:8fdf9a60065b 1575 }
kadonotakashi 0:8fdf9a60065b 1576 /* Check if remaining receive byte count matches user request */
kadonotakashi 0:8fdf9a60065b 1577 if ((handle->remainingReceiveByteCount == 0) || (handle->state == kDSPI_Error))
kadonotakashi 0:8fdf9a60065b 1578 {
kadonotakashi 0:8fdf9a60065b 1579 /* Other cases, stop the transfer. */
kadonotakashi 0:8fdf9a60065b 1580 DSPI_SlaveTransferComplete(base, handle);
kadonotakashi 0:8fdf9a60065b 1581 return;
kadonotakashi 0:8fdf9a60065b 1582 }
kadonotakashi 0:8fdf9a60065b 1583
kadonotakashi 0:8fdf9a60065b 1584 /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */
kadonotakashi 0:8fdf9a60065b 1585 if ((DSPI_GetStatusFlags(base) & kDSPI_TxFifoUnderflowFlag) && (base->RSER & SPI_RSER_TFUF_RE_MASK))
kadonotakashi 0:8fdf9a60065b 1586 {
kadonotakashi 0:8fdf9a60065b 1587 DSPI_ClearStatusFlags(base, kDSPI_TxFifoUnderflowFlag);
kadonotakashi 0:8fdf9a60065b 1588 /* Change state to error and clear flag */
kadonotakashi 0:8fdf9a60065b 1589 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1590 {
kadonotakashi 0:8fdf9a60065b 1591 handle->state = kDSPI_Error;
kadonotakashi 0:8fdf9a60065b 1592 }
kadonotakashi 0:8fdf9a60065b 1593 handle->errorCount++;
kadonotakashi 0:8fdf9a60065b 1594 }
kadonotakashi 0:8fdf9a60065b 1595 /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */
kadonotakashi 0:8fdf9a60065b 1596 if ((DSPI_GetStatusFlags(base) & kDSPI_RxFifoOverflowFlag) && (base->RSER & SPI_RSER_RFOF_RE_MASK))
kadonotakashi 0:8fdf9a60065b 1597 {
kadonotakashi 0:8fdf9a60065b 1598 DSPI_ClearStatusFlags(base, kDSPI_RxFifoOverflowFlag);
kadonotakashi 0:8fdf9a60065b 1599 /* Change state to error and clear flag */
kadonotakashi 0:8fdf9a60065b 1600 if (handle->txData)
kadonotakashi 0:8fdf9a60065b 1601 {
kadonotakashi 0:8fdf9a60065b 1602 handle->state = kDSPI_Error;
kadonotakashi 0:8fdf9a60065b 1603 }
kadonotakashi 0:8fdf9a60065b 1604 handle->errorCount++;
kadonotakashi 0:8fdf9a60065b 1605 }
kadonotakashi 0:8fdf9a60065b 1606 }
kadonotakashi 0:8fdf9a60065b 1607
kadonotakashi 0:8fdf9a60065b 1608 static void DSPI_CommonIRQHandler(SPI_Type *base, void *param)
kadonotakashi 0:8fdf9a60065b 1609 {
kadonotakashi 0:8fdf9a60065b 1610 if (DSPI_IsMaster(base))
kadonotakashi 0:8fdf9a60065b 1611 {
kadonotakashi 0:8fdf9a60065b 1612 s_dspiMasterIsr(base, (dspi_master_handle_t *)param);
kadonotakashi 0:8fdf9a60065b 1613 }
kadonotakashi 0:8fdf9a60065b 1614 else
kadonotakashi 0:8fdf9a60065b 1615 {
kadonotakashi 0:8fdf9a60065b 1616 s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param);
kadonotakashi 0:8fdf9a60065b 1617 }
kadonotakashi 0:8fdf9a60065b 1618 }
kadonotakashi 0:8fdf9a60065b 1619
kadonotakashi 0:8fdf9a60065b 1620 #if (FSL_FEATURE_SOC_DSPI_COUNT > 0)
kadonotakashi 0:8fdf9a60065b 1621 void SPI0_DriverIRQHandler(void)
kadonotakashi 0:8fdf9a60065b 1622 {
kadonotakashi 0:8fdf9a60065b 1623 assert(g_dspiHandle[0]);
kadonotakashi 0:8fdf9a60065b 1624 DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]);
kadonotakashi 0:8fdf9a60065b 1625 }
kadonotakashi 0:8fdf9a60065b 1626 #endif
kadonotakashi 0:8fdf9a60065b 1627
kadonotakashi 0:8fdf9a60065b 1628 #if (FSL_FEATURE_SOC_DSPI_COUNT > 1)
kadonotakashi 0:8fdf9a60065b 1629 void SPI1_DriverIRQHandler(void)
kadonotakashi 0:8fdf9a60065b 1630 {
kadonotakashi 0:8fdf9a60065b 1631 assert(g_dspiHandle[1]);
kadonotakashi 0:8fdf9a60065b 1632 DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]);
kadonotakashi 0:8fdf9a60065b 1633 }
kadonotakashi 0:8fdf9a60065b 1634 #endif
kadonotakashi 0:8fdf9a60065b 1635
kadonotakashi 0:8fdf9a60065b 1636 #if (FSL_FEATURE_SOC_DSPI_COUNT > 2)
kadonotakashi 0:8fdf9a60065b 1637 void SPI2_DriverIRQHandler(void)
kadonotakashi 0:8fdf9a60065b 1638 {
kadonotakashi 0:8fdf9a60065b 1639 assert(g_dspiHandle[2]);
kadonotakashi 0:8fdf9a60065b 1640 DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]);
kadonotakashi 0:8fdf9a60065b 1641 }
kadonotakashi 0:8fdf9a60065b 1642 #endif
kadonotakashi 0:8fdf9a60065b 1643
kadonotakashi 0:8fdf9a60065b 1644 #if (FSL_FEATURE_SOC_DSPI_COUNT > 3)
kadonotakashi 0:8fdf9a60065b 1645 void SPI3_DriverIRQHandler(void)
kadonotakashi 0:8fdf9a60065b 1646 {
kadonotakashi 0:8fdf9a60065b 1647 assert(g_dspiHandle[3]);
kadonotakashi 0:8fdf9a60065b 1648 DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]);
kadonotakashi 0:8fdf9a60065b 1649 }
kadonotakashi 0:8fdf9a60065b 1650 #endif
kadonotakashi 0:8fdf9a60065b 1651
kadonotakashi 0:8fdf9a60065b 1652 #if (FSL_FEATURE_SOC_DSPI_COUNT > 4)
kadonotakashi 0:8fdf9a60065b 1653 void SPI4_DriverIRQHandler(void)
kadonotakashi 0:8fdf9a60065b 1654 {
kadonotakashi 0:8fdf9a60065b 1655 assert(g_dspiHandle[4]);
kadonotakashi 0:8fdf9a60065b 1656 DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]);
kadonotakashi 0:8fdf9a60065b 1657 }
kadonotakashi 0:8fdf9a60065b 1658 #endif
kadonotakashi 0:8fdf9a60065b 1659
kadonotakashi 0:8fdf9a60065b 1660 #if (FSL_FEATURE_SOC_DSPI_COUNT > 5)
kadonotakashi 0:8fdf9a60065b 1661 void SPI5_DriverIRQHandler(void)
kadonotakashi 0:8fdf9a60065b 1662 {
kadonotakashi 0:8fdf9a60065b 1663 assert(g_dspiHandle[5]);
kadonotakashi 0:8fdf9a60065b 1664 DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]);
kadonotakashi 0:8fdf9a60065b 1665 }
kadonotakashi 0:8fdf9a60065b 1666 #endif
kadonotakashi 0:8fdf9a60065b 1667
kadonotakashi 0:8fdf9a60065b 1668 #if (FSL_FEATURE_SOC_DSPI_COUNT > 6)
kadonotakashi 0:8fdf9a60065b 1669 #error "Should write the SPIx_DriverIRQHandler function that instance greater than 5 !"
kadonotakashi 0:8fdf9a60065b 1670 #endif