1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_dspi.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.dspi"
18 #endif
19
20 /*! @brief Typedef for master interrupt handler. */
21 typedef void (*dspi_master_isr_t)(SPI_Type *base, dspi_master_handle_t *handle);
22
23 /*! @brief Typedef for slave interrupt handler. */
24 typedef void (*dspi_slave_isr_t)(SPI_Type *base, dspi_slave_handle_t *handle);
25
26 /*******************************************************************************
27 * Prototypes
28 ******************************************************************************/
29 /*!
30 * @brief Configures the DSPI peripheral chip select polarity.
31 *
32 * This function takes in the desired peripheral chip select (Pcs) and it's corresponding desired polarity and
33 * configures the Pcs signal to operate with the desired characteristic.
34 *
35 * @param base DSPI peripheral address.
36 * @param pcs The particular peripheral chip select (parameter value is of type dspi_which_pcs_t) for which we wish to
37 * apply the active high or active low characteristic.
38 * @param activeLowOrHigh The setting for either "active high, inactive low (0)" or "active low, inactive high(1)" of
39 * type dspi_pcs_polarity_config_t.
40 */
41 static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh);
42
43 /*!
44 * @brief Master fill up the TX FIFO with data.
45 * This is not a public API.
46 */
47 static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle);
48
49 /*!
50 * @brief Master finish up a transfer.
51 * It would call back if there is callback function and set the state to idle.
52 * This is not a public API.
53 */
54 static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle);
55
56 /*!
57 * @brief Slave fill up the TX FIFO with data.
58 * This is not a public API.
59 */
60 static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle);
61
62 /*!
63 * @brief Slave finish up a transfer.
64 * It would call back if there is callback function and set the state to idle.
65 * This is not a public API.
66 */
67 static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle);
68
69 /*!
70 * @brief DSPI common interrupt handler.
71 *
72 * @param base DSPI peripheral address.
73 * @param handle pointer to g_dspiHandle which stores the transfer state.
74 */
75 static void DSPI_CommonIRQHandler(SPI_Type *base, void *param);
76
77 /*!
78 * @brief Master prepare the transfer.
79 * Basically it set up dspi_master_handle .
80 * This is not a public API.
81 */
82 static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer);
83
84 /*******************************************************************************
85 * Variables
86 ******************************************************************************/
87
88 /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/
89 static const uint32_t s_baudratePrescaler[] = {2, 3, 5, 7};
90 static const uint32_t s_baudrateScaler[] = {2, 4, 6, 8, 16, 32, 64, 128,
91 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
92
93 static const uint32_t s_delayPrescaler[] = {1, 3, 5, 7};
94 static const uint32_t s_delayScaler[] = {2, 4, 8, 16, 32, 64, 128, 256,
95 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536};
96
97 /*! @brief Pointers to dspi bases for each instance. */
98 static SPI_Type *const s_dspiBases[] = SPI_BASE_PTRS;
99
100 /*! @brief Pointers to dspi IRQ number for each instance. */
101 static IRQn_Type const s_dspiIRQ[] = SPI_IRQS;
102
103 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
104 /*! @brief Pointers to dspi clocks for each instance. */
105 static clock_ip_name_t const s_dspiClock[] = DSPI_CLOCKS;
106 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
107
108 /*! @brief Pointers to dspi handles for each instance. */
109 static void *g_dspiHandle[ARRAY_SIZE(s_dspiBases)];
110
111 /*! @brief Pointer to master IRQ handler for each instance. */
112 static dspi_master_isr_t s_dspiMasterIsr;
113
114 /*! @brief Pointer to slave IRQ handler for each instance. */
115 static dspi_slave_isr_t s_dspiSlaveIsr;
116
117 /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
118 volatile uint8_t g_dspiDummyData[ARRAY_SIZE(s_dspiBases)] = {0};
119 /**********************************************************************************************************************
120 * Code
121 *********************************************************************************************************************/
122 /*!
123 * brief Get instance number for DSPI module.
124 *
125 * param base DSPI peripheral base address.
126 */
DSPI_GetInstance(SPI_Type * base)127 uint32_t DSPI_GetInstance(SPI_Type *base)
128 {
129 uint32_t instance;
130
131 /* Find the instance index from base address mappings. */
132 for (instance = 0; instance < ARRAY_SIZE(s_dspiBases); instance++)
133 {
134 if (s_dspiBases[instance] == base)
135 {
136 break;
137 }
138 }
139
140 assert(instance < ARRAY_SIZE(s_dspiBases));
141
142 return instance;
143 }
144
145 /*!
146 * brief Dummy data for each instance.
147 *
148 * The purpose of this API is to avoid MISRA rule8.5 : Multiple declarations of
149 * externally-linked object or function g_dspiDummyData.
150 *
151 * param base DSPI peripheral base address.
152 */
DSPI_GetDummyDataInstance(SPI_Type * base)153 uint8_t DSPI_GetDummyDataInstance(SPI_Type *base)
154 {
155 uint8_t instance = g_dspiDummyData[DSPI_GetInstance(base)];
156
157 return instance;
158 }
159
160 /*!
161 * brief Set up the dummy data.
162 *
163 * param base DSPI peripheral address.
164 * param dummyData Data to be transferred when tx buffer is NULL.
165 */
DSPI_SetDummyData(SPI_Type * base,uint8_t dummyData)166 void DSPI_SetDummyData(SPI_Type *base, uint8_t dummyData)
167 {
168 uint32_t instance = DSPI_GetInstance(base);
169 g_dspiDummyData[instance] = dummyData;
170 }
171
172 /*!
173 * brief Initializes the DSPI master.
174 *
175 * This function initializes the DSPI master configuration. This is an example use case.
176 * code
177 * dspi_master_config_t masterConfig;
178 * masterConfig.whichCtar = kDSPI_Ctar0;
179 * masterConfig.ctarConfig.baudRate = 500000000U;
180 * masterConfig.ctarConfig.bitsPerFrame = 8;
181 * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
182 * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge;
183 * masterConfig.ctarConfig.direction = kDSPI_MsbFirst;
184 * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ;
185 * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ;
186 * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ;
187 * masterConfig.whichPcs = kDSPI_Pcs0;
188 * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow;
189 * masterConfig.enableContinuousSCK = false;
190 * masterConfig.enableRxFifoOverWrite = false;
191 * masterConfig.enableModifiedTimingFormat = false;
192 * masterConfig.samplePoint = kDSPI_SckToSin0Clock;
193 * DSPI_MasterInit(base, &masterConfig, srcClock_Hz);
194 * endcode
195 *
196 * param base DSPI peripheral address.
197 * param masterConfig Pointer to the structure dspi_master_config_t.
198 * param srcClock_Hz Module source input clock in Hertz.
199 */
DSPI_MasterInit(SPI_Type * base,const dspi_master_config_t * masterConfig,uint32_t srcClock_Hz)200 void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz)
201 {
202 assert(NULL != masterConfig);
203
204 uint32_t temp;
205 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
206 /* enable DSPI clock */
207 CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]);
208 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
209
210 DSPI_Enable(base, true);
211 DSPI_StopTransfer(base);
212
213 DSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow);
214 DSPI_SetMasterSlaveMode(base, kDSPI_Master);
215
216 temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK |
217 SPI_MCR_DIS_TXF_MASK | SPI_MCR_DIS_RXF_MASK));
218
219 base->MCR = temp | SPI_MCR_CONT_SCKE(masterConfig->enableContinuousSCK) |
220 SPI_MCR_MTFE(masterConfig->enableModifiedTimingFormat) |
221 SPI_MCR_ROOE(masterConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(masterConfig->samplePoint) |
222 SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U);
223
224 if (0U == DSPI_MasterSetBaudRate(base, masterConfig->whichCtar, masterConfig->ctarConfig.baudRate, srcClock_Hz))
225 {
226 assert(false);
227 }
228
229 temp = base->CTAR[masterConfig->whichCtar] &
230 ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK);
231
232 base->CTAR[masterConfig->whichCtar] = temp | SPI_CTAR_FMSZ(masterConfig->ctarConfig.bitsPerFrame - 1U) |
233 SPI_CTAR_CPOL(masterConfig->ctarConfig.cpol) |
234 SPI_CTAR_CPHA(masterConfig->ctarConfig.cpha) |
235 SPI_CTAR_LSBFE(masterConfig->ctarConfig.direction);
236
237 (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_PcsToSck, srcClock_Hz,
238 masterConfig->ctarConfig.pcsToSckDelayInNanoSec);
239 (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_LastSckToPcs, srcClock_Hz,
240 masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec);
241 (void)DSPI_MasterSetDelayTimes(base, masterConfig->whichCtar, kDSPI_BetweenTransfer, srcClock_Hz,
242 masterConfig->ctarConfig.betweenTransferDelayInNanoSec);
243
244 DSPI_SetDummyData(base, DSPI_DUMMY_DATA);
245 DSPI_StartTransfer(base);
246 }
247
248 /*!
249 * brief Sets the dspi_master_config_t structure to default values.
250 *
251 * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit().
252 * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure
253 * before calling the DSPI_MasterInit().
254 * Example:
255 * code
256 * dspi_master_config_t masterConfig;
257 * DSPI_MasterGetDefaultConfig(&masterConfig);
258 * endcode
259 * param masterConfig pointer to dspi_master_config_t structure
260 */
DSPI_MasterGetDefaultConfig(dspi_master_config_t * masterConfig)261 void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig)
262 {
263 assert(NULL != masterConfig);
264
265 /* Initializes the configure structure to zero. */
266 (void)memset(masterConfig, 0, sizeof(*masterConfig));
267
268 masterConfig->whichCtar = kDSPI_Ctar0;
269 masterConfig->ctarConfig.baudRate = 500000;
270 masterConfig->ctarConfig.bitsPerFrame = 8;
271 masterConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
272 masterConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge;
273 masterConfig->ctarConfig.direction = kDSPI_MsbFirst;
274
275 masterConfig->ctarConfig.pcsToSckDelayInNanoSec = 1000;
276 masterConfig->ctarConfig.lastSckToPcsDelayInNanoSec = 1000;
277 masterConfig->ctarConfig.betweenTransferDelayInNanoSec = 1000;
278
279 masterConfig->whichPcs = kDSPI_Pcs0;
280 masterConfig->pcsActiveHighOrLow = kDSPI_PcsActiveLow;
281
282 masterConfig->enableContinuousSCK = false;
283 masterConfig->enableRxFifoOverWrite = false;
284 masterConfig->enableModifiedTimingFormat = false;
285 masterConfig->samplePoint = kDSPI_SckToSin0Clock;
286 }
287
288 /*!
289 * brief DSPI slave configuration.
290 *
291 * This function initializes the DSPI slave configuration. This is an example use case.
292 * code
293 * dspi_slave_config_t slaveConfig;
294 * slaveConfig->whichCtar = kDSPI_Ctar0;
295 * slaveConfig->ctarConfig.bitsPerFrame = 8;
296 * slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
297 * slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge;
298 * slaveConfig->enableContinuousSCK = false;
299 * slaveConfig->enableRxFifoOverWrite = false;
300 * slaveConfig->enableModifiedTimingFormat = false;
301 * slaveConfig->samplePoint = kDSPI_SckToSin0Clock;
302 * DSPI_SlaveInit(base, &slaveConfig);
303 * endcode
304 *
305 * param base DSPI peripheral address.
306 * param slaveConfig Pointer to the structure dspi_master_config_t.
307 */
DSPI_SlaveInit(SPI_Type * base,const dspi_slave_config_t * slaveConfig)308 void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig)
309 {
310 assert(NULL != slaveConfig);
311
312 uint32_t temp = 0;
313
314 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
315 /* enable DSPI clock */
316 CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]);
317 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
318
319 DSPI_Enable(base, true);
320 DSPI_StopTransfer(base);
321
322 DSPI_SetMasterSlaveMode(base, kDSPI_Slave);
323
324 temp = base->MCR & (~(SPI_MCR_CONT_SCKE_MASK | SPI_MCR_MTFE_MASK | SPI_MCR_ROOE_MASK | SPI_MCR_SMPL_PT_MASK |
325 SPI_MCR_DIS_TXF_MASK | SPI_MCR_DIS_RXF_MASK));
326
327 base->MCR = temp | SPI_MCR_CONT_SCKE(slaveConfig->enableContinuousSCK) |
328 SPI_MCR_MTFE(slaveConfig->enableModifiedTimingFormat) |
329 SPI_MCR_ROOE(slaveConfig->enableRxFifoOverWrite) | SPI_MCR_SMPL_PT(slaveConfig->samplePoint) |
330 SPI_MCR_DIS_TXF(0U) | SPI_MCR_DIS_RXF(0U);
331
332 DSPI_SetOnePcsPolarity(base, kDSPI_Pcs0, kDSPI_PcsActiveLow);
333
334 temp = base->CTAR[slaveConfig->whichCtar] &
335 ~(SPI_CTAR_FMSZ_MASK | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_LSBFE_MASK);
336
337 base->CTAR[slaveConfig->whichCtar] = temp | SPI_CTAR_SLAVE_FMSZ(slaveConfig->ctarConfig.bitsPerFrame - 1U) |
338 SPI_CTAR_SLAVE_CPOL(slaveConfig->ctarConfig.cpol) |
339 SPI_CTAR_SLAVE_CPHA(slaveConfig->ctarConfig.cpha);
340
341 DSPI_SetDummyData(base, DSPI_DUMMY_DATA);
342
343 DSPI_StartTransfer(base);
344 }
345
346 /*!
347 * brief Sets the dspi_slave_config_t structure to a default value.
348 *
349 * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit().
350 * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure
351 * before calling the DSPI_SlaveInit().
352 * This is an example.
353 * code
354 * dspi_slave_config_t slaveConfig;
355 * DSPI_SlaveGetDefaultConfig(&slaveConfig);
356 * endcode
357 * param slaveConfig Pointer to the dspi_slave_config_t structure.
358 */
DSPI_SlaveGetDefaultConfig(dspi_slave_config_t * slaveConfig)359 void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig)
360 {
361 assert(NULL != slaveConfig);
362
363 /* Initializes the configure structure to zero. */
364 (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
365
366 slaveConfig->whichCtar = kDSPI_Ctar0;
367 slaveConfig->ctarConfig.bitsPerFrame = 8;
368 slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh;
369 slaveConfig->ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge;
370
371 slaveConfig->enableContinuousSCK = false;
372 slaveConfig->enableRxFifoOverWrite = false;
373 slaveConfig->enableModifiedTimingFormat = false;
374 slaveConfig->samplePoint = kDSPI_SckToSin0Clock;
375 }
376
377 /*!
378 * brief De-initializes the DSPI peripheral. Call this API to disable the DSPI clock.
379 * param base DSPI peripheral address.
380 */
DSPI_Deinit(SPI_Type * base)381 void DSPI_Deinit(SPI_Type *base)
382 {
383 DSPI_StopTransfer(base);
384 DSPI_Enable(base, false);
385
386 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
387 /* disable DSPI clock */
388 CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]);
389 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
390 }
391
DSPI_SetOnePcsPolarity(SPI_Type * base,dspi_which_pcs_t pcs,dspi_pcs_polarity_config_t activeLowOrHigh)392 static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh)
393 {
394 uint32_t temp;
395
396 temp = base->MCR;
397
398 if (activeLowOrHigh == kDSPI_PcsActiveLow)
399 {
400 temp |= SPI_MCR_PCSIS(pcs);
401 }
402 else
403 {
404 temp &= ~SPI_MCR_PCSIS(pcs);
405 }
406
407 base->MCR = temp;
408 }
409
410 /*!
411 * brief Sets the DSPI baud rate in bits per second.
412 *
413 * This function takes in the desired baudRate_Bps (baud rate) and calculates the nearest possible baud rate without
414 * exceeding the desired baud rate, and returns the calculated baud rate in bits-per-second. It requires that the
415 * caller also provide the frequency of the module source clock (in Hertz).
416 *
417 * param base DSPI peripheral address.
418 * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of the type dspi_ctar_selection_t
419 * param baudRate_Bps The desired baud rate in bits per second
420 * param srcClock_Hz Module source input clock in Hertz
421 * return The actual calculated baud rate
422 */
DSPI_MasterSetBaudRate(SPI_Type * base,dspi_ctar_selection_t whichCtar,uint32_t baudRate_Bps,uint32_t srcClock_Hz)423 uint32_t DSPI_MasterSetBaudRate(SPI_Type *base,
424 dspi_ctar_selection_t whichCtar,
425 uint32_t baudRate_Bps,
426 uint32_t srcClock_Hz)
427 {
428 /* for master mode configuration, if slave mode detected, return 0*/
429 if (!DSPI_IsMaster(base))
430 {
431 return 0U;
432 }
433 uint32_t temp;
434 uint32_t prescaler, bestPrescaler;
435 uint32_t scaler, bestScaler;
436 uint32_t dbr, bestDbr;
437 uint32_t realBaudrate, bestBaudrate;
438 uint32_t diff, min_diff;
439 uint32_t baudrate = baudRate_Bps;
440
441 /* find combination of prescaler and scaler resulting in baudrate closest to the requested value */
442 min_diff = 0xFFFFFFFFU;
443 bestPrescaler = 0;
444 bestScaler = 0;
445 bestDbr = 1;
446 bestBaudrate = 0; /* required to avoid compilation warning */
447
448 /* In all for loops, if min_diff = 0, the exit for loop*/
449 for (prescaler = 0U; prescaler < 4U; prescaler++)
450 {
451 for (scaler = 0U; scaler < 16U; scaler++)
452 {
453 for (dbr = 1U; dbr < 3U; dbr++)
454 {
455 realBaudrate = ((srcClock_Hz * dbr) / (s_baudratePrescaler[prescaler] * (s_baudrateScaler[scaler])));
456
457 /* calculate the baud rate difference based on the conditional statement that states that the calculated
458 * baud rate must not exceed the desired baud rate.
459 */
460 if (baudrate >= realBaudrate)
461 {
462 diff = baudrate - realBaudrate;
463 if (min_diff > diff)
464 {
465 /* a better match found */
466 min_diff = diff;
467 bestPrescaler = prescaler;
468 bestScaler = scaler;
469 bestBaudrate = realBaudrate;
470 bestDbr = dbr;
471 }
472 }
473 if (0U == min_diff)
474 {
475 break;
476 }
477 }
478
479 if (0U == min_diff)
480 {
481 break;
482 }
483 }
484 if (0U == min_diff)
485 {
486 break;
487 }
488 }
489
490 /* write the best dbr, prescalar, and baud rate scalar to the CTAR */
491 temp = base->CTAR[whichCtar] & ~(SPI_CTAR_DBR_MASK | SPI_CTAR_PBR_MASK | SPI_CTAR_BR_MASK);
492
493 base->CTAR[whichCtar] = temp | ((bestDbr - 1U) << SPI_CTAR_DBR_SHIFT) | (bestPrescaler << SPI_CTAR_PBR_SHIFT) |
494 (bestScaler << SPI_CTAR_BR_SHIFT);
495
496 /* return the actual calculated baud rate */
497 return bestBaudrate;
498 }
499
500 /*!
501 * brief Manually configures the delay prescaler and scaler for a particular CTAR.
502 *
503 * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar
504 * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT).
505 *
506 * These delay names are available in the type dspi_delay_type_t.
507 *
508 * The user passes the delay to the configuration along with the prescaler and scaler value.
509 * This allows the user to directly set the prescaler/scaler values if pre-calculated or
510 * to manually increment either value.
511 *
512 * param base DSPI peripheral address.
513 * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t.
514 * param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3).
515 * param scaler The scaler delay value (can be any integer between 0 to 15).
516 * param whichDelay The desired delay to configure; must be of type dspi_delay_type_t
517 */
DSPI_MasterSetDelayScaler(SPI_Type * base,dspi_ctar_selection_t whichCtar,uint32_t prescaler,uint32_t scaler,dspi_delay_type_t whichDelay)518 void DSPI_MasterSetDelayScaler(
519 SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay)
520 {
521 /* these settings are only relevant in master mode */
522 if (DSPI_IsMaster(base))
523 {
524 switch (whichDelay)
525 {
526 case kDSPI_PcsToSck:
527 base->CTAR[whichCtar] = (base->CTAR[whichCtar] & (~SPI_CTAR_PCSSCK_MASK) & (~SPI_CTAR_CSSCK_MASK)) |
528 SPI_CTAR_PCSSCK(prescaler) | SPI_CTAR_CSSCK(scaler);
529 break;
530 case kDSPI_LastSckToPcs:
531 base->CTAR[whichCtar] = (base->CTAR[whichCtar] & (~SPI_CTAR_PASC_MASK) & (~SPI_CTAR_ASC_MASK)) |
532 SPI_CTAR_PASC(prescaler) | SPI_CTAR_ASC(scaler);
533 break;
534 case kDSPI_BetweenTransfer:
535 base->CTAR[whichCtar] = (base->CTAR[whichCtar] & (~SPI_CTAR_PDT_MASK) & (~SPI_CTAR_DT_MASK)) |
536 SPI_CTAR_PDT(prescaler) | SPI_CTAR_DT(scaler);
537 break;
538 default:
539 /* All cases have been listed above, the default clause should not be reached. */
540 assert(false);
541 break;
542 }
543 }
544 }
545
546 /*!
547 * brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds.
548 *
549 * This function calculates the values for the following.
550 * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or
551 * After SCK delay pre-scalar (PASC) and scalar (ASC), or
552 * Delay after transfer pre-scalar (PDT) and scalar (DT).
553 *
554 * These delay names are available in the type dspi_delay_type_t.
555 *
556 * The user passes which delay to configure along with the desired delay value in nanoseconds. The function
557 * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact
558 * delay match may not be possible. In this case, the closest match is calculated without going below the desired
559 * delay value input.
560 * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum
561 * supported delay is returned. The higher-level peripheral driver alerts the user of an out of range delay
562 * input.
563 *
564 * param base DSPI peripheral address.
565 * param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t.
566 * param whichDelay The desired delay to configure, must be of type dspi_delay_type_t
567 * param srcClock_Hz Module source input clock in Hertz
568 * param delayTimeInNanoSec The desired delay value in nanoseconds.
569 * return The actual calculated delay value.
570 */
DSPI_MasterSetDelayTimes(SPI_Type * base,dspi_ctar_selection_t whichCtar,dspi_delay_type_t whichDelay,uint32_t srcClock_Hz,uint32_t delayTimeInNanoSec)571 uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base,
572 dspi_ctar_selection_t whichCtar,
573 dspi_delay_type_t whichDelay,
574 uint32_t srcClock_Hz,
575 uint32_t delayTimeInNanoSec)
576 {
577 /* for master mode configuration, if slave mode detected, return 0 */
578 if (!DSPI_IsMaster(base))
579 {
580 return 0U;
581 }
582
583 uint32_t prescaler, bestPrescaler;
584 uint32_t scaler, bestScaler;
585 uint32_t realDelay, bestDelay;
586 uint32_t diff, min_diff;
587 uint32_t initialDelayNanoSec;
588
589 /* find combination of prescaler and scaler resulting in the delay closest to the
590 * requested value
591 */
592 min_diff = 0xFFFFFFFFU;
593 /* Initialize prescaler and scaler to their max values to generate the max delay */
594 bestPrescaler = 0x3;
595 bestScaler = 0xF;
596 bestDelay = (((1000000000U * 4U) / srcClock_Hz) * s_delayPrescaler[bestPrescaler] * s_delayScaler[bestScaler]) / 4U;
597
598 /* First calculate the initial, default delay */
599 initialDelayNanoSec = 1000000000U / srcClock_Hz * 2U;
600
601 /* If the initial, default delay is already greater than the desired delay, then
602 * set the delays to their initial value (0) and return the delay. In other words,
603 * there is no way to decrease the delay value further.
604 */
605 if (initialDelayNanoSec >= delayTimeInNanoSec)
606 {
607 DSPI_MasterSetDelayScaler(base, whichCtar, 0, 0, whichDelay);
608 return initialDelayNanoSec;
609 }
610
611 /* In all for loops, if min_diff = 0, the exit for loop */
612 for (prescaler = 0; prescaler < 4U; prescaler++)
613 {
614 for (scaler = 0; scaler < 16U; scaler++)
615 {
616 realDelay = ((4000000000U / srcClock_Hz) * s_delayPrescaler[prescaler] * s_delayScaler[scaler]) / 4U;
617
618 /* calculate the delay difference based on the conditional statement
619 * that states that the calculated delay must not be less then the desired delay
620 */
621 if (realDelay >= delayTimeInNanoSec)
622 {
623 diff = realDelay - delayTimeInNanoSec;
624 if (min_diff > diff)
625 {
626 /* a better match found */
627 min_diff = diff;
628 bestPrescaler = prescaler;
629 bestScaler = scaler;
630 bestDelay = realDelay;
631 }
632 }
633
634 if (0U == min_diff)
635 {
636 break;
637 }
638 }
639 if (0U == min_diff)
640 {
641 break;
642 }
643 }
644
645 /* write the best dbr, prescalar, and baud rate scalar to the CTAR */
646 DSPI_MasterSetDelayScaler(base, whichCtar, bestPrescaler, bestScaler, whichDelay);
647
648 /* return the actual calculated baud rate */
649 return bestDelay;
650 }
651
652 /*!
653 * brief Sets the dspi_command_data_config_t structure to default values.
654 *
655 * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx().
656 * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure
657 * before calling the DSPI_MasterWrite_xx().
658 * This is an example.
659 * code
660 * dspi_command_data_config_t command;
661 * DSPI_GetDefaultDataCommandConfig(&command);
662 * endcode
663 * param command Pointer to the dspi_command_data_config_t structure.
664 */
DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t * command)665 void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command)
666 {
667 assert(NULL != command);
668
669 /* Initializes the configure structure to zero. */
670 (void)memset(command, 0, sizeof(*command));
671
672 command->isPcsContinuous = false;
673 command->whichCtar = (uint8_t)kDSPI_Ctar0;
674 command->whichPcs = (uint8_t)kDSPI_Pcs0;
675 command->isEndOfQueue = false;
676 command->clearTransferCount = false;
677 }
678
679 /*!
680 * brief Writes data into the data buffer master mode and waits till complete to return.
681 *
682 * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion
683 * provides characteristics of the data, such as the optional continuous chip select
684 * operation between transfers, the desired Clock and Transfer Attributes register to use for the
685 * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current
686 * transfer is the last in the queue, and whether to clear the transfer count (normally needed when
687 * sending the first frame of a data packet). This is an example.
688 * code
689 * dspi_command_config_t commandConfig;
690 * commandConfig.isPcsContinuous = true;
691 * commandConfig.whichCtar = kDSPICtar0;
692 * commandConfig.whichPcs = kDSPIPcs1;
693 * commandConfig.clearTransferCount = false;
694 * commandConfig.isEndOfQueue = false;
695 * DSPI_MasterWriteDataBlocking(base, &commandConfig, dataWord);
696 * endcode
697 *
698 * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be
699 * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol,
700 * the received data is available when the transmit completes.
701 *
702 * param base DSPI peripheral address.
703 * param command Pointer to the command structure.
704 * param data The data word to be sent.
705 */
DSPI_MasterWriteDataBlocking(SPI_Type * base,dspi_command_data_config_t * command,uint16_t data)706 void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data)
707 {
708 assert(NULL != command);
709
710 /* First, clear Transmit Complete Flag (TCF) */
711 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag);
712
713 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
714 {
715 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
716 }
717
718 base->PUSHR = SPI_PUSHR_CONT(command->isPcsContinuous) | SPI_PUSHR_CTAS(command->whichCtar) |
719 SPI_PUSHR_PCS(command->whichPcs) | SPI_PUSHR_EOQ(command->isEndOfQueue) |
720 SPI_PUSHR_CTCNT(command->clearTransferCount) | SPI_PUSHR_TXDATA(data);
721 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
722
723 /* Wait till TCF sets */
724 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag))
725 {
726 }
727 }
728
729 /*!
730 * brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data
731 * buffer master mode and waits till complete to return.
732 *
733 * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total
734 * 32-bit word
735 * as the data to send.
736 * The command portion provides characteristics of the data, such as the optional continuous chip select operation
737 * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the
738 * desired PCS
739 * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the
740 * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for
741 * appending this command with the data to send. This is an example:
742 * code
743 * dataWord = <16-bit command> | <16-bit data>;
744 * DSPI_MasterWriteCommandDataBlocking(base, dataWord);
745 * endcode
746 *
747 * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be
748 * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0).
749 * Because the SPI is a synchronous protocol, the received data is available when the transmit completes.
750 *
751 * For a blocking polling transfer, see methods below.
752 * Option 1:
753 * uint32_t command_to_send = DSPI_MasterGetFormattedCommand(&command);
754 * uint32_t data0 = command_to_send | data_need_to_send_0;
755 * uint32_t data1 = command_to_send | data_need_to_send_1;
756 * uint32_t data2 = command_to_send | data_need_to_send_2;
757 *
758 * DSPI_MasterWriteCommandDataBlocking(base,data0);
759 * DSPI_MasterWriteCommandDataBlocking(base,data1);
760 * DSPI_MasterWriteCommandDataBlocking(base,data2);
761 *
762 * Option 2:
763 * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_0);
764 * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_1);
765 * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2);
766 *
767 * param base DSPI peripheral address.
768 * param data The data word (command and data combined) to be sent.
769 */
DSPI_MasterWriteCommandDataBlocking(SPI_Type * base,uint32_t data)770 void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data)
771 {
772 /* First, clear Transmit Complete Flag (TCF) */
773 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag);
774
775 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
776 {
777 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
778 }
779
780 base->PUSHR = data;
781
782 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
783
784 /* Wait till TCF sets */
785 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag))
786 {
787 }
788 }
789
790 /*!
791 * brief Writes data into the data buffer in slave mode, waits till data was transmitted, and returns.
792 *
793 * In slave mode, up to 16-bit words may be written. The function first clears the transmit complete flag, writes data
794 * into data register, and finally waits until the data is transmitted.
795 *
796 * param base DSPI peripheral address.
797 * param data The data to send.
798 */
DSPI_SlaveWriteDataBlocking(SPI_Type * base,uint32_t data)799 void DSPI_SlaveWriteDataBlocking(SPI_Type *base, uint32_t data)
800 {
801 /* First, clear Transmit Complete Flag (TCF) */
802 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxCompleteFlag);
803
804 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
805 {
806 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
807 }
808
809 base->PUSHR_SLAVE = data;
810
811 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
812
813 /* Wait till TCF sets */
814 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxCompleteFlag))
815 {
816 }
817 }
818
819 /*!
820 * brief Enables the DSPI interrupts.
821 *
822 * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask.
823 * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request.
824 * Do not use this API(write to RSER register) while DSPI is in running state.
825 *
826 * code
827 * DSPI_EnableInterrupts(base, kDSPI_TxCompleteInterruptEnable | kDSPI_EndOfQueueInterruptEnable );
828 * endcode
829 *
830 * param base DSPI peripheral address.
831 * param mask The interrupt mask; use the enum _dspi_interrupt_enable.
832 */
DSPI_EnableInterrupts(SPI_Type * base,uint32_t mask)833 void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
834 {
835 if (0U != (mask & SPI_RSER_TFFF_RE_MASK))
836 {
837 base->RSER &= ~SPI_RSER_TFFF_DIRS_MASK;
838 }
839 if (0U != (mask & SPI_RSER_RFDF_RE_MASK))
840 {
841 base->RSER &= ~SPI_RSER_RFDF_DIRS_MASK;
842 }
843 base->RSER |= mask;
844 }
845
846 /*Transactional APIs -- Master*/
847
848 /*!
849 * brief Initializes the DSPI master handle.
850 *
851 * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a
852 * specified DSPI instance, call this API once to get the initialized handle.
853 *
854 * param base DSPI peripheral base address.
855 * param handle DSPI handle pointer to dspi_master_handle_t.
856 * param callback DSPI callback.
857 * param userData Callback function parameter.
858 */
DSPI_MasterTransferCreateHandle(SPI_Type * base,dspi_master_handle_t * handle,dspi_master_transfer_callback_t callback,void * userData)859 void DSPI_MasterTransferCreateHandle(SPI_Type *base,
860 dspi_master_handle_t *handle,
861 dspi_master_transfer_callback_t callback,
862 void *userData)
863 {
864 assert(NULL != handle);
865
866 /* Zero the handle. */
867 (void)memset(handle, 0, sizeof(*handle));
868
869 g_dspiHandle[DSPI_GetInstance(base)] = handle;
870
871 handle->callback = callback;
872 handle->userData = userData;
873 }
874
875 /*!
876 * brief DSPI master transfer data using polling.
877 *
878 * This function transfers data using polling. This is a blocking function, which does not return until all transfers
879 * have been completed.
880 *
881 * param base DSPI peripheral base address.
882 * param transfer Pointer to the dspi_transfer_t structure.
883 * return status of status_t.
884 */
DSPI_MasterTransferBlocking(SPI_Type * base,dspi_transfer_t * transfer)885 status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer)
886 {
887 assert(NULL != transfer);
888
889 uint16_t wordToSend = 0;
890 uint16_t wordReceived = 0;
891 uint8_t dummyData = DSPI_GetDummyDataInstance(base);
892 uint8_t bitsPerFrame;
893
894 uint32_t command;
895 uint32_t lastCommand;
896
897 const uint8_t *txData;
898 uint8_t *rxData;
899 uint32_t remainingSendByteCount;
900 uint32_t remainingReceiveByteCount;
901
902 uint32_t fifoSize;
903 uint32_t tmpMCR = 0;
904 dspi_command_data_config_t commandStruct;
905
906 /* If the transfer count is zero, then return immediately.*/
907 if (transfer->dataSize == 0U)
908 {
909 return kStatus_InvalidArgument;
910 }
911
912 DSPI_StopTransfer(base);
913 DSPI_DisableInterrupts(base, (uint32_t)kDSPI_AllInterruptEnable);
914 DSPI_FlushFifo(base, true, true);
915 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
916
917 /*Calculate the command and lastCommand*/
918 commandStruct.whichPcs =
919 (uint8_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
920 commandStruct.isEndOfQueue = false;
921 commandStruct.clearTransferCount = false;
922 commandStruct.whichCtar = (uint8_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
923 commandStruct.isPcsContinuous =
924 (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
925
926 command = DSPI_MasterGetFormattedCommand(&(commandStruct));
927
928 commandStruct.isEndOfQueue = true;
929 commandStruct.isPcsContinuous =
930 (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
931 lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
932
933 /*Calculate the bitsPerFrame*/
934 bitsPerFrame = (uint8_t)(((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U);
935
936 txData = transfer->txData;
937 rxData = transfer->rxData;
938 remainingSendByteCount = transfer->dataSize;
939 remainingReceiveByteCount = transfer->dataSize;
940
941 tmpMCR = base->MCR;
942 if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK)))
943 {
944 fifoSize = 1U;
945 }
946 else
947 {
948 fifoSize = (uint32_t)FSL_FEATURE_DSPI_FIFO_SIZEn(base);
949 }
950
951 DSPI_StartTransfer(base);
952
953 if (bitsPerFrame <= 8U)
954 {
955 while (remainingSendByteCount > 0U)
956 {
957 if (remainingSendByteCount == 1U)
958 {
959 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
960 {
961 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
962 }
963
964 if (txData != NULL)
965 {
966 base->PUSHR = (*txData) | (lastCommand);
967 txData++;
968 }
969 else
970 {
971 base->PUSHR = (lastCommand) | (dummyData);
972 }
973 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
974 remainingSendByteCount--;
975
976 while (remainingReceiveByteCount > 0U)
977 {
978 if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
979 (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
980 {
981 if (rxData != NULL)
982 {
983 /* Read data from POPR*/
984 *(rxData) = (uint8_t)DSPI_ReadData(base);
985 rxData++;
986 }
987 else
988 {
989 (void)DSPI_ReadData(base);
990 }
991 remainingReceiveByteCount--;
992
993 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
994 }
995 }
996 }
997 else
998 {
999 /*Wait until Tx Fifo is not full*/
1000 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
1001 {
1002 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1003 }
1004 if (txData != NULL)
1005 {
1006 base->PUSHR = command | (uint16_t)(*txData);
1007 txData++;
1008 }
1009 else
1010 {
1011 base->PUSHR = command | dummyData;
1012 }
1013 remainingSendByteCount--;
1014
1015 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1016
1017 while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize)
1018 {
1019 if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
1020 (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
1021 {
1022 if (rxData != NULL)
1023 {
1024 *(rxData) = (uint8_t)DSPI_ReadData(base);
1025 rxData++;
1026 }
1027 else
1028 {
1029 (void)DSPI_ReadData(base);
1030 }
1031 remainingReceiveByteCount--;
1032
1033 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
1034 }
1035 }
1036 }
1037 }
1038 }
1039 else
1040 {
1041 while (remainingSendByteCount > 0U)
1042 {
1043 if (remainingSendByteCount <= 2U)
1044 {
1045 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
1046 {
1047 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1048 }
1049
1050 if (txData != NULL)
1051 {
1052 wordToSend = *(txData);
1053 ++txData;
1054
1055 if (remainingSendByteCount > 1U)
1056 {
1057 wordToSend |= (uint16_t)(*(txData)) << 8U;
1058 ++txData;
1059 }
1060 }
1061 else
1062 {
1063 wordToSend = dummyData;
1064 }
1065
1066 base->PUSHR = lastCommand | wordToSend;
1067
1068 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1069 remainingSendByteCount = 0;
1070
1071 while (remainingReceiveByteCount > 0U)
1072 {
1073 if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
1074 (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
1075 {
1076 wordReceived = (uint16_t)DSPI_ReadData(base);
1077
1078 if (remainingReceiveByteCount != 1U)
1079 {
1080 if (rxData != NULL)
1081 {
1082 *(rxData) = (uint8_t)wordReceived;
1083 ++rxData;
1084 *(rxData) = (uint8_t)(wordReceived >> 8U);
1085 ++rxData;
1086 }
1087 remainingReceiveByteCount -= 2U;
1088 }
1089 else
1090 {
1091 if (rxData != NULL)
1092 {
1093 *(rxData) = (uint8_t)wordReceived;
1094 ++rxData;
1095 }
1096 remainingReceiveByteCount--;
1097 }
1098 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
1099 }
1100 }
1101 }
1102 else
1103 {
1104 /*Wait until Tx Fifo is not full*/
1105 while (0U == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
1106 {
1107 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1108 }
1109
1110 if (txData != NULL)
1111 {
1112 wordToSend = *(txData);
1113 ++txData;
1114 wordToSend |= (uint16_t)(*(txData)) << 8U;
1115 ++txData;
1116 }
1117 else
1118 {
1119 wordToSend = dummyData;
1120 }
1121 base->PUSHR = command | wordToSend;
1122 remainingSendByteCount -= 2U;
1123
1124 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1125
1126 while (((remainingReceiveByteCount - remainingSendByteCount) / 2U) >= fifoSize)
1127 {
1128 if ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
1129 (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
1130 {
1131 wordReceived = (uint16_t)DSPI_ReadData(base);
1132
1133 if (rxData != NULL)
1134 {
1135 *rxData = (uint8_t)wordReceived;
1136 ++rxData;
1137 *rxData = (uint8_t)(wordReceived >> 8U);
1138 ++rxData;
1139 }
1140 remainingReceiveByteCount -= 2U;
1141
1142 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
1143 }
1144 }
1145 }
1146 }
1147 }
1148
1149 return kStatus_Success;
1150 }
1151
DSPI_MasterTransferPrepare(SPI_Type * base,dspi_master_handle_t * handle,dspi_transfer_t * transfer)1152 static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer)
1153 {
1154 assert(NULL != handle);
1155 assert(NULL != transfer);
1156
1157 uint32_t tmpMCR = 0;
1158 dspi_command_data_config_t commandStruct = {false, (uint8_t)kDSPI_Ctar0, (uint8_t)kDSPI_Pcs0, false, false};
1159
1160 DSPI_StopTransfer(base);
1161 DSPI_FlushFifo(base, true, true);
1162 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
1163
1164 commandStruct.whichPcs =
1165 (uint8_t)((uint32_t)1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
1166 commandStruct.isEndOfQueue = false;
1167 commandStruct.clearTransferCount = false;
1168 commandStruct.whichCtar = (uint8_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
1169 commandStruct.isPcsContinuous =
1170 (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterPcsContinuous)) ? true : false;
1171 handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct));
1172
1173 commandStruct.isEndOfQueue = true;
1174 commandStruct.isPcsContinuous =
1175 (0U != (transfer->configFlags & (uint32_t)kDSPI_MasterActiveAfterTransfer)) ? true : false;
1176 handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
1177
1178 handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1U;
1179
1180 tmpMCR = base->MCR;
1181 if ((0U != (tmpMCR & SPI_MCR_DIS_RXF_MASK)) || (0U != (tmpMCR & SPI_MCR_DIS_TXF_MASK)))
1182 {
1183 handle->fifoSize = 1U;
1184 }
1185 else
1186 {
1187 handle->fifoSize = (uint8_t)FSL_FEATURE_DSPI_FIFO_SIZEn(base);
1188 }
1189 handle->txData = transfer->txData;
1190 handle->rxData = transfer->rxData;
1191 handle->remainingSendByteCount = transfer->dataSize;
1192 handle->remainingReceiveByteCount = transfer->dataSize;
1193 handle->totalByteCount = transfer->dataSize;
1194 }
1195
1196 /*!
1197 * brief DSPI master transfer data using interrupts.
1198 *
1199 * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all
1200 * data is transferred, the callback function is called.
1201
1202 * param base DSPI peripheral base address.
1203 * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
1204 * param transfer Pointer to the dspi_transfer_t structure.
1205 * return status of status_t.
1206 */
DSPI_MasterTransferNonBlocking(SPI_Type * base,dspi_master_handle_t * handle,dspi_transfer_t * transfer)1207 status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer)
1208 {
1209 assert(NULL != handle);
1210 assert(NULL != transfer);
1211
1212 /* If the transfer count is zero, then return immediately.*/
1213 if (transfer->dataSize == 0U)
1214 {
1215 return kStatus_InvalidArgument;
1216 }
1217
1218 /* Check that we're not busy.*/
1219 if (handle->state == (uint8_t)kDSPI_Busy)
1220 {
1221 return kStatus_DSPI_Busy;
1222 }
1223
1224 handle->state = (uint8_t)kDSPI_Busy;
1225
1226 /* Disable the NVIC for DSPI peripheral. */
1227 (void)DisableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]);
1228
1229 DSPI_MasterTransferPrepare(base, handle, transfer);
1230
1231 /* RX FIFO Drain request: RFDF_RE to enable RFDF interrupt
1232 * Since SPI is a synchronous interface, we only need to enable the RX interrupt.
1233 * The IRQ handler will get the status of RX and TX interrupt flags.
1234 */
1235 s_dspiMasterIsr = DSPI_MasterTransferHandleIRQ;
1236
1237 DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable);
1238 DSPI_StartTransfer(base);
1239
1240 /* Fill up the Tx FIFO to trigger the transfer. */
1241 DSPI_MasterTransferFillUpTxFifo(base, handle);
1242
1243 /* Enable the NVIC for DSPI peripheral. */
1244 (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]);
1245
1246 return kStatus_Success;
1247 }
1248
1249 /*!
1250 * brief Transfers a block of data using a polling method.
1251 *
1252 * This function will do a half-duplex transfer for DSPI master, This is a blocking function,
1253 * which does not retuen until all transfer have been completed. And data transfer will be half-duplex,
1254 * users can set transmit first or receive first.
1255 *
1256 * param base DSPI base pointer
1257 * param xfer pointer to dspi_half_duplex_transfer_t structure
1258 * return status of status_t.
1259 */
DSPI_MasterHalfDuplexTransferBlocking(SPI_Type * base,dspi_half_duplex_transfer_t * xfer)1260 status_t DSPI_MasterHalfDuplexTransferBlocking(SPI_Type *base, dspi_half_duplex_transfer_t *xfer)
1261 {
1262 assert(NULL != xfer);
1263
1264 dspi_transfer_t tempXfer = {0};
1265 status_t status;
1266
1267 if (true == xfer->isTransmitFirst)
1268 {
1269 tempXfer.txData = xfer->txData;
1270 tempXfer.rxData = NULL;
1271 tempXfer.dataSize = xfer->txDataSize;
1272 }
1273 else
1274 {
1275 tempXfer.txData = NULL;
1276 tempXfer.rxData = xfer->rxData;
1277 tempXfer.dataSize = xfer->rxDataSize;
1278 }
1279 /* If the pcs pin keep assert between transmit and receive. */
1280 if (true == xfer->isPcsAssertInTransfer)
1281 {
1282 tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer;
1283 }
1284 else
1285 {
1286 tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer);
1287 }
1288
1289 status = DSPI_MasterTransferBlocking(base, &tempXfer);
1290 if (status != kStatus_Success)
1291 {
1292 return status;
1293 }
1294
1295 if (true == xfer->isTransmitFirst)
1296 {
1297 tempXfer.txData = NULL;
1298 tempXfer.rxData = xfer->rxData;
1299 tempXfer.dataSize = xfer->rxDataSize;
1300 }
1301 else
1302 {
1303 tempXfer.txData = xfer->txData;
1304 tempXfer.rxData = NULL;
1305 tempXfer.dataSize = xfer->txDataSize;
1306 }
1307 tempXfer.configFlags = xfer->configFlags;
1308
1309 /* DSPI transfer blocking. */
1310 status = DSPI_MasterTransferBlocking(base, &tempXfer);
1311
1312 return status;
1313 }
1314
1315 /*!
1316 * brief Performs a non-blocking DSPI interrupt transfer.
1317 *
1318 * This function transfers data using interrupts, the transfer mechanism is half-duplex. This is a non-blocking
1319 * function,
1320 * which returns right away. When all data is transferred, the callback function is called.
1321 *
1322 * param base DSPI peripheral base address.
1323 * param handle pointer to dspi_master_handle_t structure which stores the transfer state
1324 * param xfer pointer to dspi_half_duplex_transfer_t structure
1325 * return status of status_t.
1326 */
DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type * base,dspi_master_handle_t * handle,dspi_half_duplex_transfer_t * xfer)1327 status_t DSPI_MasterHalfDuplexTransferNonBlocking(SPI_Type *base,
1328 dspi_master_handle_t *handle,
1329 dspi_half_duplex_transfer_t *xfer)
1330 {
1331 assert(NULL != xfer);
1332 assert(NULL != handle);
1333 dspi_transfer_t tempXfer = {0};
1334 status_t status;
1335
1336 if (true == xfer->isTransmitFirst)
1337 {
1338 tempXfer.txData = xfer->txData;
1339 tempXfer.rxData = NULL;
1340 tempXfer.dataSize = xfer->txDataSize;
1341 }
1342 else
1343 {
1344 tempXfer.txData = NULL;
1345 tempXfer.rxData = xfer->rxData;
1346 tempXfer.dataSize = xfer->rxDataSize;
1347 }
1348 /* If the pcs pin keep assert between transmit and receive. */
1349 if (true == xfer->isPcsAssertInTransfer)
1350 {
1351 tempXfer.configFlags = (xfer->configFlags) | (uint32_t)kDSPI_MasterActiveAfterTransfer;
1352 }
1353 else
1354 {
1355 tempXfer.configFlags = (xfer->configFlags) & (~(uint32_t)kDSPI_MasterActiveAfterTransfer);
1356 }
1357
1358 status = DSPI_MasterTransferBlocking(base, &tempXfer);
1359 if (status != kStatus_Success)
1360 {
1361 return status;
1362 }
1363
1364 if (true == xfer->isTransmitFirst)
1365 {
1366 tempXfer.txData = NULL;
1367 tempXfer.rxData = xfer->rxData;
1368 tempXfer.dataSize = xfer->rxDataSize;
1369 }
1370 else
1371 {
1372 tempXfer.txData = xfer->txData;
1373 tempXfer.rxData = NULL;
1374 tempXfer.dataSize = xfer->txDataSize;
1375 }
1376 tempXfer.configFlags = xfer->configFlags;
1377
1378 status = DSPI_MasterTransferNonBlocking(base, handle, &tempXfer);
1379
1380 return status;
1381 }
1382
1383 /*!
1384 * brief Gets the master transfer count.
1385 *
1386 * This function gets the master transfer count.
1387 *
1388 * param base DSPI peripheral base address.
1389 * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
1390 * param count The number of bytes transferred by using the non-blocking transaction.
1391 * return status of status_t.
1392 */
DSPI_MasterTransferGetCount(SPI_Type * base,dspi_master_handle_t * handle,size_t * count)1393 status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count)
1394 {
1395 assert(NULL != handle);
1396
1397 if (NULL == count)
1398 {
1399 return kStatus_InvalidArgument;
1400 }
1401
1402 /* Catch when there is not an active transfer. */
1403 if (handle->state != (uint8_t)kDSPI_Busy)
1404 {
1405 *count = 0;
1406 return kStatus_NoTransferInProgress;
1407 }
1408
1409 *count = handle->totalByteCount - handle->remainingReceiveByteCount;
1410 return kStatus_Success;
1411 }
1412
DSPI_MasterTransferComplete(SPI_Type * base,dspi_master_handle_t * handle)1413 static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle)
1414 {
1415 assert(NULL != handle);
1416
1417 /* Disable interrupt requests*/
1418 DSPI_DisableInterrupts(
1419 base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable));
1420
1421 status_t status = 0;
1422 if (handle->state == (uint8_t)kDSPI_Error)
1423 {
1424 status = kStatus_DSPI_Error;
1425 }
1426 else
1427 {
1428 status = kStatus_Success;
1429 }
1430
1431 if ((NULL != handle->callback) && ((uint8_t)kDSPI_Idle != handle->state))
1432 {
1433 handle->state = (uint8_t)kDSPI_Idle;
1434 handle->callback(base, handle, status, handle->userData);
1435 }
1436 }
1437
DSPI_MasterTransferFillUpTxFifo(SPI_Type * base,dspi_master_handle_t * handle)1438 static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle)
1439 {
1440 assert(NULL != handle);
1441
1442 uint16_t wordToSend = 0;
1443 uint8_t dummyData = DSPI_GetDummyDataInstance(base);
1444 size_t tmpRemainingSendByteCount = handle->remainingSendByteCount;
1445 size_t tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount;
1446 uint8_t tmpFifoSize = handle->fifoSize;
1447
1448 /* If bits/frame is greater than one byte */
1449 if (handle->bitsPerFrame > 8U)
1450 {
1451 /* Fill the fifo until it is full or until the send word count is 0 or until the difference
1452 * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth.
1453 * The reason for checking the difference is to ensure we only send as much as the
1454 * RX FIFO can receive.
1455 * For this case where bitsPerFrame > 8, each entry in the FIFO contains 2 bytes of the
1456 * send data, hence the difference between the remainingReceiveByteCount and
1457 * remainingSendByteCount must be divided by 2 to convert this difference into a
1458 * 16-bit (2 byte) value.
1459 */
1460 while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) &&
1461 (((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) / 2U) < tmpFifoSize))
1462 {
1463 if (handle->remainingSendByteCount <= 2U)
1464 {
1465 if (NULL != handle->txData)
1466 {
1467 if (handle->remainingSendByteCount == 1U)
1468 {
1469 wordToSend = *(handle->txData);
1470 }
1471 else
1472 {
1473 wordToSend = *(handle->txData);
1474 ++handle->txData; /* increment to next data byte */
1475 wordToSend |= (uint16_t)(*(handle->txData)) << 8U;
1476 }
1477 }
1478 else
1479 {
1480 wordToSend = dummyData;
1481 }
1482 handle->remainingSendByteCount = 0;
1483 base->PUSHR = handle->lastCommand | wordToSend;
1484 }
1485 /* For all words except the last word */
1486 else
1487 {
1488 if (NULL != handle->txData)
1489 {
1490 wordToSend = *(handle->txData);
1491 ++handle->txData; /* increment to next data byte */
1492 wordToSend |= (uint16_t)(*(handle->txData)) << 8U;
1493 ++handle->txData; /* increment to next data byte */
1494 }
1495 else
1496 {
1497 wordToSend = dummyData;
1498 }
1499 handle->remainingSendByteCount -= 2U; /* decrement remainingSendByteCount by 2 */
1500 base->PUSHR = handle->command | wordToSend;
1501 }
1502
1503 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
1504 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1505
1506 /* exit loop if send count is zero, else update local variables for next loop.
1507 * If this is the first time write to the PUSHR, write only once.
1508 */
1509 tmpRemainingSendByteCount = handle->remainingSendByteCount;
1510 if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == handle->totalByteCount - 2U))
1511 {
1512 break;
1513 }
1514 tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount;
1515 tmpRemainingSendByteCount = handle->remainingSendByteCount;
1516 tmpFifoSize = handle->fifoSize;
1517 } /* End of TX FIFO fill while loop */
1518 }
1519 /* Optimized for bits/frame less than or equal to one byte. */
1520 else
1521 {
1522 /* Fill the fifo until it is full or until the send word count is 0 or until the difference
1523 * between the remainingReceiveByteCount and remainingSendByteCount equals the FIFO depth.
1524 * The reason for checking the difference is to ensure we only send as much as the
1525 * RX FIFO can receive.
1526 */
1527 while ((0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag)) &&
1528 ((tmpRemainingReceiveByteCount - tmpRemainingSendByteCount) < tmpFifoSize))
1529 {
1530 if (NULL != handle->txData)
1531 {
1532 wordToSend = *(handle->txData);
1533 ++handle->txData;
1534 }
1535 else
1536 {
1537 wordToSend = dummyData;
1538 }
1539
1540 if (handle->remainingSendByteCount == 1U)
1541 {
1542 base->PUSHR = handle->lastCommand | wordToSend;
1543 }
1544 else
1545 {
1546 base->PUSHR = handle->command | wordToSend;
1547 }
1548
1549 /* Try to clear the TFFF; if the TX FIFO is full this will clear */
1550 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1551
1552 --handle->remainingSendByteCount;
1553
1554 /* exit loop if send count is zero, else update local variables for next loop
1555 * If this is the first time write to the PUSHR, write only once.
1556 */
1557 tmpRemainingSendByteCount = handle->remainingSendByteCount;
1558 if ((tmpRemainingSendByteCount == 0U) || (tmpRemainingSendByteCount == (handle->totalByteCount - 1U)))
1559 {
1560 break;
1561 }
1562 tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount;
1563 tmpRemainingSendByteCount = handle->remainingSendByteCount;
1564 tmpFifoSize = handle->fifoSize;
1565 }
1566 }
1567 }
1568
1569 /*!
1570 * brief DSPI master aborts a transfer using an interrupt.
1571 *
1572 * This function aborts a transfer using an interrupt.
1573 *
1574 * param base DSPI peripheral base address.
1575 * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
1576 */
DSPI_MasterTransferAbort(SPI_Type * base,dspi_master_handle_t * handle)1577 void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle)
1578 {
1579 assert(NULL != handle);
1580
1581 DSPI_StopTransfer(base);
1582
1583 /* Disable interrupt requests*/
1584 DSPI_DisableInterrupts(
1585 base, ((uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable));
1586
1587 handle->state = (uint8_t)kDSPI_Idle;
1588 }
1589
1590 /*!
1591 * brief DSPI Master IRQ handler function.
1592 *
1593 * This function processes the DSPI transmit and receive IRQ.
1594
1595 * param base DSPI peripheral base address.
1596 * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
1597 */
DSPI_MasterTransferHandleIRQ(SPI_Type * base,dspi_master_handle_t * handle)1598 void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle)
1599 {
1600 assert(NULL != handle);
1601
1602 /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */
1603 if (0U != (handle->remainingReceiveByteCount))
1604 {
1605 /* Check read buffer.*/
1606 uint16_t wordReceived; /* Maximum supported data bit length in master mode is 16-bits */
1607
1608 /* If bits/frame is greater than one byte */
1609 if (handle->bitsPerFrame > 8U)
1610 {
1611 while ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
1612 (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
1613 {
1614 wordReceived = (uint16_t)DSPI_ReadData(base);
1615 /* clear the rx fifo drain request, needed for non-DMA applications as this flag
1616 * will remain set even if the rx fifo is empty. By manually clearing this flag, it
1617 * either remain clear if no more data is in the fifo, or it will set if there is
1618 * more data in the fifo.
1619 */
1620 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
1621
1622 /* Store read bytes into rx buffer only if a buffer pointer was provided */
1623 if (NULL != handle->rxData)
1624 {
1625 /* For the last word received, if there is an extra byte due to the odd transfer
1626 * byte count, only save the last byte and discard the upper byte
1627 */
1628 if (handle->remainingReceiveByteCount == 1U)
1629 {
1630 *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */
1631 --handle->remainingReceiveByteCount;
1632 }
1633 else
1634 {
1635 *handle->rxData = (uint8_t)wordReceived; /* Write first data byte */
1636 ++handle->rxData; /* increment to next data byte */
1637 *handle->rxData = (uint8_t)(wordReceived >> 8U); /* Write second data byte */
1638 ++handle->rxData; /* increment to next data byte */
1639 handle->remainingReceiveByteCount -= 2U;
1640 }
1641 }
1642 else
1643 {
1644 if (handle->remainingReceiveByteCount == 1U)
1645 {
1646 --handle->remainingReceiveByteCount;
1647 }
1648 else
1649 {
1650 handle->remainingReceiveByteCount -= 2U;
1651 }
1652 }
1653 if (handle->remainingReceiveByteCount == 0U)
1654 {
1655 break;
1656 }
1657 } /* End of RX FIFO drain while loop */
1658 }
1659 /* Optimized for bits/frame less than or equal to one byte. */
1660 else
1661 {
1662 while ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
1663 (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
1664 {
1665 wordReceived = (uint16_t)DSPI_ReadData(base);
1666 /* clear the rx fifo drain request, needed for non-DMA applications as this flag
1667 * will remain set even if the rx fifo is empty. By manually clearing this flag, it
1668 * either remain clear if no more data is in the fifo, or it will set if there is
1669 * more data in the fifo.
1670 */
1671 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
1672
1673 /* Store read bytes into rx buffer only if a buffer pointer was provided */
1674 if (NULL != handle->rxData)
1675 {
1676 *handle->rxData = (uint8_t)wordReceived;
1677 ++handle->rxData;
1678 }
1679
1680 --handle->remainingReceiveByteCount;
1681
1682 if (handle->remainingReceiveByteCount == 0U)
1683 {
1684 break;
1685 }
1686 } /* End of RX FIFO drain while loop */
1687 }
1688 }
1689
1690 /* Check write buffer. We always have to send a word in order to keep the transfer
1691 * moving. So if the caller didn't provide a send buffer, we just send a zero.
1692 */
1693 if (0U != (handle->remainingSendByteCount))
1694 {
1695 DSPI_MasterTransferFillUpTxFifo(base, handle);
1696 }
1697
1698 /* Check if we're done with this transfer.*/
1699 if (handle->remainingSendByteCount == 0U)
1700 {
1701 if (handle->remainingReceiveByteCount == 0U)
1702 {
1703 /* Complete the transfer and disable the interrupts */
1704 DSPI_MasterTransferComplete(base, handle);
1705 }
1706 }
1707 }
1708
1709 /*Transactional APIs -- Slave*/
1710 /*!
1711 * brief Initializes the DSPI slave handle.
1712 *
1713 * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a
1714 * specified DSPI instance, call this API once to get the initialized handle.
1715 *
1716 * param handle DSPI handle pointer to the dspi_slave_handle_t.
1717 * param base DSPI peripheral base address.
1718 * param callback DSPI callback.
1719 * param userData Callback function parameter.
1720 */
DSPI_SlaveTransferCreateHandle(SPI_Type * base,dspi_slave_handle_t * handle,dspi_slave_transfer_callback_t callback,void * userData)1721 void DSPI_SlaveTransferCreateHandle(SPI_Type *base,
1722 dspi_slave_handle_t *handle,
1723 dspi_slave_transfer_callback_t callback,
1724 void *userData)
1725 {
1726 assert(NULL != handle);
1727
1728 /* Zero the handle. */
1729 (void)memset(handle, 0, sizeof(*handle));
1730
1731 g_dspiHandle[DSPI_GetInstance(base)] = handle;
1732
1733 handle->callback = callback;
1734 handle->userData = userData;
1735 }
1736
1737 /*!
1738 * brief DSPI slave transfers data using an interrupt.
1739 *
1740 * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all
1741 * data is transferred, the callback function is called.
1742 *
1743 * param base DSPI peripheral base address.
1744 * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state.
1745 * param transfer Pointer to the dspi_transfer_t structure.
1746 * return status of status_t.
1747 */
DSPI_SlaveTransferNonBlocking(SPI_Type * base,dspi_slave_handle_t * handle,dspi_transfer_t * transfer)1748 status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer)
1749 {
1750 assert(NULL != handle);
1751 assert(NULL != transfer);
1752
1753 /* If receive length is zero */
1754 if (transfer->dataSize == 0U)
1755 {
1756 return kStatus_InvalidArgument;
1757 }
1758
1759 /* If both send buffer and receive buffer is null */
1760 if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData)))
1761 {
1762 return kStatus_InvalidArgument;
1763 }
1764
1765 /* Check that we're not busy.*/
1766 if (handle->state == (uint8_t)kDSPI_Busy)
1767 {
1768 return kStatus_DSPI_Busy;
1769 }
1770 handle->state = (uint8_t)kDSPI_Busy;
1771
1772 /* Enable the NVIC for DSPI peripheral. */
1773 (void)EnableIRQ(s_dspiIRQ[DSPI_GetInstance(base)]);
1774
1775 /* Store transfer information */
1776 handle->txData = transfer->txData;
1777 handle->rxData = transfer->rxData;
1778 handle->remainingSendByteCount = transfer->dataSize;
1779 handle->remainingReceiveByteCount = transfer->dataSize;
1780 handle->totalByteCount = transfer->dataSize;
1781
1782 handle->errorCount = 0;
1783
1784 uint8_t whichCtar = (uint8_t)((transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT);
1785 handle->bitsPerFrame =
1786 (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1U;
1787
1788 DSPI_StopTransfer(base);
1789
1790 DSPI_FlushFifo(base, true, true);
1791 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_AllStatusFlag);
1792
1793 s_dspiSlaveIsr = DSPI_SlaveTransferHandleIRQ;
1794
1795 /* Enable RX FIFO drain request, the slave only use this interrupt */
1796 DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable);
1797
1798 if (NULL != handle->rxData)
1799 {
1800 /* RX FIFO overflow request enable */
1801 DSPI_EnableInterrupts(base, (uint32_t)kDSPI_RxFifoOverflowInterruptEnable);
1802 }
1803 if (NULL != handle->txData)
1804 {
1805 /* TX FIFO underflow request enable */
1806 DSPI_EnableInterrupts(base, (uint32_t)kDSPI_TxFifoUnderflowInterruptEnable);
1807 }
1808
1809 DSPI_StartTransfer(base);
1810
1811 /* Prepare data to transmit */
1812 DSPI_SlaveTransferFillUpTxFifo(base, handle);
1813
1814 return kStatus_Success;
1815 }
1816
1817 /*!
1818 * brief Gets the slave transfer count.
1819 *
1820 * This function gets the slave transfer count.
1821 *
1822 * param base DSPI peripheral base address.
1823 * param handle Pointer to the dspi_master_handle_t structure which stores the transfer state.
1824 * param count The number of bytes transferred by using the non-blocking transaction.
1825 * return status of status_t.
1826 */
DSPI_SlaveTransferGetCount(SPI_Type * base,dspi_slave_handle_t * handle,size_t * count)1827 status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count)
1828 {
1829 assert(NULL != handle);
1830
1831 if (NULL == count)
1832 {
1833 return kStatus_InvalidArgument;
1834 }
1835
1836 /* Catch when there is not an active transfer. */
1837 if (handle->state != (uint8_t)kDSPI_Busy)
1838 {
1839 *count = 0;
1840 return kStatus_NoTransferInProgress;
1841 }
1842
1843 *count = handle->totalByteCount - handle->remainingReceiveByteCount;
1844 return kStatus_Success;
1845 }
1846
DSPI_SlaveTransferFillUpTxFifo(SPI_Type * base,dspi_slave_handle_t * handle)1847 static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle)
1848 {
1849 assert(NULL != handle);
1850
1851 uint16_t transmitData = 0;
1852 uint8_t dummyPattern = DSPI_GetDummyDataInstance(base);
1853
1854 /* Service the transmitter, if transmit buffer provided, transmit the data,
1855 * else transmit dummy pattern
1856 */
1857 while ((uint32_t)kDSPI_TxFifoFillRequestFlag == (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoFillRequestFlag))
1858 {
1859 /* Transmit data */
1860 if (handle->remainingSendByteCount > 0U)
1861 {
1862 /* Have data to transmit, update the transmit data and push to FIFO */
1863 if (handle->bitsPerFrame <= 8U)
1864 {
1865 /* bits/frame is 1 byte */
1866 if (NULL != handle->txData)
1867 {
1868 /* Update transmit data and transmit pointer */
1869 transmitData = *handle->txData;
1870 handle->txData++;
1871 }
1872 else
1873 {
1874 transmitData = dummyPattern;
1875 }
1876
1877 /* Decrease remaining dataSize */
1878 --handle->remainingSendByteCount;
1879 }
1880 /* bits/frame is 2 bytes */
1881 else
1882 {
1883 /* With multibytes per frame transmission, the transmit frame contains data from
1884 * transmit buffer until sent dataSize matches user request. Other bytes will set to
1885 * dummy pattern value.
1886 */
1887 if (NULL != handle->txData)
1888 {
1889 /* Update first byte of transmit data and transmit pointer */
1890 transmitData = *handle->txData;
1891 handle->txData++;
1892
1893 if (handle->remainingSendByteCount == 1U)
1894 {
1895 /* Decrease remaining dataSize */
1896 --handle->remainingSendByteCount;
1897 /* Update second byte of transmit data to second byte of dummy pattern */
1898 transmitData = transmitData | (uint16_t)(((uint16_t)dummyPattern) << 8U);
1899 }
1900 else
1901 {
1902 /* Update second byte of transmit data and transmit pointer */
1903 transmitData = transmitData | (uint16_t)((uint16_t)(*handle->txData) << 8U);
1904 handle->txData++;
1905 handle->remainingSendByteCount -= 2U;
1906 }
1907 }
1908 else
1909 {
1910 if (handle->remainingSendByteCount == 1U)
1911 {
1912 --handle->remainingSendByteCount;
1913 }
1914 else
1915 {
1916 handle->remainingSendByteCount -= 2U;
1917 }
1918 transmitData = (uint16_t)((uint16_t)(dummyPattern) << 8U) | dummyPattern;
1919 }
1920 }
1921 }
1922 else
1923 {
1924 break;
1925 }
1926
1927 /* Write the data to the DSPI data register */
1928 base->PUSHR_SLAVE = transmitData;
1929
1930 /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */
1931 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
1932 }
1933 }
1934
DSPI_SlaveTransferComplete(SPI_Type * base,dspi_slave_handle_t * handle)1935 static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle)
1936 {
1937 assert(NULL != handle);
1938
1939 /* Disable interrupt requests */
1940 DSPI_DisableInterrupts(
1941 base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable |
1942 (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable));
1943
1944 /* The transfer is complete. */
1945 handle->txData = NULL;
1946 handle->rxData = NULL;
1947 handle->remainingReceiveByteCount = 0;
1948 handle->remainingSendByteCount = 0;
1949
1950 status_t status;
1951 if (handle->state == (uint8_t)kDSPI_Error)
1952 {
1953 status = kStatus_DSPI_Error;
1954 }
1955 else
1956 {
1957 status = kStatus_Success;
1958 }
1959
1960 handle->state = (uint8_t)kDSPI_Idle;
1961
1962 if (NULL != handle->callback)
1963 {
1964 handle->callback(base, handle, status, handle->userData);
1965 }
1966 }
1967
1968 /*!
1969 * brief DSPI slave aborts a transfer using an interrupt.
1970 *
1971 * This function aborts a transfer using an interrupt.
1972 *
1973 * param base DSPI peripheral base address.
1974 * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state.
1975 */
DSPI_SlaveTransferAbort(SPI_Type * base,dspi_slave_handle_t * handle)1976 void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle)
1977 {
1978 assert(NULL != handle);
1979
1980 DSPI_StopTransfer(base);
1981
1982 /* Disable interrupt requests */
1983 DSPI_DisableInterrupts(
1984 base, ((uint32_t)kDSPI_TxFifoUnderflowInterruptEnable | (uint32_t)kDSPI_TxFifoFillRequestInterruptEnable |
1985 (uint32_t)kDSPI_RxFifoOverflowInterruptEnable | (uint32_t)kDSPI_RxFifoDrainRequestInterruptEnable));
1986
1987 handle->state = (uint8_t)kDSPI_Idle;
1988 handle->remainingSendByteCount = 0;
1989 handle->remainingReceiveByteCount = 0;
1990 }
1991
1992 /*!
1993 * brief DSPI Master IRQ handler function.
1994 *
1995 * This function processes the DSPI transmit and receive IRQ.
1996 *
1997 * param base DSPI peripheral base address.
1998 * param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state.
1999 */
DSPI_SlaveTransferHandleIRQ(SPI_Type * base,dspi_slave_handle_t * handle)2000 void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle)
2001 {
2002 assert(NULL != handle);
2003
2004 uint8_t dummyPattern = DSPI_GetDummyDataInstance(base);
2005 uint32_t dataReceived;
2006 uint32_t dataSend = 0;
2007 uint32_t tmpRemainingReceiveByteCount = 0;
2008
2009 /* Because SPI protocol is synchronous, the number of bytes that that slave received from the
2010 * master is the actual number of bytes that the slave transmitted to the master. So we only
2011 * monitor the received dataSize to know when the transfer is complete.
2012 */
2013 if (handle->remainingReceiveByteCount > 0U)
2014 {
2015 while ((uint32_t)kDSPI_RxFifoDrainRequestFlag ==
2016 (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoDrainRequestFlag))
2017 {
2018 /* Have received data in the buffer. */
2019 dataReceived = base->POPR;
2020 /*Clear the rx fifo drain request, needed for non-DMA applications as this flag
2021 * will remain set even if the rx fifo is empty. By manually clearing this flag, it
2022 * either remain clear if no more data is in the fifo, or it will set if there is
2023 * more data in the fifo.
2024 */
2025 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoDrainRequestFlag);
2026
2027 /* If bits/frame is one byte */
2028 if (handle->bitsPerFrame <= 8U)
2029 {
2030 if (NULL != handle->rxData)
2031 {
2032 /* Receive buffer is not null, store data into it */
2033 *handle->rxData = (uint8_t)dataReceived;
2034 ++handle->rxData;
2035 }
2036 /* Descrease remaining receive byte count */
2037 --handle->remainingReceiveByteCount;
2038
2039 if (handle->remainingSendByteCount > 0U)
2040 {
2041 if (NULL != handle->txData)
2042 {
2043 dataSend = *handle->txData;
2044 ++handle->txData;
2045 }
2046 else
2047 {
2048 dataSend = dummyPattern;
2049 }
2050
2051 --handle->remainingSendByteCount;
2052 /* Write the data to the DSPI data register */
2053 base->PUSHR_SLAVE = dataSend;
2054 }
2055 }
2056 else /* If bits/frame is 2 bytes */
2057 {
2058 /* With multibytes frame receiving, we only receive till the received dataSize
2059 * matches user request. Other bytes will be ignored.
2060 */
2061 if (NULL != handle->rxData)
2062 {
2063 /* Receive buffer is not null, store first byte into it */
2064 *handle->rxData = (uint8_t)dataReceived;
2065 ++handle->rxData;
2066
2067 if (handle->remainingReceiveByteCount == 1U)
2068 {
2069 /* Decrease remaining receive byte count */
2070 --handle->remainingReceiveByteCount;
2071 }
2072 else
2073 {
2074 /* Receive buffer is not null, store second byte into it */
2075 *handle->rxData = (uint8_t)(dataReceived >> 8U);
2076 ++handle->rxData;
2077 handle->remainingReceiveByteCount -= 2U;
2078 }
2079 }
2080 /* If no handle->rxData*/
2081 else
2082 {
2083 if (handle->remainingReceiveByteCount == 1U)
2084 {
2085 /* Decrease remaining receive byte count */
2086 --handle->remainingReceiveByteCount;
2087 }
2088 else
2089 {
2090 handle->remainingReceiveByteCount -= 2U;
2091 }
2092 }
2093
2094 if (handle->remainingSendByteCount > 0U)
2095 {
2096 if (NULL != handle->txData)
2097 {
2098 dataSend = *handle->txData;
2099 ++handle->txData;
2100
2101 if (handle->remainingSendByteCount == 1U)
2102 {
2103 --handle->remainingSendByteCount;
2104 dataSend |= (uint16_t)((uint16_t)(dummyPattern) << 8U);
2105 }
2106 else
2107 {
2108 dataSend |= (uint32_t)(*handle->txData) << 8U;
2109 ++handle->txData;
2110 handle->remainingSendByteCount -= 2U;
2111 }
2112 }
2113 /* If no handle->txData*/
2114 else
2115 {
2116 if (handle->remainingSendByteCount == 1U)
2117 {
2118 --handle->remainingSendByteCount;
2119 }
2120 else
2121 {
2122 handle->remainingSendByteCount -= 2U;
2123 }
2124 dataSend = ((uint32_t)(dummyPattern) << 8U) | dummyPattern;
2125 }
2126 /* Write the data to the DSPI data register */
2127 base->PUSHR_SLAVE = dataSend;
2128 }
2129 }
2130 /* Try to clear TFFF by writing a one to it; it will not clear if TX FIFO not full */
2131 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoFillRequestFlag);
2132
2133 if (handle->remainingReceiveByteCount == 0U)
2134 {
2135 break;
2136 }
2137 }
2138 }
2139 /* Check if remaining receive byte count matches user request */
2140 tmpRemainingReceiveByteCount = handle->remainingReceiveByteCount;
2141 if ((handle->state == (uint8_t)(kDSPI_Error)) || (tmpRemainingReceiveByteCount == 0U))
2142 {
2143 /* Other cases, stop the transfer. */
2144 DSPI_SlaveTransferComplete(base, handle);
2145 return;
2146 }
2147
2148 /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */
2149 if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_TxFifoUnderflowFlag))
2150 {
2151 if (0U != (base->RSER & SPI_RSER_TFUF_RE_MASK))
2152 {
2153 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_TxFifoUnderflowFlag);
2154 /* Change state to error and clear flag */
2155 if (NULL != handle->txData)
2156 {
2157 handle->state = (uint8_t)kDSPI_Error;
2158 }
2159 handle->errorCount++;
2160 }
2161 }
2162
2163 /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */
2164 if (0U != (DSPI_GetStatusFlags(base) & (uint32_t)kDSPI_RxFifoOverflowFlag))
2165 {
2166 if (0U != (base->RSER & SPI_RSER_RFOF_RE_MASK))
2167 {
2168 DSPI_ClearStatusFlags(base, (uint32_t)kDSPI_RxFifoOverflowFlag);
2169 /* Change state to error and clear flag */
2170 if (NULL != handle->txData)
2171 {
2172 handle->state = (uint8_t)kDSPI_Error;
2173 }
2174 handle->errorCount++;
2175 }
2176 }
2177 }
2178
DSPI_CommonIRQHandler(SPI_Type * base,void * param)2179 static void DSPI_CommonIRQHandler(SPI_Type *base, void *param)
2180 {
2181 if (DSPI_IsMaster(base))
2182 {
2183 s_dspiMasterIsr(base, (dspi_master_handle_t *)param);
2184 }
2185 else
2186 {
2187 s_dspiSlaveIsr(base, (dspi_slave_handle_t *)param);
2188 }
2189 SDK_ISR_EXIT_BARRIER;
2190 }
2191
2192 #if defined(SPI0)
2193 void SPI0_DriverIRQHandler(void);
SPI0_DriverIRQHandler(void)2194 void SPI0_DriverIRQHandler(void)
2195 {
2196 assert(NULL != g_dspiHandle[0]);
2197 DSPI_CommonIRQHandler(SPI0, g_dspiHandle[0]);
2198 }
2199 #endif
2200
2201 #if defined(SPI1)
2202 void SPI1_DriverIRQHandler(void);
SPI1_DriverIRQHandler(void)2203 void SPI1_DriverIRQHandler(void)
2204 {
2205 assert(NULL != g_dspiHandle[1]);
2206 DSPI_CommonIRQHandler(SPI1, g_dspiHandle[1]);
2207 }
2208 #endif
2209
2210 #if defined(SPI2)
2211 void SPI2_DriverIRQHandler(void);
SPI2_DriverIRQHandler(void)2212 void SPI2_DriverIRQHandler(void)
2213 {
2214 assert(NULL != g_dspiHandle[2]);
2215 DSPI_CommonIRQHandler(SPI2, g_dspiHandle[2]);
2216 }
2217 #endif
2218
2219 #if defined(SPI3)
2220 void SPI3_DriverIRQHandler(void);
SPI3_DriverIRQHandler(void)2221 void SPI3_DriverIRQHandler(void)
2222 {
2223 assert(NULL != g_dspiHandle[3]);
2224 DSPI_CommonIRQHandler(SPI3, g_dspiHandle[3]);
2225 }
2226 #endif
2227
2228 #if defined(SPI4)
2229 void SPI4_DriverIRQHandler(void);
SPI4_DriverIRQHandler(void)2230 void SPI4_DriverIRQHandler(void)
2231 {
2232 assert(NULL != g_dspiHandle[4]);
2233 DSPI_CommonIRQHandler(SPI4, g_dspiHandle[4]);
2234 }
2235 #endif
2236
2237 #if defined(SPI5)
2238 void SPI5_DriverIRQHandler(void);
SPI5_DriverIRQHandler(void)2239 void SPI5_DriverIRQHandler(void)
2240 {
2241 assert(NULL != g_dspiHandle[5]);
2242 DSPI_CommonIRQHandler(SPI5, g_dspiHandle[5]);
2243 }
2244 #endif
2245
2246 #if (FSL_FEATURE_SOC_DSPI_COUNT > 6)
2247 #error "Should write the SPIx_DriverIRQHandler function that instance greater than 5 !"
2248 #endif
2249