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