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