1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2022 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_lpspi.h"
10 /*
11 * $Coverage Justification Reference$
12 *
13 * $Justification fsl_lpspi_c_ref_1$
14 * The default branch cannot be executed in any circumstances, it is only added to avoid MISRA violation.
15 *
16 * $Justification fsl_lpspi_c_ref_2$
17 * The FIFO was emptied before the check and there was no writing after the FIFO was emptied, so the obtained FIFO count
18 * is 0, and the #kStatus_LPSPI_Timeout cannot be obtained.(will improve)
19 *
20 * $Justification fsl_lpspi_c_ref_3$
21 * The fifosize is determined by the hardware.
22 *
23 * $Justification fsl_lpspi_c_ref_4$
24 * If an interrupt is generated by this error, the corresponding interrupt bit must be set.(will improve)
25 *
26 */
27
28 /*******************************************************************************
29 * Definitions
30 ******************************************************************************/
31
32 /* Component ID definition, used by tools. */
33 #ifndef FSL_COMPONENT_ID
34 #define FSL_COMPONENT_ID "platform.drivers.lpspi"
35 #endif
36
37 /*!
38 * @brief Default watermark values.
39 *
40 * The default watermarks are set to zero.
41 */
42 enum _lpspi_default_watermarks
43 {
44 kLpspiDefaultTxWatermark = 0,
45 kLpspiDefaultRxWatermark = 0,
46 };
47
48 /*
49 * <! Structure definition for variables that passed as parameters in LPSPI_MasterTransferBlocking.
50 * The structure is private.
51 */
52 typedef struct _lpspi_transfer_blocking_param
53 {
54 bool isTxMask;
55 bool isPcsContinuous;
56 uint8_t bytesEachWrite;
57 uint8_t bytesEachRead;
58 uint8_t *txData;
59 uint8_t *rxData;
60 uint32_t rxRemainingByteCount;
61 } lpspi_transfer_blocking_param_t;
62
63 /*! @brief Typedef for master interrupt handler. */
64 typedef void (*lpspi_master_isr_t)(LPSPI_Type *base, lpspi_master_handle_t *handle);
65
66 /*! @brief Typedef for slave interrupt handler. */
67 typedef void (*lpspi_slave_isr_t)(LPSPI_Type *base, lpspi_slave_handle_t *handle);
68
69 /*******************************************************************************
70 * Prototypes
71 ******************************************************************************/
72
73 /*!
74 * @brief Configures the LPSPI peripheral chip select polarity.
75 *
76 * This function takes in the desired peripheral chip select (Pcs) and it's corresponding desired polarity and
77 * configures the Pcs signal to operate with the desired characteristic.
78 *
79 * @param base LPSPI peripheral address.
80 * @param pcs The particular peripheral chip select (parameter value is of type lpspi_which_pcs_t) for which we wish to
81 * apply the active high or active low characteristic.
82 * @param activeLowOrHigh The setting for either "active high, inactive low (0)" or "active low, inactive high(1)" of
83 * type lpspi_pcs_polarity_config_t.
84 */
85 static void LPSPI_SetOnePcsPolarity(LPSPI_Type *base,
86 lpspi_which_pcs_t pcs,
87 lpspi_pcs_polarity_config_t activeLowOrHigh);
88
89 /*!
90 * @brief Combine the write data for 1 byte to 4 bytes.
91 * This is not a public API.
92 */
93 static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint8_t bytesEachWrite, bool isByteSwap);
94
95 /*!
96 * @brief Separate the read data for 1 byte to 4 bytes.
97 * This is not a public API.
98 */
99 static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint8_t bytesEachRead, bool isByteSwap);
100
101 /*!
102 * @brief Wait for tx FIFO to be empty.
103 * This is not a public API.
104 * @param base LPSPI peripheral address.
105 * @return true for the tx FIFO is ready, false is not.
106 */
107 static bool LPSPI_TxFifoReady(LPSPI_Type *base);
108
109 /*!
110 * @brief Master fill up the TX FIFO with data.
111 * This is not a public API.
112 */
113 static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_master_handle_t *handle);
114
115 /*!
116 * @brief Master finish up a transfer.
117 * It would call back if there is callback function and set the state to idle.
118 * This is not a public API.
119 */
120 static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle);
121
122 /*!
123 * @brief Slave fill up the TX FIFO with data.
124 * This is not a public API.
125 */
126 static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_slave_handle_t *handle);
127
128 /*!
129 * @brief Slave finish up a transfer.
130 * It would call back if there is callback function and set the state to idle.
131 * This is not a public API.
132 */
133 static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle);
134
135 /*!
136 * @brief LPSPI common interrupt handler.
137 *
138 * @param handle pointer to s_lpspiHandle which stores the transfer state.
139 */
140 static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param);
141
142 /*!
143 * @brief introduce function static bool LPSPI_MasterTransferWriteAllTxData.
144 * This function was deal with write all Txdata.
145 *
146 * @param base LPSPI peripheral address.
147 * @param stateParams Pass the address of the parent function variable.
148 *
149 * @return default is true when No abnormality.
150 * @return false when time out.
151 */
152 static bool LPSPI_MasterTransferWriteAllTxData(LPSPI_Type *base,
153 lpspi_transfer_t *transfer,
154 lpspi_transfer_blocking_param_t *stateParams);
155
156 /*!
157 * @brief introduce function LPSPI_MasterTransferClearTCR.
158 * This function was deal with clear TCR.
159 *
160 * @param base LPSPI peripheral address.
161 * @param stateParams Pass the address of the parent function variable.
162 *
163 * @return default is true when No abnormality.
164 * @return false when time out.
165 */
166 static bool LPSPI_MasterTransferClearTCR(LPSPI_Type *base, lpspi_transfer_blocking_param_t *stateParams);
167
168 /*!
169 * @brief introduce function LPSPI_MasterTransferReadDataInFifo.
170 * This function was deal with read data in fifo.
171 *
172 * @param base LPSPI peripheral address.
173 * @param stateParams Pass the address of the parent function variable.
174 *
175 * @return default is true when No abnormality.
176 * @return false when time out.
177 */
178 static bool LPSPI_MasterTransferReadDataInFifo(LPSPI_Type *base,
179 lpspi_transfer_t *transfer,
180 lpspi_transfer_blocking_param_t *stateParams);
181
182 /*!
183 * @brief introduce function LPSPI_MasterTransferReadDataInFifoNoBuf.
184 * This function was deal with no buf in fifo.
185 *
186 * @param base LPSPI peripheral address.
187 * @param stateParams Pass the address of the parent function variable.
188 *
189 * @return default is true when No abnormality.
190 * @return false when time out.
191 */
192 static bool LPSPI_MasterTransferReadDataInFifoNoBuf(LPSPI_Type *base, lpspi_transfer_blocking_param_t *stateParams);
193
194 /*******************************************************************************
195 * Variables
196 ******************************************************************************/
197
198 /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/
199 static const uint8_t s_baudratePrescaler[] = {1, 2, 4, 8, 16, 32, 64, 128};
200
201 /*! @brief Pointers to lpspi bases for each instance. */
202 static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS;
203
204 /*! @brief Pointers to lpspi IRQ number for each instance. */
205 static const IRQn_Type s_lpspiIRQ[] = LPSPI_IRQS;
206
207 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
208 /*! @brief Pointers to lpspi clocks for each instance. */
209 static const clock_ip_name_t s_lpspiClocks[] = LPSPI_CLOCKS;
210
211 #if defined(LPSPI_PERIPH_CLOCKS)
212 static const clock_ip_name_t s_LpspiPeriphClocks[] = LPSPI_PERIPH_CLOCKS;
213 #endif
214
215 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
216
217 /*! @brief Pointers to lpspi handles for each instance. */
218 static void *s_lpspiHandle[ARRAY_SIZE(s_lpspiBases)];
219
220 /*! @brief Pointer to master IRQ handler for each instance. */
221 static lpspi_master_isr_t s_lpspiMasterIsr;
222 /*! @brief Pointer to slave IRQ handler for each instance. */
223 static lpspi_slave_isr_t s_lpspiSlaveIsr;
224 /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
225 volatile uint8_t g_lpspiDummyData[ARRAY_SIZE(s_lpspiBases)] = {0};
226
227 /**********************************************************************************************************************
228 * Code
229 *********************************************************************************************************************/
230
231 /*!
232 * brief Get the LPSPI instance from peripheral base address.
233 *
234 * param base LPSPI peripheral base address.
235 * return LPSPI instance.
236 */
LPSPI_GetInstance(LPSPI_Type * base)237 uint32_t LPSPI_GetInstance(LPSPI_Type *base)
238 {
239 uint8_t instance = 0;
240
241 /* Find the instance index from base address mappings. */
242 for (instance = 0; instance < ARRAY_SIZE(s_lpspiBases); instance++)
243 {
244 if (s_lpspiBases[instance] == base)
245 {
246 break;
247 }
248 }
249
250 assert(instance < ARRAY_SIZE(s_lpspiBases));
251
252 return instance;
253 }
254
255 /*!
256 * brief Set up the dummy data.
257 *
258 * param base LPSPI peripheral address.
259 * param dummyData Data to be transferred when tx buffer is NULL.
260 * Note:
261 * This API has no effect when LPSPI in slave interrupt mode, because driver
262 * will set the TXMSK bit to 1 if txData is NULL, no data is loaded from transmit
263 * FIFO and output pin is tristated.
264 */
LPSPI_SetDummyData(LPSPI_Type * base,uint8_t dummyData)265 void LPSPI_SetDummyData(LPSPI_Type *base, uint8_t dummyData)
266 {
267 uint32_t instance = LPSPI_GetInstance(base);
268 g_lpspiDummyData[instance] = dummyData;
269 }
270
271 /*!
272 * brief Initializes the LPSPI master.
273 *
274 * param base LPSPI peripheral address.
275 * param masterConfig Pointer to structure lpspi_master_config_t.
276 * param srcClock_Hz Module source input clock in Hertz
277 */
LPSPI_MasterInit(LPSPI_Type * base,const lpspi_master_config_t * masterConfig,uint32_t srcClock_Hz)278 void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz)
279 {
280 assert(masterConfig != NULL);
281
282 uint32_t tcrPrescaleValue = 0;
283
284 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
285
286 uint32_t instance = LPSPI_GetInstance(base);
287 /* Enable LPSPI clock */
288 (void)CLOCK_EnableClock(s_lpspiClocks[instance]);
289
290 #if defined(LPSPI_PERIPH_CLOCKS)
291 (void)CLOCK_EnableClock(s_LpspiPeriphClocks[instance]);
292 #endif
293
294 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
295
296 /* Set LPSPI to master */
297 LPSPI_SetMasterSlaveMode(base, kLPSPI_Master);
298
299 /* Set specific PCS to active high or low */
300 LPSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow);
301
302 /* Set Configuration Register 1 related setting.*/
303 base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK | LPSPI_CFGR1_NOSTALL_MASK |
304 LPSPI_CFGR1_SAMPLE_MASK)) |
305 LPSPI_CFGR1_OUTCFG(masterConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(masterConfig->pinCfg) |
306 LPSPI_CFGR1_NOSTALL(0) | LPSPI_CFGR1_SAMPLE((uint32_t)masterConfig->enableInputDelay);
307 if ((masterConfig->pinCfg == kLPSPI_SdiInSdiOut) || (masterConfig->pinCfg == kLPSPI_SdoInSdoOut))
308 {
309 base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK;
310 }
311 /* Set baudrate and delay times*/
312 (void)LPSPI_MasterSetBaudRate(base, masterConfig->baudRate, srcClock_Hz, &tcrPrescaleValue);
313
314 /* Set default watermarks */
315 LPSPI_SetFifoWatermarks(base, (uint32_t)kLpspiDefaultTxWatermark, (uint32_t)kLpspiDefaultRxWatermark);
316
317 /* Set Transmit Command Register*/
318 base->TCR = LPSPI_TCR_CPOL(masterConfig->cpol) | LPSPI_TCR_CPHA(masterConfig->cpha) |
319 LPSPI_TCR_LSBF(masterConfig->direction) | LPSPI_TCR_FRAMESZ(masterConfig->bitsPerFrame - 1U) |
320 LPSPI_TCR_PRESCALE(tcrPrescaleValue) | LPSPI_TCR_PCS(masterConfig->whichPcs);
321
322 LPSPI_Enable(base, true);
323
324 (void)LPSPI_MasterSetDelayTimes(base, masterConfig->pcsToSckDelayInNanoSec, kLPSPI_PcsToSck, srcClock_Hz);
325 (void)LPSPI_MasterSetDelayTimes(base, masterConfig->lastSckToPcsDelayInNanoSec, kLPSPI_LastSckToPcs, srcClock_Hz);
326 (void)LPSPI_MasterSetDelayTimes(base, masterConfig->betweenTransferDelayInNanoSec, kLPSPI_BetweenTransfer,
327 srcClock_Hz);
328
329 LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA);
330 }
331
332 /*!
333 * brief Sets the lpspi_master_config_t structure to default values.
334 *
335 * This API initializes the configuration structure for LPSPI_MasterInit().
336 * The initialized structure can remain unchanged in LPSPI_MasterInit(), or can be modified
337 * before calling the LPSPI_MasterInit().
338 * Example:
339 * code
340 * lpspi_master_config_t masterConfig;
341 * LPSPI_MasterGetDefaultConfig(&masterConfig);
342 * endcode
343 * param masterConfig pointer to lpspi_master_config_t structure
344 */
LPSPI_MasterGetDefaultConfig(lpspi_master_config_t * masterConfig)345 void LPSPI_MasterGetDefaultConfig(lpspi_master_config_t *masterConfig)
346 {
347 assert(masterConfig != NULL);
348
349 /* Initializes the configure structure to zero. */
350 (void)memset(masterConfig, 0, sizeof(*masterConfig));
351
352 masterConfig->baudRate = 500000;
353 masterConfig->bitsPerFrame = 8;
354 masterConfig->cpol = kLPSPI_ClockPolarityActiveHigh;
355 masterConfig->cpha = kLPSPI_ClockPhaseFirstEdge;
356 masterConfig->direction = kLPSPI_MsbFirst;
357
358 masterConfig->pcsToSckDelayInNanoSec = (1000000000U / masterConfig->baudRate) / 2U;
359 masterConfig->lastSckToPcsDelayInNanoSec = (1000000000U / masterConfig->baudRate) / 2U;
360 masterConfig->betweenTransferDelayInNanoSec = (1000000000U / masterConfig->baudRate) / 2U;
361
362 masterConfig->whichPcs = kLPSPI_Pcs0;
363 masterConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
364
365 masterConfig->pinCfg = kLPSPI_SdiInSdoOut;
366 masterConfig->dataOutConfig = kLpspiDataOutRetained;
367
368 masterConfig->enableInputDelay = false;
369 }
370
371 /*!
372 * brief LPSPI slave configuration.
373 *
374 * param base LPSPI peripheral address.
375 * param slaveConfig Pointer to a structure lpspi_slave_config_t.
376 */
LPSPI_SlaveInit(LPSPI_Type * base,const lpspi_slave_config_t * slaveConfig)377 void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig)
378 {
379 assert(slaveConfig != NULL);
380
381 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
382
383 uint32_t instance = LPSPI_GetInstance(base);
384 /* Enable LPSPI clock */
385 (void)CLOCK_EnableClock(s_lpspiClocks[instance]);
386
387 #if defined(LPSPI_PERIPH_CLOCKS)
388 (void)CLOCK_EnableClock(s_LpspiPeriphClocks[instance]);
389 #endif
390
391 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
392
393 LPSPI_SetMasterSlaveMode(base, kLPSPI_Slave);
394
395 LPSPI_SetOnePcsPolarity(base, slaveConfig->whichPcs, slaveConfig->pcsActiveHighOrLow);
396
397 base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK)) |
398 LPSPI_CFGR1_OUTCFG(slaveConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(slaveConfig->pinCfg);
399
400 if ((slaveConfig->pinCfg == kLPSPI_SdiInSdiOut) || (slaveConfig->pinCfg == kLPSPI_SdoInSdoOut))
401 {
402 base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK;
403 }
404
405 LPSPI_SetFifoWatermarks(base, (uint32_t)kLpspiDefaultTxWatermark, (uint32_t)kLpspiDefaultRxWatermark);
406
407 base->TCR = LPSPI_TCR_CPOL(slaveConfig->cpol) | LPSPI_TCR_CPHA(slaveConfig->cpha) |
408 LPSPI_TCR_LSBF(slaveConfig->direction) | LPSPI_TCR_FRAMESZ(slaveConfig->bitsPerFrame - 1U);
409
410 /* This operation will set the dummy data for edma transfer, no effect in interrupt way. */
411 LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA);
412
413 LPSPI_Enable(base, true);
414 }
415
416 /*!
417 * brief Sets the lpspi_slave_config_t structure to default values.
418 *
419 * This API initializes the configuration structure for LPSPI_SlaveInit().
420 * The initialized structure can remain unchanged in LPSPI_SlaveInit() or can be modified
421 * before calling the LPSPI_SlaveInit().
422 * Example:
423 * code
424 * lpspi_slave_config_t slaveConfig;
425 * LPSPI_SlaveGetDefaultConfig(&slaveConfig);
426 * endcode
427 * param slaveConfig pointer to lpspi_slave_config_t structure.
428 */
LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t * slaveConfig)429 void LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t *slaveConfig)
430 {
431 assert(slaveConfig != NULL);
432
433 /* Initializes the configure structure to zero. */
434 (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
435
436 slaveConfig->bitsPerFrame = 8; /*!< Bits per frame, minimum 8, maximum 4096.*/
437 slaveConfig->cpol = kLPSPI_ClockPolarityActiveHigh; /*!< Clock polarity. */
438 slaveConfig->cpha = kLPSPI_ClockPhaseFirstEdge; /*!< Clock phase. */
439 slaveConfig->direction = kLPSPI_MsbFirst; /*!< MSB or LSB data shift direction. */
440
441 slaveConfig->whichPcs = kLPSPI_Pcs0; /*!< Desired Peripheral Chip Select (pcs) */
442 slaveConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow; /*!< Desired PCS active high or low */
443
444 slaveConfig->pinCfg = kLPSPI_SdiInSdoOut;
445 slaveConfig->dataOutConfig = kLpspiDataOutRetained;
446 }
447
448 /*!
449 * brief Restores the LPSPI peripheral to reset state. Note that this function
450 * sets all registers to reset state. As a result, the LPSPI module can't work after calling
451 * this API.
452 * param base LPSPI peripheral address.
453 */
LPSPI_Reset(LPSPI_Type * base)454 void LPSPI_Reset(LPSPI_Type *base)
455 {
456 /* Reset all internal logic and registers, except the Control Register. Remains set until cleared by software.*/
457 base->CR |= LPSPI_CR_RST_MASK;
458
459 /* Software reset doesn't reset the CR, so manual reset the FIFOs */
460 base->CR |= LPSPI_CR_RRF_MASK | LPSPI_CR_RTF_MASK;
461
462 /* Master logic is not reset and module is disabled.*/
463 base->CR = 0x00U;
464 }
465
466 /*!
467 * brief De-initializes the LPSPI peripheral. Call this API to disable the LPSPI clock.
468 * param base LPSPI peripheral address.
469 */
LPSPI_Deinit(LPSPI_Type * base)470 void LPSPI_Deinit(LPSPI_Type *base)
471 {
472 /* Reset to default value */
473 LPSPI_Reset(base);
474
475 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
476
477 uint32_t instance = LPSPI_GetInstance(base);
478 /* Enable LPSPI clock */
479 (void)CLOCK_DisableClock(s_lpspiClocks[instance]);
480
481 #if defined(LPSPI_PERIPH_CLOCKS)
482 (void)CLOCK_DisableClock(s_LpspiPeriphClocks[instance]);
483 #endif
484
485 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
486 }
487
LPSPI_SetOnePcsPolarity(LPSPI_Type * base,lpspi_which_pcs_t pcs,lpspi_pcs_polarity_config_t activeLowOrHigh)488 static void LPSPI_SetOnePcsPolarity(LPSPI_Type *base,
489 lpspi_which_pcs_t pcs,
490 lpspi_pcs_polarity_config_t activeLowOrHigh)
491 {
492 uint32_t cfgr1Value = 0;
493 /* Clear the PCS polarity bit */
494 cfgr1Value = base->CFGR1 & ~(1UL << (LPSPI_CFGR1_PCSPOL_SHIFT + (uint32_t)pcs));
495
496 /* Configure the PCS polarity bit according to the activeLowOrHigh setting */
497 base->CFGR1 = cfgr1Value | ((uint32_t)activeLowOrHigh << (LPSPI_CFGR1_PCSPOL_SHIFT + (uint32_t)pcs));
498 }
499
500 /*!
501 * brief Sets the LPSPI baud rate in bits per second.
502 *
503 * This function takes in the desired bitsPerSec (baud rate) and calculates the nearest
504 * possible baud rate without exceeding the desired baud rate and returns the
505 * calculated baud rate in bits-per-second. It requires the caller to provide
506 * the frequency of the module source clock (in Hertz). Note that the baud rate
507 * does not go into effect until the Transmit Control Register (TCR) is programmed
508 * with the prescale value. Hence, this function returns the prescale tcrPrescaleValue
509 * parameter for later programming in the TCR. The higher level
510 * peripheral driver should alert the user of an out of range baud rate input.
511 *
512 * Note that the LPSPI module must first be disabled before configuring this.
513 * Note that the LPSPI module must be configured for master mode before configuring this.
514 *
515 * param base LPSPI peripheral address.
516 * param baudRate_Bps The desired baud rate in bits per second.
517 * param srcClock_Hz Module source input clock in Hertz.
518 * param tcrPrescaleValue The TCR prescale value needed to program the TCR.
519 * return The actual calculated baud rate. This function may also return a "0" if the
520 * LPSPI is not configured for master mode or if the LPSPI module is not disabled.
521 */
522
LPSPI_MasterSetBaudRate(LPSPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz,uint32_t * tcrPrescaleValue)523 uint32_t LPSPI_MasterSetBaudRate(LPSPI_Type *base,
524 uint32_t baudRate_Bps,
525 uint32_t srcClock_Hz,
526 uint32_t *tcrPrescaleValue)
527 {
528 assert(tcrPrescaleValue != NULL);
529
530 /* For master mode configuration only, if slave mode detected, return 0.
531 * Also, the LPSPI module needs to be disabled first, if enabled, return 0
532 */
533 if ((!LPSPI_IsMaster(base)) || ((base->CR & LPSPI_CR_MEN_MASK) != 0U))
534 {
535 return 0U;
536 }
537
538 uint32_t prescaler, bestPrescaler;
539 uint32_t scaler, bestScaler;
540 uint32_t realBaudrate, bestBaudrate;
541 uint32_t diff, min_diff;
542 uint32_t desiredBaudrate = baudRate_Bps;
543
544 /* find combination of prescaler and scaler resulting in baudrate closest to the
545 * requested value
546 */
547 min_diff = 0xFFFFFFFFU;
548
549 /* Set to maximum divisor value bit settings so that if baud rate passed in is less
550 * than the minimum possible baud rate, then the SPI will be configured to the lowest
551 * possible baud rate
552 */
553 bestPrescaler = 7;
554 bestScaler = 255;
555
556 bestBaudrate = 0; /* required to avoid compilation warning */
557
558 /* In all for loops, if min_diff = 0, the exit for loop*/
559 for (prescaler = 0U; prescaler < 8U; prescaler++)
560 {
561 if (min_diff == 0U)
562 {
563 break;
564 }
565 for (scaler = 0U; scaler < 256U; scaler++)
566 {
567 if (min_diff == 0U)
568 {
569 break;
570 }
571 realBaudrate = (srcClock_Hz / (s_baudratePrescaler[prescaler] * (scaler + 2U)));
572
573 /* calculate the baud rate difference based on the conditional statement
574 * that states that the calculated baud rate must not exceed the desired baud rate
575 */
576 if (desiredBaudrate >= realBaudrate)
577 {
578 diff = desiredBaudrate - realBaudrate;
579 if (min_diff > diff)
580 {
581 /* a better match found */
582 min_diff = diff;
583 bestPrescaler = prescaler;
584 bestScaler = scaler;
585 bestBaudrate = realBaudrate;
586 }
587 }
588 }
589 }
590
591 /* Write the best baud rate scalar to the CCR.
592 * Note, no need to check for error since we've already checked to make sure the module is
593 * disabled and in master mode. Also, there is a limit on the maximum divider so we will not
594 * exceed this.
595 */
596 #if defined(FSL_FEATURE_LPSPI_HAS_CCR1) && FSL_FEATURE_LPSPI_HAS_CCR1
597 /* When CCR1 is present, the CCR[DBT] and CCR[SCKDIV] is write only, all read will return 0
598 The real DBT and SCKDIV can be obtained in CCR1, CCR[DBT]=CCR1[SCKSCK] and CCR[SCKDIV]=CCR1[SCKHLD]+CCR1[SCKSET]
599 So when changing either CCR[DBT] or CCR[SCKDIV] make sure the other value is not overwritten by 0 */
600 base->CCR = base->CCR | LPSPI_CCR_DBT((base->CCR1 & LPSPI_CCR1_SCKSCK_MASK) >> LPSPI_CCR1_SCKSCK_SHIFT) |
601 LPSPI_CCR_SCKDIV(bestScaler);
602 #else
603 base->CCR = (base->CCR & ~LPSPI_CCR_SCKDIV_MASK) | LPSPI_CCR_SCKDIV(bestScaler);
604 #endif /* FSL_FEATURE_LPSPI_HAS_CCR1 */
605
606 /* return the best prescaler value for user to use later */
607 *tcrPrescaleValue = bestPrescaler;
608
609 /* return the actual calculated baud rate */
610 return bestBaudrate;
611 }
612
613 /*!
614 * brief Manually configures a specific LPSPI delay parameter (module must be disabled to
615 * change the delay values).
616 *
617 * This function configures the following:
618 * SCK to PCS delay, or
619 * PCS to SCK delay, or
620 * The configurations must occur between the transfer delay.
621 *
622 * The delay names are available in type lpspi_delay_type_t.
623 *
624 * The user passes the desired delay along with the delay value.
625 * This allows the user to directly set the delay values if they have
626 * pre-calculated them or if they simply wish to manually increment the value.
627 *
628 * Note that the LPSPI module must first be disabled before configuring this.
629 * Note that the LPSPI module must be configured for master mode before configuring this.
630 *
631 * param base LPSPI peripheral address.
632 * param scaler The 8-bit delay value 0x00 to 0xFF (255).
633 * param whichDelay The desired delay to configure, must be of type lpspi_delay_type_t.
634 */
LPSPI_MasterSetDelayScaler(LPSPI_Type * base,uint32_t scaler,lpspi_delay_type_t whichDelay)635 void LPSPI_MasterSetDelayScaler(LPSPI_Type *base, uint32_t scaler, lpspi_delay_type_t whichDelay)
636 {
637 /*These settings are only relevant in master mode */
638 #if defined(FSL_FEATURE_LPSPI_HAS_CCR1) && FSL_FEATURE_LPSPI_HAS_CCR1
639 /* When CCR1 is present, the CCR[DBT] and CCR[SCKDIV] is write only, all read will return 0
640 The real DBT and SCKDIV can be obtained in CCR1, CCR[DBT]=CCR1[SCKSCK] and CCR[SCKDIV]=CCR1[SCKHLD]+CCR1[SCKSET]
641 So when changing either CCR[DBT] or CCR[SCKDIV] make sure the other value is not overwritten by 0 */
642 uint32_t dbt = (base->CCR1 & LPSPI_CCR1_SCKSCK_MASK) >> LPSPI_CCR1_SCKSCK_SHIFT;
643 uint32_t sckdiv = (base->CCR1 & LPSPI_CCR1_SCKHLD_MASK) >> LPSPI_CCR1_SCKHLD_SHIFT;
644 sckdiv += (base->CCR1 & LPSPI_CCR1_SCKSET_MASK) >> LPSPI_CCR1_SCKSET_SHIFT;
645 switch (whichDelay)
646 {
647 case kLPSPI_PcsToSck:
648 base->CCR = (base->CCR & (~LPSPI_CCR_PCSSCK_MASK)) | LPSPI_CCR_PCSSCK(scaler) | LPSPI_CCR_DBT(dbt) |
649 LPSPI_CCR_SCKDIV(sckdiv);
650
651 break;
652 case kLPSPI_LastSckToPcs:
653 base->CCR = (base->CCR & (~LPSPI_CCR_SCKPCS_MASK)) | LPSPI_CCR_SCKPCS(scaler) | LPSPI_CCR_DBT(dbt) |
654 LPSPI_CCR_SCKDIV(sckdiv);
655
656 break;
657 case kLPSPI_BetweenTransfer:
658 base->CCR = base->CCR | LPSPI_CCR_DBT(scaler) | LPSPI_CCR_SCKDIV(sckdiv);
659 #else
660 switch (whichDelay)
661 {
662 case kLPSPI_PcsToSck:
663 base->CCR = (base->CCR & (~LPSPI_CCR_PCSSCK_MASK)) | LPSPI_CCR_PCSSCK(scaler);
664
665 break;
666 case kLPSPI_LastSckToPcs:
667 base->CCR = (base->CCR & (~LPSPI_CCR_SCKPCS_MASK)) | LPSPI_CCR_SCKPCS(scaler);
668
669 break;
670 case kLPSPI_BetweenTransfer:
671 base->CCR = (base->CCR & (~LPSPI_CCR_DBT_MASK)) | LPSPI_CCR_DBT(scaler);
672 #endif /* FSL_FEATURE_LPSPI_HAS_CCR1 */
673 break;
674 default:
675 assert(false);
676 break;
677 }
678 }
679
680 /*!
681 * brief Calculates the delay based on the desired delay input in nanoseconds (module must be
682 * disabled to change the delay values).
683 *
684 * This function calculates the values for the following:
685 * SCK to PCS delay, or
686 * PCS to SCK delay, or
687 * The configurations must occur between the transfer delay.
688 *
689 * The delay names are available in type lpspi_delay_type_t.
690 *
691 * The user passes the desired delay and the desired delay value in
692 * nano-seconds. The function calculates the value needed for the desired delay parameter
693 * and returns the actual calculated delay because an exact delay match may not be possible. In this
694 * case, the closest match is calculated without going below the desired delay value input.
695 * It is possible to input a very large delay value that exceeds the capability of the part, in
696 * which case the maximum supported delay is returned. It is up to the higher level
697 * peripheral driver to alert the user of an out of range delay input.
698 *
699 * Note that the LPSPI module must be configured for master mode before configuring this. And note that
700 * the delayTime = LPSPI_clockSource / (PRESCALE * Delay_scaler).
701 *
702 * param base LPSPI peripheral address.
703 * param delayTimeInNanoSec The desired delay value in nano-seconds.
704 * param whichDelay The desired delay to configuration, which must be of type lpspi_delay_type_t.
705 * param srcClock_Hz Module source input clock in Hertz.
706 * return actual Calculated delay value in nano-seconds.
707 */
708 uint32_t LPSPI_MasterSetDelayTimes(LPSPI_Type *base,
709 uint32_t delayTimeInNanoSec,
710 lpspi_delay_type_t whichDelay,
711 uint32_t srcClock_Hz)
712 {
713 uint64_t realDelay, bestDelay;
714 uint32_t scaler, bestScaler;
715 uint32_t diff, min_diff;
716 uint64_t initialDelayNanoSec;
717 uint32_t clockDividedPrescaler;
718
719 /* For delay between transfer, an additional scaler value is needed */
720 uint32_t additionalScaler = 0;
721
722 /*As the RM note, the LPSPI baud rate clock is itself divided by the PRESCALE setting, which can vary between
723 * transfers.*/
724 clockDividedPrescaler =
725 srcClock_Hz / s_baudratePrescaler[(base->TCR & LPSPI_TCR_PRESCALE_MASK) >> LPSPI_TCR_PRESCALE_SHIFT];
726
727 /* Find combination of prescaler and scaler resulting in the delay closest to the requested value.*/
728 min_diff = 0xFFFFFFFFU;
729
730 /* Initialize scaler to max value to generate the max delay */
731 bestScaler = 0xFFU;
732
733 /* Calculate the initial (min) delay and maximum possible delay based on the specific delay as
734 * the delay divisors are slightly different based on which delay we are configuring.
735 */
736 if (whichDelay == kLPSPI_BetweenTransfer)
737 {
738 /* First calculate the initial, default delay, note min delay is 2 clock cycles. Due to large size of
739 calculated values (uint64_t), we need to break up the calculation into several steps to ensure
740 accurate calculated results
741 */
742 initialDelayNanoSec = 1000000000U;
743 initialDelayNanoSec *= 2U;
744 initialDelayNanoSec /= clockDividedPrescaler;
745
746 /* Calculate the maximum delay */
747 bestDelay = 1000000000U;
748 bestDelay *= 257U; /* based on DBT+2, or 255 + 2 */
749 bestDelay /= clockDividedPrescaler;
750
751 additionalScaler = 1U;
752 }
753 else
754 {
755 /* First calculate the initial, default delay, min delay is 1 clock cycle. Due to large size of calculated
756 values (uint64_t), we need to break up the calculation into several steps to ensure accurate calculated
757 results.
758 */
759 initialDelayNanoSec = 1000000000U;
760 initialDelayNanoSec /= clockDividedPrescaler;
761
762 /* Calculate the maximum delay */
763 bestDelay = 1000000000U;
764 bestDelay *= 256U; /* based on SCKPCS+1 or PCSSCK+1, or 255 + 1 */
765 bestDelay /= clockDividedPrescaler;
766
767 additionalScaler = 0U;
768 }
769
770 /* If the initial, default delay is already greater than the desired delay, then
771 * set the delay to their initial value (0) and return the delay. In other words,
772 * there is no way to decrease the delay value further.
773 */
774 if (initialDelayNanoSec >= delayTimeInNanoSec)
775 {
776 LPSPI_MasterSetDelayScaler(base, 0, whichDelay);
777 return (uint32_t)initialDelayNanoSec;
778 }
779
780 /* If min_diff = 0, the exit for loop */
781 for (scaler = 0U; scaler < 256U; scaler++)
782 {
783 if (min_diff == 0U)
784 {
785 break;
786 }
787 /* Calculate the real delay value as we cycle through the scaler values.
788 Due to large size of calculated values (uint64_t), we need to break up the
789 calculation into several steps to ensure accurate calculated results
790 */
791 realDelay = 1000000000U;
792 realDelay *= ((uint64_t)scaler + 1UL + (uint64_t)additionalScaler);
793 realDelay /= clockDividedPrescaler;
794
795 /* calculate the delay difference based on the conditional statement
796 * that states that the calculated delay must not be less then the desired delay
797 */
798 if (realDelay >= delayTimeInNanoSec)
799 {
800 diff = (uint32_t)(realDelay - (uint64_t)delayTimeInNanoSec);
801 if (min_diff > diff)
802 {
803 /* a better match found */
804 min_diff = diff;
805 bestScaler = scaler;
806 bestDelay = realDelay;
807 }
808 }
809 }
810
811 /* write the best scaler value for the delay */
812 LPSPI_MasterSetDelayScaler(base, bestScaler, whichDelay);
813
814 /* return the actual calculated delay value (in ns) */
815 return (uint32_t)bestDelay;
816 }
817
818 /*Transactional APIs -- Master*/
819
820 /*!
821 * brief Initializes the LPSPI master handle.
822 *
823 * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a
824 * specified LPSPI instance, call this API once to get the initialized handle.
825
826 * param base LPSPI peripheral address.
827 * param handle LPSPI handle pointer to lpspi_master_handle_t.
828 * param callback DSPI callback.
829 * param userData callback function parameter.
830 */
831 void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base,
832 lpspi_master_handle_t *handle,
833 lpspi_master_transfer_callback_t callback,
834 void *userData)
835 {
836 assert(handle != NULL);
837
838 /* Zero the handle. */
839 (void)memset(handle, 0, sizeof(*handle));
840
841 s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
842
843 /* Set irq handler. */
844 s_lpspiMasterIsr = LPSPI_MasterTransferHandleIRQ;
845
846 handle->callback = callback;
847 handle->userData = userData;
848 }
849
850 /*!
851 * brief Check the argument for transfer .
852 *
853 * param base LPSPI peripheral address.
854 * param transfer the transfer struct to be used.
855 * param isEdma True to check for EDMA transfer, false to check interrupt non-blocking transfer
856 * return Return true for right and false for wrong.
857 */
858 bool LPSPI_CheckTransferArgument(LPSPI_Type *base, lpspi_transfer_t *transfer, bool isEdma)
859 {
860 assert(transfer != NULL);
861 uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1U;
862 uint32_t bytesPerFrame = (bitsPerFrame + 7U) / 8U;
863 uint32_t temp = (base->CFGR1 & LPSPI_CFGR1_PINCFG_MASK);
864 /* If the transfer count is zero, then return immediately.*/
865 if (transfer->dataSize == 0U)
866 {
867 return false;
868 }
869
870 /* If both send buffer and receive buffer is null */
871 if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData)))
872 {
873 return false;
874 }
875
876 /*The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4 .
877 *For bytesPerFrame greater than 4 situation:
878 *the transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4 ,
879 *otherwise , the transfer data size can be integer multiples of bytesPerFrame.
880 */
881 if (bytesPerFrame <= 4U)
882 {
883 if ((transfer->dataSize % bytesPerFrame) != 0U)
884 {
885 return false;
886 }
887 }
888 else
889 {
890 if ((bytesPerFrame % 4U) != 0U)
891 {
892 if (transfer->dataSize != bytesPerFrame)
893 {
894 return false;
895 }
896 }
897 else
898 {
899 if ((transfer->dataSize % bytesPerFrame) != 0U)
900 {
901 return false;
902 }
903 }
904 }
905
906 /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */
907 if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut)))
908 {
909 /* The 3-wire mode can't send and receive data at the same time. */
910 if ((transfer->txData != NULL) && (transfer->rxData != NULL))
911 {
912 return false;
913 }
914 }
915
916 if (isEdma && ((bytesPerFrame % 4U) == 3U))
917 {
918 return false;
919 }
920
921 return true;
922 }
923
924 static bool LPSPI_MasterTransferWriteAllTxData(LPSPI_Type *base,
925 lpspi_transfer_t *transfer,
926 lpspi_transfer_blocking_param_t *stateParams)
927 {
928 uint8_t dummyData = g_lpspiDummyData[LPSPI_GetInstance(base)];
929 uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
930 uint32_t txRemainingByteCount = transfer->dataSize;
931 bool isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
932 uint32_t wordToSend =
933 ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
934 uint32_t rxFifoMaxBytes = MIN(bytesPerFrame, 4U) * LPSPI_GetRxFifoSize(base);
935 uint32_t readData;
936 uint8_t fifo_size = LPSPI_GetRxFifoSize(base);
937 /*Write the TX data until txRemainingByteCount is equal to 0 */
938 while (txRemainingByteCount > 0U)
939 {
940 if (txRemainingByteCount < (stateParams->bytesEachWrite))
941 {
942 (stateParams->bytesEachWrite) = (uint8_t)txRemainingByteCount;
943 }
944
945 /*Wait until TX FIFO is not full*/
946 #if SPI_RETRY_TIMES
947 uint32_t waitTimes = SPI_RETRY_TIMES;
948 while (LPSPI_GetTxFifoCount(base) == fifo_size) && ((--waitTimes) != 0U))
949 #else
950 while (LPSPI_GetTxFifoCount(base) == fifo_size)
951 #endif
952 {
953 }
954 #if SPI_RETRY_TIMES
955 if (waitTimes == 0U)
956 {
957 return false;
958 }
959 #endif
960
961 /* To prevent rxfifo overflow, ensure transmitting and receiving are executed in parallel */
962 if (((NULL == (stateParams->rxData)) ||
963 ((stateParams->rxRemainingByteCount) - txRemainingByteCount) < rxFifoMaxBytes))
964 {
965 if (stateParams->isTxMask)
966 {
967 /* When TCR[TXMSK]=1, transfer is initiate by writting a new command word to TCR. TCR[TXMSK] is cleared
968 by hardware every time when TCR[FRAMESZ] bit of data is transfered.
969 In this case TCR[TXMSK] should be set to initiate each transfer. */
970 base->TCR |= LPSPI_TCR_TXMSK_MASK;
971 if (stateParams->isPcsContinuous && (txRemainingByteCount == bytesPerFrame))
972 {
973 /* For the last piece of frame size of data, if is PCS continous mode(TCR[CONT]), TCR[CONTC] should
974 * be cleared to de-assert the PCS. Be sure to clear the TXMSK as well otherwise another FRAMESZ
975 * of data will be received. */
976 base->TCR &= ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK | LPSPI_TCR_TXMSK_MASK);
977 }
978 txRemainingByteCount -= bytesPerFrame;
979 }
980 else
981 {
982 if ((stateParams->txData) != NULL)
983 {
984 if (stateParams->bytesEachWrite != 1U)
985 {
986 wordToSend =
987 LPSPI_CombineWriteData((stateParams->txData), (stateParams->bytesEachWrite), isByteSwap);
988 (stateParams->txData) += (stateParams->bytesEachWrite);
989 }
990 else
991 {
992 wordToSend = *(stateParams->txData);
993 (stateParams->txData) += 1U;
994 }
995 }
996 /* Otherwise push data to tx FIFO to initiate transfer */
997 LPSPI_WriteData(base, wordToSend);
998 txRemainingByteCount -= (stateParams->bytesEachWrite);
999 }
1000 }
1001
1002 /* Check whether there is RX data in RX FIFO . Read out the RX data so that the RX FIFO would not overrun. */
1003 /*
1004 * $Branch Coverage Justification$
1005 * Data will be transferred in the inner loop until complete, after which the interrupt will end.(will improve)
1006 */
1007 if (((stateParams->rxData) != NULL) && ((stateParams->rxRemainingByteCount) != 0U))
1008 {
1009 /* To ensure parallel execution in 3-wire mode, after writting 1 to TXMSK to generate clock of
1010 bytesPerFrame's data wait until bytesPerFrame's data is received. */
1011 while ((stateParams->isTxMask) && (LPSPI_GetRxFifoCount(base) == 0U))
1012 {
1013 }
1014 #if SPI_RETRY_TIMES
1015 uint32_t waitTimes = SPI_RETRY_TIMES;
1016 while ((LPSPI_GetRxFifoCount(base) != 0U) && (--waitTimes != 0U))
1017 #else
1018 while (LPSPI_GetRxFifoCount(base) != 0U)
1019 #endif
1020 {
1021 readData = LPSPI_ReadData(base);
1022 /*
1023 * $Branch Coverage Justification$
1024 * rxRemainingByteCount must be an integer multiple of bytesEachRead, otherwise it cannot pass the check
1025 * of #LPSPI_CheckTransferArgument,so it doesn't happen here.(will improve)
1026 */
1027 if ((stateParams->rxRemainingByteCount) < (stateParams->bytesEachRead))
1028 {
1029 (stateParams->bytesEachRead) = (uint8_t)(stateParams->rxRemainingByteCount);
1030 }
1031
1032 LPSPI_SeparateReadData((stateParams->rxData), readData, (stateParams->bytesEachRead), isByteSwap);
1033 (stateParams->rxData) += (stateParams->bytesEachRead);
1034
1035 (stateParams->rxRemainingByteCount) -= (stateParams->bytesEachRead);
1036 }
1037 #if SPI_RETRY_TIMES
1038 if (waitTimes == 0U)
1039 {
1040 return false;
1041 }
1042 #endif
1043 }
1044 }
1045 return true;
1046 }
1047
1048 static bool LPSPI_MasterTransferClearTCR(LPSPI_Type *base, lpspi_transfer_blocking_param_t *stateParams)
1049 {
1050 #if SPI_RETRY_TIMES
1051 uint32_t waitTimes = SPI_RETRY_TIMES;
1052 while ((LPSPI_GetTxFifoCount(base) == LPSPI_GetRxFifoSize(base)) && (--waitTimes != 0U))
1053 #else
1054 while (LPSPI_GetTxFifoCount(base) == LPSPI_GetRxFifoSize(base))
1055 #endif
1056 {
1057 }
1058 #if SPI_RETRY_TIMES
1059 if (waitTimes == 0U)
1060 {
1061 return false;
1062 }
1063 #endif
1064 base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK));
1065 return true;
1066 }
1067
1068 static bool LPSPI_MasterTransferReadDataInFifo(LPSPI_Type *base,
1069 lpspi_transfer_t *transfer,
1070 lpspi_transfer_blocking_param_t *stateParams)
1071 {
1072 uint32_t readData;
1073 bool isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
1074 while ((stateParams->rxRemainingByteCount) > 0U)
1075 {
1076 #if SPI_RETRY_TIMES
1077 uint32_t waitTimes = SPI_RETRY_TIMES;
1078 while ((LPSPI_GetRxFifoCount(base) != 0U) && (--waitTimes != 0U))
1079 #else
1080 while (LPSPI_GetRxFifoCount(base) != 0U)
1081 #endif
1082 {
1083 readData = LPSPI_ReadData(base);
1084
1085 if ((stateParams->rxRemainingByteCount) < (stateParams->bytesEachRead))
1086 {
1087 (stateParams->bytesEachRead) = (uint8_t)(stateParams->rxRemainingByteCount);
1088 }
1089
1090 LPSPI_SeparateReadData((stateParams->rxData), readData, (stateParams->bytesEachRead), isByteSwap);
1091 (stateParams->rxData) += (stateParams->bytesEachRead);
1092
1093 (stateParams->rxRemainingByteCount) -= (stateParams->bytesEachRead);
1094 }
1095 #if SPI_RETRY_TIMES
1096 if (waitTimes == 0U)
1097 {
1098 return false;
1099 }
1100 #endif
1101 }
1102
1103 return true;
1104 }
1105
1106 static bool LPSPI_MasterTransferReadDataInFifoNoBuf(LPSPI_Type *base, lpspi_transfer_blocking_param_t *stateParams)
1107 {
1108 #if SPI_RETRY_TIMES
1109 uint32_t waitTimes = SPI_RETRY_TIMES;
1110 while (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) == 0U) && (--waitTimes != 0U))
1111 #else
1112 while ((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) == 0U)
1113 #endif
1114 {
1115 }
1116 #if SPI_RETRY_TIMES
1117 if (waitTimes == 0U)
1118 {
1119 return false;
1120 }
1121 #endif
1122 return true;
1123 }
1124
1125 /*!
1126 * brief LPSPI master transfer data using a polling method.
1127 *
1128 * This function transfers data using a polling method. This is a blocking function, which does not return until all
1129 * transfers have been completed.
1130 *
1131 * Note:
1132 * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4.
1133 * For bytesPerFrame greater than 4:
1134 * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4.
1135 * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
1136 *
1137 * param base LPSPI peripheral address.
1138 * param transfer pointer to lpspi_transfer_t structure.
1139 * return status of status_t.
1140 */
1141 status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer)
1142 {
1143 assert(transfer != NULL);
1144
1145 /* Check that LPSPI is not busy.*/
1146 /*
1147 * $Branch Coverage Justification$
1148 * MBF state setting and clearing is done by hardware, the state is too fast to be overwritten.(will improve)
1149 */
1150 if ((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_ModuleBusyFlag) != 0U)
1151 {
1152 return kStatus_LPSPI_Busy;
1153 }
1154 LPSPI_Enable(base, false);
1155 /* Check arguements */
1156 if (!LPSPI_CheckTransferArgument(base, transfer, false))
1157 {
1158 return kStatus_InvalidArgument;
1159 }
1160
1161 LPSPI_FlushFifo(base, true, true);
1162 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
1163
1164 /* Variables */
1165 uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
1166 uint32_t temp = (base->CFGR1 & LPSPI_CFGR1_PINCFG_MASK);
1167 lpspi_transfer_blocking_param_t stateParams;
1168 (void)memset(&stateParams, 0, sizeof(stateParams));
1169
1170 stateParams.txData = transfer->txData;
1171 stateParams.rxData = transfer->rxData;
1172 stateParams.isTxMask = false;
1173 stateParams.rxRemainingByteCount = transfer->dataSize;
1174 /*The TX and RX FIFO sizes are always the same*/
1175 uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
1176 /* No need to configure PCS continous if the transfer byte count is smaller than frame size */
1177 stateParams.isPcsContinuous = (((transfer->configFlags & (uint32_t)kLPSPI_MasterPcsContinuous) != 0U) &&
1178 (bytesPerFrame < transfer->dataSize));
1179
1180 /* Mask tx data in half duplex mode */
1181 if (((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut))) &&
1182 (stateParams.txData == NULL))
1183 {
1184 stateParams.isTxMask = true;
1185 }
1186
1187 base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
1188 LPSPI_Enable(base, true);
1189
1190 /* Configure transfer control register. */
1191 base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK |
1192 LPSPI_TCR_TXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
1193 LPSPI_TCR_PCS(whichPcs);
1194
1195 /*TCR is also shared the FIFO, so wait for TCR written.*/
1196 /*
1197 * $Branch Coverage Justification$
1198 * $ref fsl_lpspi_c_ref_2$
1199 */
1200 if (!LPSPI_TxFifoReady(base))
1201 {
1202 return kStatus_LPSPI_Timeout;
1203 }
1204
1205 /* PCS should be configured separately from the other bits, otherwise it will not take effect. */
1206 base->TCR |= LPSPI_TCR_CONT(stateParams.isPcsContinuous) | LPSPI_TCR_CONTC(stateParams.isPcsContinuous) |
1207 LPSPI_TCR_RXMSK(NULL == stateParams.rxData);
1208
1209 /*TCR is also shared the FIFO, so wait for TCR written.*/
1210 /*
1211 * $Branch Coverage Justification$
1212 * $ref fsl_lpspi_c_ref_2$
1213 */
1214 if (!LPSPI_TxFifoReady(base))
1215 {
1216 return kStatus_LPSPI_Timeout;
1217 }
1218
1219 if (bytesPerFrame <= 4U)
1220 {
1221 stateParams.bytesEachWrite = (uint8_t)bytesPerFrame;
1222 stateParams.bytesEachRead = (uint8_t)bytesPerFrame;
1223 }
1224 else
1225 {
1226 stateParams.bytesEachWrite = 4U;
1227 stateParams.bytesEachRead = 4U;
1228 }
1229
1230 /*
1231 * $Branch Coverage Justification$
1232 * $ref fsl_lpspi_c_ref_2$
1233 */
1234 if (false == LPSPI_MasterTransferWriteAllTxData(base, transfer, &stateParams))
1235 {
1236 return kStatus_LPSPI_Timeout;
1237 }
1238
1239 if (stateParams.isPcsContinuous && !stateParams.isTxMask)
1240 {
1241 /* In PCS continous mode(TCR[CONT]), after write all the data in TX FIFO, TCR[CONTC] and TCR[CONT] should be
1242 cleared to de-assert the PCS. Note that TCR register also use the TX FIFO. Also CONTC should be cleared when
1243 tx is not masked, otherwise written to TCR register with TXMSK bit set will initiate a new transfer. */
1244 /*
1245 * $Branch Coverage Justification$
1246 * $ref fsl_lpspi_c_ref_2$
1247 */
1248 if (false == LPSPI_MasterTransferClearTCR(base, &stateParams))
1249 {
1250 return kStatus_LPSPI_Timeout;
1251 }
1252 }
1253
1254 /*Read out the RX data in FIFO*/
1255 if (stateParams.rxData != NULL)
1256 {
1257 /*
1258 * $Branch Coverage Justification$
1259 * $ref fsl_lpspi_c_ref_2$
1260 */
1261 if (false == LPSPI_MasterTransferReadDataInFifo(base, transfer, &stateParams))
1262 {
1263 return kStatus_LPSPI_Timeout;
1264 }
1265 }
1266 else
1267 {
1268 /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
1269 /*
1270 * $Branch Coverage Justification$
1271 * $ref fsl_lpspi_c_ref_2$
1272 */
1273 if (false == LPSPI_MasterTransferReadDataInFifoNoBuf(base, &stateParams))
1274 {
1275 return kStatus_LPSPI_Timeout;
1276 }
1277 }
1278
1279 return kStatus_Success;
1280 }
1281
1282 /*!
1283 * brief LPSPI master transfer data using an interrupt method.
1284 *
1285 * This function transfers data using an interrupt method. This is a non-blocking function, which returns right away.
1286 * When all data is transferred, the callback function is called.
1287 *
1288 * Note:
1289 * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4.
1290 * For bytesPerFrame greater than 4:
1291 * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4.
1292 * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
1293 *
1294 * param base LPSPI peripheral address.
1295 * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1296 * param transfer pointer to lpspi_transfer_t structure.
1297 * return status of status_t.
1298 */
1299 status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer)
1300 {
1301 assert(handle != NULL);
1302 assert(transfer != NULL);
1303
1304 /* Check that we're not busy.*/
1305 if (handle->state == (uint8_t)kLPSPI_Busy)
1306 {
1307 return kStatus_LPSPI_Busy;
1308 }
1309
1310 LPSPI_Enable(base, false);
1311 /* Check arguements */
1312 if (!LPSPI_CheckTransferArgument(base, transfer, false))
1313 {
1314 return kStatus_InvalidArgument;
1315 }
1316
1317 /* Flush FIFO, clear status, disable all the interrupts. */
1318 LPSPI_FlushFifo(base, true, true);
1319 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
1320 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1321
1322 /* Variables */
1323 bool isRxMask = false;
1324 uint8_t txWatermark;
1325 uint8_t dummyData = g_lpspiDummyData[LPSPI_GetInstance(base)];
1326 uint32_t tmpTimes;
1327 uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
1328 uint32_t temp = (base->CFGR1 & LPSPI_CFGR1_PINCFG_MASK);
1329
1330 /* Assign the original value for members of transfer handle. */
1331 handle->state = (uint8_t)kLPSPI_Busy;
1332 handle->txData = transfer->txData;
1333 handle->rxData = transfer->rxData;
1334 handle->txRemainingByteCount = transfer->dataSize;
1335 handle->rxRemainingByteCount = transfer->dataSize;
1336 handle->totalByteCount = transfer->dataSize;
1337 handle->writeTcrInIsr = false;
1338 handle->bytesPerFrame = (uint16_t)((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
1339 /* No need to configure PCS continous if the transfer byte count is smaller than frame size */
1340 bool isPcsContinuous = (((transfer->configFlags & (uint32_t)kLPSPI_MasterPcsContinuous) != 0U) &&
1341 (transfer->dataSize > handle->bytesPerFrame));
1342 handle->writeRegRemainingTimes =
1343 (transfer->dataSize / (uint32_t)handle->bytesPerFrame) * (((uint32_t)handle->bytesPerFrame + 3U) / 4U);
1344 handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
1345 handle->txBuffIfNull =
1346 ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
1347 /*The TX and RX FIFO sizes are always the same*/
1348 handle->fifoSize = LPSPI_GetRxFifoSize(base);
1349 handle->isPcsContinuous = isPcsContinuous;
1350 handle->isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
1351 /*Calculate the bytes for write/read the TX/RX register each time*/
1352 if (handle->bytesPerFrame <= 4U)
1353 {
1354 handle->bytesEachWrite = (uint8_t)handle->bytesPerFrame;
1355 handle->bytesEachRead = (uint8_t)handle->bytesPerFrame;
1356 }
1357 else
1358 {
1359 handle->bytesEachWrite = 4U;
1360 handle->bytesEachRead = 4U;
1361 }
1362
1363 /*Set the RX and TX watermarks to reduce the ISR times.*/
1364 /*
1365 * $Branch Coverage Justification$
1366 * $ref fsl_lpspi_c_ref_3$
1367 */
1368 if (handle->fifoSize > 1U)
1369 {
1370 txWatermark = 1U;
1371 handle->rxWatermark = handle->fifoSize - 2U;
1372 }
1373 else
1374 {
1375 txWatermark = 0U;
1376 handle->rxWatermark = 0U;
1377 }
1378 LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
1379
1380 /* If there is no rxData, mask the receive data so that receive data is not stored in receive FIFO. */
1381 if (handle->rxData == NULL)
1382 {
1383 isRxMask = true;
1384 handle->rxRemainingByteCount = 0;
1385 }
1386
1387 /* Mask tx data in half duplex mode since the tx/rx share the same pin, so that the data received from slave is not
1388 * interfered. */
1389 if (((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut))) &&
1390 (handle->txData == NULL))
1391 {
1392 handle->isTxMask = true;
1393 }
1394
1395 /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
1396 base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
1397
1398 /* Enable module for following configuration of TCR to take effect. */
1399 LPSPI_Enable(base, true);
1400
1401 /* Configure transfer control register. */
1402 base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK |
1403 LPSPI_TCR_TXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
1404 LPSPI_TCR_PCS(whichPcs);
1405
1406 /*TCR is also shared the FIFO , so wait for TCR written.*/
1407 /*
1408 * $Branch Coverage Justification$
1409 * $ref fsl_lpspi_c_ref_2$
1410 */
1411 if (!LPSPI_TxFifoReady(base))
1412 {
1413 return kStatus_LPSPI_Timeout;
1414 }
1415
1416 /* PCS should be configured separately from the other bits, otherwise it will not take effect. */
1417 base->TCR |= LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(isPcsContinuous) | LPSPI_TCR_RXMSK(isRxMask);
1418
1419 /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
1420 * and you should also enable the INTMUX interupt in your application.
1421 */
1422 (void)EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
1423
1424 /*TCR is also shared the FIFO , so wait for TCR written.*/
1425 /*
1426 * $Branch Coverage Justification$
1427 * $ref fsl_lpspi_c_ref_2$
1428 */
1429 if (!LPSPI_TxFifoReady(base))
1430 {
1431 return kStatus_LPSPI_Timeout;
1432 }
1433
1434 if (handle->isTxMask)
1435 {
1436 /* When TCR[TXMSK]=1, transfer is initiate by writting a new command word to TCR. TCR[TXMSK] is cleared by
1437 hardware every time when TCR[FRAMESZ] bit of data is transfered. In this case TCR[TXMSK] should be set to
1438 initiate each transfer. */
1439
1440 base->TCR |= LPSPI_TCR_TXMSK_MASK;
1441 handle->txRemainingByteCount -= (uint32_t)handle->bytesPerFrame;
1442 }
1443 else
1444 {
1445 /* Fill up the TX data in FIFO to initiate transfer */
1446 LPSPI_MasterTransferFillUpTxFifo(base, handle);
1447 }
1448
1449 /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
1450 * The IRQ handler will get the status of RX and TX interrupt flags.
1451 */
1452 if (handle->rxData != NULL)
1453 {
1454 if (handle->isTxMask)
1455 {
1456 /* if tx data is masked, transfer is initiated by writing 1 to TCR[TXMSK] and TCR[FRMESZ] bits of data is
1457 read. If rx water mark is set larger than TCR[FRMESZ], rx interrupt will not be generated. Lower the rx
1458 water mark setting */
1459 if ((handle->bytesPerFrame / 4U) < (uint16_t)handle->rxWatermark)
1460 {
1461 handle->rxWatermark =
1462 (uint8_t)(handle->bytesPerFrame / 4U) > 0U ? (uint8_t)(handle->bytesPerFrame / 4U - 1U) : 0U;
1463 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->rxWatermark);
1464 }
1465 }
1466 else
1467 {
1468 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise
1469 *there is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1470 */
1471 tmpTimes = handle->readRegRemainingTimes;
1472 if (tmpTimes <= handle->rxWatermark)
1473 {
1474 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(tmpTimes - 1U);
1475 }
1476 }
1477
1478 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable);
1479 }
1480 else
1481 {
1482 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable);
1483 }
1484
1485 return kStatus_Success;
1486 }
1487
1488 static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_master_handle_t *handle)
1489 {
1490 assert(handle != NULL);
1491
1492 uint32_t wordToSend = 0;
1493 uint8_t fifoSize = handle->fifoSize;
1494 uint32_t writeRegRemainingTimes = handle->writeRegRemainingTimes;
1495 uint32_t readRegRemainingTimes = handle->readRegRemainingTimes;
1496 size_t txRemainingByteCount = handle->txRemainingByteCount;
1497 uint8_t bytesEachWrite = handle->bytesEachWrite;
1498 bool isByteSwap = handle->isByteSwap;
1499
1500 /* Make sure the difference in remaining TX and RX byte counts does not exceed FIFO depth
1501 * and that the number of TX FIFO entries does not exceed the FIFO depth.
1502 * But no need to make the protection if there is no rxData.
1503 */
1504 while ((LPSPI_GetTxFifoCount(base) < fifoSize) &&
1505 (((readRegRemainingTimes - writeRegRemainingTimes) < (uint32_t)fifoSize) || (handle->rxData == NULL)))
1506 {
1507 if (txRemainingByteCount < (size_t)bytesEachWrite)
1508 {
1509 handle->bytesEachWrite = (uint8_t)txRemainingByteCount;
1510 bytesEachWrite = handle->bytesEachWrite;
1511 }
1512
1513 if (handle->txData != NULL)
1514 {
1515 wordToSend = LPSPI_CombineWriteData(handle->txData, bytesEachWrite, isByteSwap);
1516 handle->txData += bytesEachWrite;
1517 }
1518 else
1519 {
1520 wordToSend = handle->txBuffIfNull;
1521 }
1522
1523 /*Write the word to TX register*/
1524 LPSPI_WriteData(base, wordToSend);
1525
1526 /*Decrease the write TX register times.*/
1527 --handle->writeRegRemainingTimes;
1528 writeRegRemainingTimes = handle->writeRegRemainingTimes;
1529
1530 /*Decrease the remaining TX byte count.*/
1531 handle->txRemainingByteCount -= (size_t)bytesEachWrite;
1532 txRemainingByteCount = handle->txRemainingByteCount;
1533
1534 if (handle->txRemainingByteCount == 0U)
1535 {
1536 /* If PCS is continuous, update TCR to de-assert PCS */
1537 if (handle->isPcsContinuous)
1538 {
1539 /* Only write to the TCR if the FIFO has room */
1540 if (LPSPI_GetTxFifoCount(base) < fifoSize)
1541 {
1542 base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
1543 handle->writeTcrInIsr = false;
1544 }
1545 /* Else, set a global flag to tell the ISR to do write to the TCR */
1546 else
1547 {
1548 handle->writeTcrInIsr = true;
1549 }
1550 }
1551 break;
1552 }
1553 }
1554 }
1555
1556 static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle)
1557 {
1558 assert(handle != NULL);
1559
1560 /* Disable interrupt requests*/
1561 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1562
1563 handle->state = (uint8_t)kLPSPI_Idle;
1564
1565 if (handle->callback != NULL)
1566 {
1567 handle->callback(base, handle, kStatus_Success, handle->userData);
1568 }
1569 }
1570
1571 /*!
1572 * brief Gets the master transfer remaining bytes.
1573 *
1574 * This function gets the master transfer remaining bytes.
1575 *
1576 * param base LPSPI peripheral address.
1577 * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1578 * param count Number of bytes transferred so far by the non-blocking transaction.
1579 * return status of status_t.
1580 */
1581 status_t LPSPI_MasterTransferGetCount(LPSPI_Type *base, lpspi_master_handle_t *handle, size_t *count)
1582 {
1583 assert(handle != NULL);
1584
1585 if (NULL == count)
1586 {
1587 return kStatus_InvalidArgument;
1588 }
1589
1590 /* Catch when there is not an active transfer. */
1591 if (handle->state != (uint8_t)kLPSPI_Busy)
1592 {
1593 *count = 0;
1594 return kStatus_NoTransferInProgress;
1595 }
1596
1597 size_t remainingByte;
1598
1599 if (handle->rxData != NULL)
1600 {
1601 remainingByte = handle->rxRemainingByteCount;
1602 }
1603 else
1604 {
1605 remainingByte = handle->txRemainingByteCount;
1606 }
1607
1608 *count = handle->totalByteCount - remainingByte;
1609
1610 return kStatus_Success;
1611 }
1612
1613 /*!
1614 * brief LPSPI master abort transfer which uses an interrupt method.
1615 *
1616 * This function aborts a transfer which uses an interrupt method.
1617 *
1618 * param base LPSPI peripheral address.
1619 * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1620 */
1621 void LPSPI_MasterTransferAbort(LPSPI_Type *base, lpspi_master_handle_t *handle)
1622 {
1623 assert(handle != NULL);
1624
1625 /* Disable interrupt requests*/
1626 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1627
1628 LPSPI_Reset(base);
1629
1630 handle->state = (uint8_t)kLPSPI_Idle;
1631 handle->txRemainingByteCount = 0;
1632 handle->rxRemainingByteCount = 0;
1633 }
1634
1635 /*!
1636 * brief LPSPI Master IRQ handler function.
1637 *
1638 * This function processes the LPSPI transmit and receive IRQ.
1639 *
1640 * param base LPSPI peripheral address.
1641 * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1642 */
1643 void LPSPI_MasterTransferHandleIRQ(LPSPI_Type *base, lpspi_master_handle_t *handle)
1644 {
1645 assert(handle != NULL);
1646
1647 uint32_t readData;
1648 uint8_t bytesEachRead = handle->bytesEachRead;
1649 bool isByteSwap = handle->isByteSwap;
1650 uint32_t readRegRemainingTimes = handle->readRegRemainingTimes;
1651
1652 if (handle->rxData != NULL)
1653 {
1654 if (handle->rxRemainingByteCount != 0U)
1655 {
1656 /* First, disable the interrupts to avoid potentially triggering another interrupt
1657 * while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll
1658 * re-enable the interrupts based on the LPSPI state after reading out the FIFO.
1659 */
1660 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable);
1661
1662 /*
1663 * $Branch Coverage Justification$
1664 * If the remaining number is 0, the FIFO must be 0, and the condition after will not be judged.(will
1665 * improve)
1666 */
1667 while ((LPSPI_GetRxFifoCount(base) != 0U) && (handle->rxRemainingByteCount != 0U))
1668 {
1669 /*Read out the data*/
1670 readData = LPSPI_ReadData(base);
1671
1672 /*Decrease the read RX register times.*/
1673 --handle->readRegRemainingTimes;
1674 readRegRemainingTimes = handle->readRegRemainingTimes;
1675
1676 if (handle->rxRemainingByteCount < (size_t)bytesEachRead)
1677 {
1678 handle->bytesEachRead = (uint8_t)(handle->rxRemainingByteCount);
1679 bytesEachRead = handle->bytesEachRead;
1680 }
1681
1682 LPSPI_SeparateReadData(handle->rxData, readData, bytesEachRead, isByteSwap);
1683 handle->rxData += bytesEachRead;
1684
1685 /*Decrease the remaining RX byte count.*/
1686 handle->rxRemainingByteCount -= (size_t)bytesEachRead;
1687 }
1688
1689 /* Re-enable the interrupts only if rxCount indicates there is more data to receive,
1690 * else we may get a spurious interrupt.
1691 * */
1692 if (handle->rxRemainingByteCount != 0U)
1693 {
1694 /* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */
1695 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable);
1696 }
1697 }
1698
1699 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1700 *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1701 */
1702 if (readRegRemainingTimes <= (uint32_t)handle->rxWatermark)
1703 {
1704 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
1705 LPSPI_FCR_RXWATER((readRegRemainingTimes > 1U) ? (readRegRemainingTimes - 1U) : (0U));
1706 }
1707 }
1708
1709 if (handle->txRemainingByteCount != 0U)
1710 {
1711 if (handle->isTxMask)
1712 {
1713 /* When TCR[TXMSK]=1, transfer is initiate by writting a new command word to TCR. TCR[TXMSK] is cleared by
1714 hardware every time when TCR[FRAMESZ] bit of data is transfered.
1715 In this case TCR[TXMSK] should be set to initiate each transfer. */
1716 base->TCR |= LPSPI_TCR_TXMSK_MASK;
1717 if ((handle->txRemainingByteCount == (uint32_t)handle->bytesPerFrame) && (handle->isPcsContinuous))
1718 {
1719 /* For the last piece of frame size of data, if is PCS continous mode(TCR[CONT]), TCR[CONTC] should
1720 * be cleared to de-assert the PCS. Be sure to clear the TXMSK as well otherwise another FRAMESZ
1721 * of data will be received. */
1722 base->TCR &= ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK | LPSPI_TCR_TXMSK_MASK);
1723 }
1724 handle->txRemainingByteCount -= (uint32_t)handle->bytesPerFrame;
1725 }
1726 else
1727 {
1728 LPSPI_MasterTransferFillUpTxFifo(base, handle);
1729 }
1730 }
1731 else
1732 {
1733 if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)))
1734 {
1735 if ((handle->isPcsContinuous) && (handle->writeTcrInIsr) && (!handle->isTxMask))
1736 {
1737 base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
1738 handle->writeTcrInIsr = false;
1739 }
1740 }
1741 }
1742
1743 if ((handle->txRemainingByteCount == 0U) && (handle->rxRemainingByteCount == 0U) && (!handle->writeTcrInIsr))
1744 {
1745 /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
1746 if (handle->rxData == NULL)
1747 {
1748 if ((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) != 0U)
1749 {
1750 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_TransferCompleteFlag);
1751 /* Complete the transfer and disable the interrupts */
1752 LPSPI_MasterTransferComplete(base, handle);
1753 }
1754 else
1755 {
1756 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TransferCompleteInterruptEnable);
1757 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable | (uint32_t)kLPSPI_RxInterruptEnable);
1758 }
1759 }
1760 else
1761 {
1762 /* Complete the transfer and disable the interrupts */
1763 LPSPI_MasterTransferComplete(base, handle);
1764 }
1765 }
1766 }
1767
1768 /*Transactional APIs -- Slave*/
1769 /*!
1770 * brief Initializes the LPSPI slave handle.
1771 *
1772 * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs. Usually, for a
1773 * specified LPSPI instance, call this API once to get the initialized handle.
1774 *
1775 * param base LPSPI peripheral address.
1776 * param handle LPSPI handle pointer to lpspi_slave_handle_t.
1777 * param callback DSPI callback.
1778 * param userData callback function parameter.
1779 */
1780 void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base,
1781 lpspi_slave_handle_t *handle,
1782 lpspi_slave_transfer_callback_t callback,
1783 void *userData)
1784 {
1785 assert(handle != NULL);
1786
1787 /* Zero the handle. */
1788 (void)memset(handle, 0, sizeof(*handle));
1789
1790 s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
1791
1792 /* Set irq handler. */
1793 s_lpspiSlaveIsr = LPSPI_SlaveTransferHandleIRQ;
1794
1795 handle->callback = callback;
1796 handle->userData = userData;
1797 }
1798
1799 /*!
1800 * brief LPSPI slave transfer data using an interrupt method.
1801 *
1802 * This function transfer data using an interrupt method. This is a non-blocking function, which returns right away.
1803 * When all data is transferred, the callback function is called.
1804 *
1805 * Note:
1806 * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4.
1807 * For bytesPerFrame greater than 4:
1808 * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
1809 * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
1810 *
1811 * param base LPSPI peripheral address.
1812 * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
1813 * param transfer pointer to lpspi_transfer_t structure.
1814 * return status of status_t.
1815 */
1816 status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer)
1817 {
1818 assert(handle != NULL);
1819 assert(transfer != NULL);
1820
1821 /* Check that we're not busy.*/
1822 if (handle->state == (uint8_t)kLPSPI_Busy)
1823 {
1824 return kStatus_LPSPI_Busy;
1825 }
1826 LPSPI_Enable(base, false);
1827 /* Check arguements */
1828 if (!LPSPI_CheckTransferArgument(base, transfer, false))
1829 {
1830 return kStatus_InvalidArgument;
1831 }
1832
1833 /* Flush FIFO, clear status, disable all the inerrupts. */
1834 LPSPI_FlushFifo(base, true, true);
1835 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
1836 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1837
1838 /* Variables */
1839 bool isRxMask = false;
1840 bool isTxMask = false;
1841 uint8_t txWatermark;
1842 uint32_t readRegRemainingTimes;
1843 uint32_t whichPcs = (transfer->configFlags & LPSPI_SLAVE_PCS_MASK) >> LPSPI_SLAVE_PCS_SHIFT;
1844 uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
1845
1846 /* Assign the original value for members of transfer handle. */
1847 handle->state = (uint8_t)kLPSPI_Busy;
1848 handle->txData = transfer->txData;
1849 handle->rxData = transfer->rxData;
1850 handle->txRemainingByteCount = transfer->dataSize;
1851 handle->rxRemainingByteCount = transfer->dataSize;
1852 handle->totalByteCount = transfer->dataSize;
1853 handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
1854 handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
1855 /*The TX and RX FIFO sizes are always the same*/
1856 handle->fifoSize = LPSPI_GetRxFifoSize(base);
1857 handle->isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_SlaveByteSwap) != 0U);
1858 /*Calculate the bytes for write/read the TX/RX register each time*/
1859 if (bytesPerFrame <= 4U)
1860 {
1861 handle->bytesEachWrite = (uint8_t)bytesPerFrame;
1862 handle->bytesEachRead = (uint8_t)bytesPerFrame;
1863 }
1864 else
1865 {
1866 handle->bytesEachWrite = 4U;
1867 handle->bytesEachRead = 4U;
1868 }
1869 /* Set proper RX and TX watermarks to reduce the ISR response times. */
1870 /*
1871 * $Branch Coverage Justification$
1872 * $ref fsl_lpspi_c_ref_3$
1873 */
1874 if (handle->fifoSize > 1U)
1875 {
1876 txWatermark = 1U;
1877 handle->rxWatermark = handle->fifoSize / 2U;
1878 }
1879 else
1880 {
1881 txWatermark = 0U;
1882 handle->rxWatermark = 0U;
1883 }
1884 LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
1885
1886 /* If there is no rxData, mask the receive data so that receive data is not stored in receive FIFO. */
1887 if (handle->rxData == NULL)
1888 {
1889 isRxMask = true;
1890 handle->rxRemainingByteCount = 0U;
1891 }
1892 /* If there is no txData, mask the transmit data so that no data is loaded from transmit FIFO and output pin
1893 * is tristated. */
1894 if (handle->txData == NULL)
1895 {
1896 isTxMask = true;
1897 handle->txRemainingByteCount = 0U;
1898 }
1899
1900 /* Enable module for following configuration of TCR to take effect. */
1901 LPSPI_Enable(base, true);
1902
1903 base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK |
1904 LPSPI_TCR_TXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
1905 LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_TXMSK(isTxMask) | LPSPI_TCR_PCS(whichPcs);
1906
1907 /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
1908 * and you should also enable the INTMUX interupt in your application.
1909 */
1910 (void)EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
1911
1912 /*TCR is also shared the FIFO, so wait for TCR written.*/
1913 /*
1914 * $Branch Coverage Justification$
1915 * $ref fsl_lpspi_c_ref_3$
1916 */
1917 if (!LPSPI_TxFifoReady(base))
1918 {
1919 return kStatus_LPSPI_Timeout;
1920 }
1921
1922 /* Fill up the TX data in FIFO */
1923 if (handle->txData != NULL)
1924 {
1925 LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1926 }
1927
1928 /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
1929 * The IRQ handler will get the status of RX and TX interrupt flags.
1930 */
1931 if (handle->rxData != NULL)
1932 {
1933 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1934 *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1935 */
1936 readRegRemainingTimes = handle->readRegRemainingTimes;
1937 if (readRegRemainingTimes <= (uint32_t)handle->rxWatermark)
1938 {
1939 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(readRegRemainingTimes - 1U);
1940 }
1941
1942 /* RX request and FIFO overflow request enable */
1943 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable | (uint32_t)kLPSPI_ReceiveErrorInterruptEnable);
1944 }
1945 else
1946 {
1947 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable);
1948 }
1949
1950 if (handle->txData != NULL)
1951 {
1952 /* TX FIFO underflow request enable */
1953 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TransmitErrorInterruptEnable);
1954 }
1955
1956 return kStatus_Success;
1957 }
1958
1959 static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1960 {
1961 assert(handle != NULL);
1962
1963 uint32_t wordToSend = 0U;
1964 uint8_t bytesEachWrite = handle->bytesEachWrite;
1965 bool isByteSwap = handle->isByteSwap;
1966
1967 while (LPSPI_GetTxFifoCount(base) < (handle->fifoSize))
1968 {
1969 if (handle->txRemainingByteCount < (size_t)bytesEachWrite)
1970 {
1971 handle->bytesEachWrite = (uint8_t)handle->txRemainingByteCount;
1972 bytesEachWrite = handle->bytesEachWrite;
1973 }
1974
1975 wordToSend = LPSPI_CombineWriteData(handle->txData, bytesEachWrite, isByteSwap);
1976 handle->txData += bytesEachWrite;
1977
1978 /*Decrease the remaining TX byte count.*/
1979 handle->txRemainingByteCount -= (size_t)bytesEachWrite;
1980
1981 /*Write the word to TX register*/
1982 LPSPI_WriteData(base, wordToSend);
1983
1984 if (handle->txRemainingByteCount == 0U)
1985 {
1986 break;
1987 }
1988 }
1989 }
1990
1991 static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1992 {
1993 assert(handle != NULL);
1994
1995 status_t status = kStatus_Success;
1996
1997 /* Disable interrupt requests*/
1998 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1999
2000 if (handle->state == (uint8_t)kLPSPI_Error)
2001 {
2002 status = kStatus_LPSPI_Error;
2003 }
2004 else
2005 {
2006 status = kStatus_Success;
2007 }
2008
2009 handle->state = (uint8_t)kLPSPI_Idle;
2010
2011 if (handle->callback != NULL)
2012 {
2013 handle->callback(base, handle, status, handle->userData);
2014 }
2015 }
2016
2017 /*!
2018 * brief Gets the slave transfer remaining bytes.
2019 *
2020 * This function gets the slave transfer remaining bytes.
2021 *
2022 * param base LPSPI peripheral address.
2023 * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
2024 * param count Number of bytes transferred so far by the non-blocking transaction.
2025 * return status of status_t.
2026 */
2027 status_t LPSPI_SlaveTransferGetCount(LPSPI_Type *base, lpspi_slave_handle_t *handle, size_t *count)
2028 {
2029 assert(handle != NULL);
2030
2031 if (NULL == count)
2032 {
2033 return kStatus_InvalidArgument;
2034 }
2035
2036 /* Catch when there is not an active transfer. */
2037 if (handle->state != (uint8_t)kLPSPI_Busy)
2038 {
2039 *count = 0;
2040 return kStatus_NoTransferInProgress;
2041 }
2042
2043 size_t remainingByte;
2044
2045 if (handle->rxData != NULL)
2046 {
2047 remainingByte = handle->rxRemainingByteCount;
2048 }
2049 else
2050 {
2051 remainingByte = handle->txRemainingByteCount;
2052 }
2053
2054 *count = handle->totalByteCount - remainingByte;
2055
2056 return kStatus_Success;
2057 }
2058
2059 /*!
2060 * brief LPSPI slave aborts a transfer which uses an interrupt method.
2061 *
2062 * This function aborts a transfer which uses an interrupt method.
2063 *
2064 * param base LPSPI peripheral address.
2065 * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
2066 */
2067 void LPSPI_SlaveTransferAbort(LPSPI_Type *base, lpspi_slave_handle_t *handle)
2068 {
2069 assert(handle != NULL);
2070
2071 /* Disable interrupt requests*/
2072 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable | (uint32_t)kLPSPI_RxInterruptEnable);
2073
2074 LPSPI_Reset(base);
2075
2076 handle->state = (uint8_t)kLPSPI_Idle;
2077 handle->txRemainingByteCount = 0U;
2078 handle->rxRemainingByteCount = 0U;
2079 }
2080
2081 /*!
2082 * brief LPSPI Slave IRQ handler function.
2083 *
2084 * This function processes the LPSPI transmit and receives an IRQ.
2085 *
2086 * param base LPSPI peripheral address.
2087 * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
2088 */
2089 void LPSPI_SlaveTransferHandleIRQ(LPSPI_Type *base, lpspi_slave_handle_t *handle)
2090 {
2091 assert(handle != NULL);
2092
2093 uint32_t readData; /* variable to store word read from RX FIFO */
2094 uint8_t bytesEachRead = handle->bytesEachRead;
2095 bool isByteSwap = handle->isByteSwap;
2096 uint32_t readRegRemainingTimes;
2097
2098 if (handle->rxData != NULL)
2099 {
2100 if (handle->rxRemainingByteCount > 0U)
2101 {
2102 while (LPSPI_GetRxFifoCount(base) != 0U)
2103 {
2104 /*Read out the data*/
2105 readData = LPSPI_ReadData(base);
2106
2107 /*Decrease the read RX register times.*/
2108 --handle->readRegRemainingTimes;
2109
2110 if (handle->rxRemainingByteCount < (size_t)bytesEachRead)
2111 {
2112 handle->bytesEachRead = (uint8_t)handle->rxRemainingByteCount;
2113 bytesEachRead = handle->bytesEachRead;
2114 }
2115
2116 LPSPI_SeparateReadData(handle->rxData, readData, bytesEachRead, isByteSwap);
2117 handle->rxData += bytesEachRead;
2118
2119 /*Decrease the remaining RX byte count.*/
2120 handle->rxRemainingByteCount -= (size_t)bytesEachRead;
2121
2122 if ((handle->txRemainingByteCount > 0U) && (handle->txData != NULL))
2123 {
2124 LPSPI_SlaveTransferFillUpTxFifo(base, handle);
2125 }
2126
2127 if (handle->rxRemainingByteCount == 0U)
2128 {
2129 break;
2130 }
2131 }
2132 }
2133
2134 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
2135 *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
2136 */
2137 readRegRemainingTimes = handle->readRegRemainingTimes;
2138 if (readRegRemainingTimes <= (uint32_t)handle->rxWatermark)
2139 {
2140 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
2141 LPSPI_FCR_RXWATER((readRegRemainingTimes > 1U) ? (readRegRemainingTimes - 1U) : (0U));
2142 }
2143 }
2144 if ((handle->rxData == NULL) && (handle->txRemainingByteCount != 0U) && (handle->txData != NULL))
2145 {
2146 LPSPI_SlaveTransferFillUpTxFifo(base, handle);
2147 }
2148
2149 if ((handle->txRemainingByteCount == 0U) && (handle->rxRemainingByteCount == 0U))
2150 {
2151 /* If no RX buffer, then transfer is not complete until transfer complete flag sets and the TX FIFO empty*/
2152 if (handle->rxData == NULL)
2153 {
2154 if (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_FrameCompleteFlag) != 0U) &&
2155 (LPSPI_GetTxFifoCount(base) == 0U))
2156 {
2157 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_FrameCompleteFlag);
2158 /* Complete the transfer and disable the interrupts */
2159 LPSPI_SlaveTransferComplete(base, handle);
2160 }
2161 else
2162 {
2163 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_FrameCompleteFlag);
2164 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_FrameCompleteInterruptEnable);
2165 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable | (uint32_t)kLPSPI_RxInterruptEnable);
2166 }
2167 }
2168 else
2169 {
2170 /* Complete the transfer and disable the interrupts */
2171 LPSPI_SlaveTransferComplete(base, handle);
2172 }
2173 }
2174
2175 /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */
2176 /*
2177 * $Branch Coverage Justification$
2178 * $ref fsl_lpspi_c_ref_4$
2179 */
2180 if (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransmitErrorFlag) != 0U) &&
2181 ((base->IER & LPSPI_IER_TEIE_MASK) != 0U))
2182 {
2183 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_TransmitErrorFlag);
2184 /* Change state to error and clear flag */
2185 if (handle->txData != NULL)
2186 {
2187 handle->state = (uint8_t)kLPSPI_Error;
2188 }
2189 handle->errorCount++;
2190 }
2191 /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */
2192 /*
2193 * $Branch Coverage Justification$
2194 * $ref fsl_lpspi_c_ref_4$
2195 */
2196 if (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_ReceiveErrorFlag) != 0U) &&
2197 ((base->IER & LPSPI_IER_REIE_MASK) != 0U))
2198 {
2199 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_ReceiveErrorFlag);
2200 /* Change state to error and clear flag */
2201 /*
2202 * $Branch Coverage Justification$
2203 * This error happens on receive, so rxData won't be empty.(will improve)
2204 */
2205 if (handle->rxData != NULL)
2206 {
2207 handle->state = (uint8_t)kLPSPI_Error;
2208 }
2209 handle->errorCount++;
2210 }
2211 }
2212
2213 static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint8_t bytesEachWrite, bool isByteSwap)
2214 {
2215 assert(txData != NULL);
2216
2217 uint32_t wordToSend = 0U;
2218
2219 /*
2220 * $Branch Coverage Justification$
2221 * $ref fsl_lpspi_c_ref_1$
2222 */
2223 switch (bytesEachWrite)
2224 {
2225 case 1:
2226 wordToSend = *txData;
2227 ++txData;
2228 break;
2229
2230 case 2:
2231 if (!isByteSwap)
2232 {
2233 wordToSend = *txData;
2234 ++txData;
2235 wordToSend |= (unsigned)(*txData) << 8U;
2236 ++txData;
2237 }
2238 else
2239 {
2240 wordToSend = (unsigned)(*txData) << 8U;
2241 ++txData;
2242 wordToSend |= *txData;
2243 ++txData;
2244 }
2245
2246 break;
2247
2248 case 3:
2249 if (!isByteSwap)
2250 {
2251 wordToSend = *txData;
2252 ++txData;
2253 wordToSend |= (unsigned)(*txData) << 8U;
2254 ++txData;
2255 wordToSend |= (unsigned)(*txData) << 16U;
2256 ++txData;
2257 }
2258 else
2259 {
2260 wordToSend = (unsigned)(*txData) << 16U;
2261 ++txData;
2262 wordToSend |= (unsigned)(*txData) << 8U;
2263 ++txData;
2264 wordToSend |= *txData;
2265 ++txData;
2266 }
2267 break;
2268
2269 case 4:
2270 if (!isByteSwap)
2271 {
2272 wordToSend = *txData;
2273 ++txData;
2274 wordToSend |= (unsigned)(*txData) << 8U;
2275 ++txData;
2276 wordToSend |= (unsigned)(*txData) << 16U;
2277 ++txData;
2278 wordToSend |= (unsigned)(*txData) << 24U;
2279 ++txData;
2280 }
2281 else
2282 {
2283 wordToSend = (unsigned)(*txData) << 24U;
2284 ++txData;
2285 wordToSend |= (unsigned)(*txData) << 16U;
2286 ++txData;
2287 wordToSend |= (unsigned)(*txData) << 8U;
2288 ++txData;
2289 wordToSend |= *txData;
2290 ++txData;
2291 }
2292 break;
2293
2294 default:
2295 assert(false);
2296 break;
2297 }
2298 return wordToSend;
2299 }
2300
2301 static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint8_t bytesEachRead, bool isByteSwap)
2302 {
2303 assert(rxData != NULL);
2304
2305 /*
2306 * $Branch Coverage Justification$
2307 * $ref fsl_lpspi_c_ref_1$
2308 */
2309 switch (bytesEachRead)
2310 {
2311 case 1:
2312 *rxData = (uint8_t)readData;
2313 ++rxData;
2314 break;
2315
2316 case 2:
2317 if (!isByteSwap)
2318 {
2319 *rxData = (uint8_t)readData;
2320 ++rxData;
2321 *rxData = (uint8_t)(readData >> 8);
2322 ++rxData;
2323 }
2324 else
2325 {
2326 *rxData = (uint8_t)(readData >> 8);
2327 ++rxData;
2328 *rxData = (uint8_t)readData;
2329 ++rxData;
2330 }
2331 break;
2332
2333 case 3:
2334 if (!isByteSwap)
2335 {
2336 *rxData = (uint8_t)readData;
2337 ++rxData;
2338 *rxData = (uint8_t)(readData >> 8);
2339 ++rxData;
2340 *rxData = (uint8_t)(readData >> 16);
2341 ++rxData;
2342 }
2343 else
2344 {
2345 *rxData = (uint8_t)(readData >> 16);
2346 ++rxData;
2347 *rxData = (uint8_t)(readData >> 8);
2348 ++rxData;
2349 *rxData = (uint8_t)readData;
2350 ++rxData;
2351 }
2352 break;
2353
2354 case 4:
2355 if (!isByteSwap)
2356 {
2357 *rxData = (uint8_t)readData;
2358 ++rxData;
2359 *rxData = (uint8_t)(readData >> 8);
2360 ++rxData;
2361 *rxData = (uint8_t)(readData >> 16);
2362 ++rxData;
2363 *rxData = (uint8_t)(readData >> 24);
2364 ++rxData;
2365 }
2366 else
2367 {
2368 *rxData = (uint8_t)(readData >> 24);
2369 ++rxData;
2370 *rxData = (uint8_t)(readData >> 16);
2371 ++rxData;
2372 *rxData = (uint8_t)(readData >> 8);
2373 ++rxData;
2374 *rxData = (uint8_t)readData;
2375 ++rxData;
2376 }
2377 break;
2378
2379 default:
2380 assert(false);
2381 break;
2382 }
2383 }
2384
2385 static bool LPSPI_TxFifoReady(LPSPI_Type *base)
2386 {
2387 #if SPI_RETRY_TIMES
2388 uint32_t waitTimes = SPI_RETRY_TIMES;
2389 while (((uint8_t)LPSPI_GetTxFifoCount(base) != 0U) && (--waitTimes != 0U))
2390 #else
2391 while ((uint8_t)LPSPI_GetTxFifoCount(base) != 0U)
2392 #endif
2393 {
2394 }
2395 #if SPI_RETRY_TIMES
2396 if (waitTimes == 0U)
2397 {
2398 return false;
2399 }
2400 #endif
2401 return true;
2402 }
2403
2404 static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param)
2405 {
2406 if (LPSPI_IsMaster(base))
2407 {
2408 s_lpspiMasterIsr(base, (lpspi_master_handle_t *)param);
2409 }
2410 else
2411 {
2412 s_lpspiSlaveIsr(base, (lpspi_slave_handle_t *)param);
2413 }
2414 SDK_ISR_EXIT_BARRIER;
2415 }
2416
2417 #if defined(LPSPI0)
2418 void LPSPI0_DriverIRQHandler(void);
2419 void LPSPI0_DriverIRQHandler(void)
2420 {
2421 assert(s_lpspiHandle[0] != NULL);
2422 LPSPI_CommonIRQHandler(LPSPI0, s_lpspiHandle[0]);
2423 }
2424 #endif
2425
2426 #if defined(LPSPI1)
2427 void LPSPI1_DriverIRQHandler(void);
2428 void LPSPI1_DriverIRQHandler(void)
2429 {
2430 assert(s_lpspiHandle[1] != NULL);
2431 LPSPI_CommonIRQHandler(LPSPI1, s_lpspiHandle[1]);
2432 }
2433 #endif
2434
2435 #if defined(LPSPI2)
2436 void LPSPI2_DriverIRQHandler(void);
2437 void LPSPI2_DriverIRQHandler(void)
2438 {
2439 assert(s_lpspiHandle[2] != NULL);
2440 LPSPI_CommonIRQHandler(LPSPI2, s_lpspiHandle[2]);
2441 }
2442 #endif
2443
2444 #if defined(LPSPI3)
2445 void LPSPI3_DriverIRQHandler(void);
2446 void LPSPI3_DriverIRQHandler(void)
2447 {
2448 assert(s_lpspiHandle[3] != NULL);
2449 LPSPI_CommonIRQHandler(LPSPI3, s_lpspiHandle[3]);
2450 }
2451 #endif
2452
2453 #if defined(LPSPI4)
2454 void LPSPI4_DriverIRQHandler(void);
2455 void LPSPI4_DriverIRQHandler(void)
2456 {
2457 assert(s_lpspiHandle[4] != NULL);
2458 LPSPI_CommonIRQHandler(LPSPI4, s_lpspiHandle[4]);
2459 }
2460 #endif
2461
2462 #if defined(LPSPI5)
2463 void LPSPI5_DriverIRQHandler(void);
2464 void LPSPI5_DriverIRQHandler(void)
2465 {
2466 assert(s_lpspiHandle[5] != NULL);
2467 LPSPI_CommonIRQHandler(LPSPI5, s_lpspiHandle[5]);
2468 }
2469 #endif
2470
2471 #if defined(DMA__LPSPI0)
2472 void DMA_SPI0_INT_DriverIRQHandler(void);
2473 void DMA_SPI0_INT_DriverIRQHandler(void)
2474 {
2475 assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI0)] != NULL);
2476 LPSPI_CommonIRQHandler(DMA__LPSPI0, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI0)]);
2477 }
2478 #endif
2479
2480 #if defined(DMA__LPSPI1)
2481 void DMA_SPI1_INT_DriverIRQHandler(void);
2482 void DMA_SPI1_INT_DriverIRQHandler(void)
2483 {
2484 assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI1)] != NULL);
2485 LPSPI_CommonIRQHandler(DMA__LPSPI1, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI1)]);
2486 }
2487 #endif
2488 #if defined(DMA__LPSPI2)
2489 void DMA_SPI2_INT_DriverIRQHandler(void);
2490 void DMA_SPI2_INT_DriverIRQHandler(void)
2491 {
2492 assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI2)] != NULL);
2493 LPSPI_CommonIRQHandler(DMA__LPSPI2, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI2)]);
2494 }
2495 #endif
2496
2497 #if defined(DMA__LPSPI3)
2498 void DMA_SPI3_INT_DriverIRQHandler(void);
2499 void DMA_SPI3_INT_DriverIRQHandler(void)
2500 {
2501 assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI3)] != NULL);
2502 LPSPI_CommonIRQHandler(DMA__LPSPI3, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI3)]);
2503 }
2504 #endif
2505
2506 #if defined(ADMA__LPSPI0)
2507 void ADMA_SPI0_INT_DriverIRQHandler(void);
2508 void ADMA_SPI0_INT_DriverIRQHandler(void)
2509 {
2510 assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI0)] != NULL);
2511 LPSPI_CommonIRQHandler(ADMA__LPSPI0, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI0)]);
2512 }
2513 #endif
2514
2515 #if defined(ADMA__LPSPI1)
2516 void ADMA_SPI1_INT_DriverIRQHandler(void);
2517 void ADMA_SPI1_INT_DriverIRQHandler(void)
2518 {
2519 assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI1)] != NULL);
2520 LPSPI_CommonIRQHandler(ADMA__LPSPI1, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI1)]);
2521 }
2522 #endif
2523 #if defined(ADMA__LPSPI2)
2524 void ADMA_SPI2_INT_DriverIRQHandler(void);
2525 void ADMA_SPI2_INT_DriverIRQHandler(void)
2526 {
2527 assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI2)] != NULL);
2528 LPSPI_CommonIRQHandler(ADMA__LPSPI2, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI2)]);
2529 }
2530 #endif
2531
2532 #if defined(ADMA__LPSPI3)
2533 void ADMA_SPI3_INT_DriverIRQHandler(void);
2534 void ADMA_SPI3_INT_DriverIRQHandler(void)
2535 {
2536 assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI3)] != NULL);
2537 LPSPI_CommonIRQHandler(ADMA__LPSPI3, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI3)]);
2538 }
2539 #endif
2540