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