![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466
mbed-os/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_K82F/drivers/fsl_dspi.c@3:f3764f852aa8, 2018-10-11 (annotated)
- 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?
User | Revision | Line number | New 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 |