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