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  */
25 enum _lpspi_default_watermarks
26 {
27     kLpspiDefaultTxWatermark = 0,
28     kLpspiDefaultRxWatermark = 0,
29 };
30 
31 /*! @brief Typedef for master interrupt handler. */
32 typedef void (*lpspi_master_isr_t)(LPSPI_Type *base, lpspi_master_handle_t *handle);
33 
34 /*! @brief Typedef for slave interrupt handler. */
35 typedef 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  */
53 static 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  */
61 static 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  */
67 static 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  */
75 static 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  */
81 static 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  */
88 static 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  */
94 static 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  */
101 static 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  */
108 static 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.*/
115 static const uint8_t s_baudratePrescaler[] = {1, 2, 4, 8, 16, 32, 64, 128};
116 
117 /*! @brief Pointers to lpspi bases for each instance. */
118 static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS;
119 
120 /*! @brief Pointers to lpspi IRQ number for each instance. */
121 static 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. */
125 static const clock_ip_name_t s_lpspiClocks[] = LPSPI_CLOCKS;
126 
127 #if defined(LPSPI_PERIPH_CLOCKS)
128 static 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. */
134 static void *s_lpspiHandle[ARRAY_SIZE(s_lpspiBases)];
135 
136 /*! @brief Pointer to master IRQ handler for each instance. */
137 static lpspi_master_isr_t s_lpspiMasterIsr;
138 /*! @brief Pointer to slave IRQ handler for each instance. */
139 static lpspi_slave_isr_t s_lpspiSlaveIsr;
140 /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
141 volatile 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  */
LPSPI_GetInstance(LPSPI_Type * base)153 uint32_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  */
LPSPI_SetDummyData(LPSPI_Type * base,uint8_t dummyData)181 void 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  */
LPSPI_MasterInit(LPSPI_Type * base,const lpspi_master_config_t * masterConfig,uint32_t srcClock_Hz)194 void 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  */
LPSPI_MasterGetDefaultConfig(lpspi_master_config_t * masterConfig)257 void 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  */
LPSPI_SlaveInit(LPSPI_Type * base,const lpspi_slave_config_t * slaveConfig)287 void 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  */
LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t * slaveConfig)334 void 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  */
LPSPI_Reset(LPSPI_Type * base)359 void 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  */
LPSPI_Deinit(LPSPI_Type * base)375 void 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 
LPSPI_SetOnePcsPolarity(LPSPI_Type * base,lpspi_which_pcs_t pcs,lpspi_pcs_polarity_config_t activeLowOrHigh)393 static 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 
LPSPI_MasterSetBaudRate(LPSPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz,uint32_t * tcrPrescaleValue)428 uint32_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     base->CCR = (base->CCR & ~LPSPI_CCR_SCKDIV_MASK) | LPSPI_CCR_SCKDIV(bestScaler);
502 
503     /* return the best prescaler value for user to use later */
504     *tcrPrescaleValue = bestPrescaler;
505 
506     /* return the actual calculated baud rate */
507     return bestBaudrate;
508 }
509 
510 /*!
511  * brief Manually configures a specific LPSPI delay parameter (module must be disabled to
512  *        change the delay values).
513  *
514  * This function configures the following:
515  * SCK to PCS delay, or
516  * PCS to SCK delay, or
517  * The configurations must occur between the transfer delay.
518  *
519  * The delay names are available in type lpspi_delay_type_t.
520  *
521  * The user passes the desired delay along with the delay value.
522  * This allows the user to directly set the delay values if they have
523  * pre-calculated them or if they simply wish to manually increment the value.
524  *
525  * Note that the LPSPI module must first be disabled before configuring this.
526  * Note that the LPSPI module must be configured for master mode before configuring this.
527  *
528  * param base LPSPI peripheral address.
529  * param scaler The 8-bit delay value 0x00 to 0xFF (255).
530  * param whichDelay The desired delay to configure, must be of type lpspi_delay_type_t.
531  */
LPSPI_MasterSetDelayScaler(LPSPI_Type * base,uint32_t scaler,lpspi_delay_type_t whichDelay)532 void LPSPI_MasterSetDelayScaler(LPSPI_Type *base, uint32_t scaler, lpspi_delay_type_t whichDelay)
533 {
534     /*These settings are only relevant in master mode */
535     switch (whichDelay)
536     {
537         case kLPSPI_PcsToSck:
538             base->CCR = (base->CCR & (~LPSPI_CCR_PCSSCK_MASK)) | LPSPI_CCR_PCSSCK(scaler);
539 
540             break;
541         case kLPSPI_LastSckToPcs:
542             base->CCR = (base->CCR & (~LPSPI_CCR_SCKPCS_MASK)) | LPSPI_CCR_SCKPCS(scaler);
543 
544             break;
545         case kLPSPI_BetweenTransfer:
546             base->CCR = (base->CCR & (~LPSPI_CCR_DBT_MASK)) | LPSPI_CCR_DBT(scaler);
547 
548             break;
549         default:
550             assert(false);
551             break;
552     }
553 }
554 
555 /*!
556  * brief Calculates the delay based on the desired delay input in nanoseconds (module must be
557  *        disabled to change the delay values).
558  *
559  * This function calculates the values for the following:
560  * SCK to PCS delay, or
561  * PCS to SCK delay, or
562  * The configurations must occur between the transfer delay.
563  *
564  * The delay names are available in type lpspi_delay_type_t.
565  *
566  * The user passes the desired delay and the desired delay value in
567  * nano-seconds.  The function calculates the value needed for the desired delay parameter
568  * and returns the actual calculated delay because an exact delay match may not be possible. In this
569  * case, the closest match is calculated without going below the desired delay value input.
570  * It is possible to input a very large delay value that exceeds the capability of the part, in
571  * which case the maximum supported delay is returned. It is up to the higher level
572  * peripheral driver to alert the user of an out of range delay input.
573  *
574  * Note that the LPSPI module must be configured for master mode before configuring this. And note that
575  * the delayTime = LPSPI_clockSource / (PRESCALE * Delay_scaler).
576  *
577  * param base LPSPI peripheral address.
578  * param delayTimeInNanoSec The desired delay value in nano-seconds.
579  * param whichDelay The desired delay to configuration, which must be of type lpspi_delay_type_t.
580  * param srcClock_Hz  Module source input clock in Hertz.
581  * return actual Calculated delay value in nano-seconds.
582  */
LPSPI_MasterSetDelayTimes(LPSPI_Type * base,uint32_t delayTimeInNanoSec,lpspi_delay_type_t whichDelay,uint32_t srcClock_Hz)583 uint32_t LPSPI_MasterSetDelayTimes(LPSPI_Type *base,
584                                    uint32_t delayTimeInNanoSec,
585                                    lpspi_delay_type_t whichDelay,
586                                    uint32_t srcClock_Hz)
587 {
588     uint64_t realDelay, bestDelay;
589     uint32_t scaler, bestScaler;
590     uint32_t diff, min_diff;
591     uint64_t initialDelayNanoSec;
592     uint32_t clockDividedPrescaler;
593 
594     /* For delay between transfer, an additional scaler value is needed */
595     uint32_t additionalScaler = 0;
596 
597     /*As the RM note, the LPSPI baud rate clock is itself divided by the PRESCALE setting, which can vary between
598      * transfers.*/
599     clockDividedPrescaler =
600         srcClock_Hz / s_baudratePrescaler[(base->TCR & LPSPI_TCR_PRESCALE_MASK) >> LPSPI_TCR_PRESCALE_SHIFT];
601 
602     /* Find combination of prescaler and scaler resulting in the delay closest to the requested value.*/
603     min_diff = 0xFFFFFFFFU;
604 
605     /* Initialize scaler to max value to generate the max delay */
606     bestScaler = 0xFFU;
607 
608     /* Calculate the initial (min) delay and maximum possible delay based on the specific delay as
609      * the delay divisors are slightly different based on which delay we are configuring.
610      */
611     if (whichDelay == kLPSPI_BetweenTransfer)
612     {
613         /* First calculate the initial, default delay, note min delay is 2 clock cycles. Due to large size of
614          calculated values (uint64_t), we need to break up the calculation into several steps to ensure
615          accurate calculated results
616          */
617         initialDelayNanoSec = 1000000000U;
618         initialDelayNanoSec *= 2U;
619         initialDelayNanoSec /= clockDividedPrescaler;
620 
621         /* Calculate the maximum delay */
622         bestDelay = 1000000000U;
623         bestDelay *= 257U; /* based on DBT+2, or 255 + 2 */
624         bestDelay /= clockDividedPrescaler;
625 
626         additionalScaler = 1U;
627     }
628     else
629     {
630         /* First calculate the initial, default delay, min delay is 1 clock cycle. Due to large size of calculated
631         values (uint64_t), we need to break up the calculation into several steps to ensure accurate calculated
632         results.
633         */
634         initialDelayNanoSec = 1000000000U;
635         initialDelayNanoSec /= clockDividedPrescaler;
636 
637         /* Calculate the maximum delay */
638         bestDelay = 1000000000U;
639         bestDelay *= 256U; /* based on SCKPCS+1 or PCSSCK+1, or 255 + 1 */
640         bestDelay /= clockDividedPrescaler;
641 
642         additionalScaler = 0U;
643     }
644 
645     /* If the initial, default delay is already greater than the desired delay, then
646      * set the delay to their initial value (0) and return the delay. In other words,
647      * there is no way to decrease the delay value further.
648      */
649     if (initialDelayNanoSec >= delayTimeInNanoSec)
650     {
651         LPSPI_MasterSetDelayScaler(base, 0, whichDelay);
652         return (uint32_t)initialDelayNanoSec;
653     }
654 
655     /* If min_diff = 0, the exit for loop */
656     for (scaler = 0U; scaler < 256U; scaler++)
657     {
658         if (min_diff == 0U)
659         {
660             break;
661         }
662         /* Calculate the real delay value as we cycle through the scaler values.
663         Due to large size of calculated values (uint64_t), we need to break up the
664         calculation into several steps to ensure accurate calculated results
665         */
666         realDelay = 1000000000U;
667         realDelay *= ((uint64_t)scaler + 1UL + (uint64_t)additionalScaler);
668         realDelay /= clockDividedPrescaler;
669 
670         /* calculate the delay difference based on the conditional statement
671          * that states that the calculated delay must not be less then the desired delay
672          */
673         if (realDelay >= delayTimeInNanoSec)
674         {
675             diff = (uint32_t)(realDelay - (uint64_t)delayTimeInNanoSec);
676             if (min_diff > diff)
677             {
678                 /* a better match found */
679                 min_diff   = diff;
680                 bestScaler = scaler;
681                 bestDelay  = realDelay;
682             }
683         }
684     }
685 
686     /* write the best scaler value for the delay */
687     LPSPI_MasterSetDelayScaler(base, bestScaler, whichDelay);
688 
689     /* return the actual calculated delay value (in ns) */
690     return (uint32_t)bestDelay;
691 }
692 
693 /*Transactional APIs -- Master*/
694 
695 /*!
696  * brief Initializes the LPSPI master handle.
697  *
698  * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs.  Usually, for a
699  * specified LPSPI instance, call this API once to get the initialized handle.
700 
701  * param base LPSPI peripheral address.
702  * param handle LPSPI handle pointer to lpspi_master_handle_t.
703  * param callback DSPI callback.
704  * param userData callback function parameter.
705  */
LPSPI_MasterTransferCreateHandle(LPSPI_Type * base,lpspi_master_handle_t * handle,lpspi_master_transfer_callback_t callback,void * userData)706 void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base,
707                                       lpspi_master_handle_t *handle,
708                                       lpspi_master_transfer_callback_t callback,
709                                       void *userData)
710 {
711     assert(handle != NULL);
712 
713     /* Zero the handle. */
714     (void)memset(handle, 0, sizeof(*handle));
715 
716     s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
717 
718     /* Set irq handler. */
719     s_lpspiMasterIsr = LPSPI_MasterTransferHandleIRQ;
720 
721     handle->callback = callback;
722     handle->userData = userData;
723 }
724 
725 /*!
726  * brief Check the argument for transfer .
727  *
728  * param base LPSPI peripheral address.
729  * param transfer the transfer struct to be used.
730  * param isEdma True to check for EDMA transfer, false to check interrupt non-blocking transfer
731  * return Return true for right and false for wrong.
732  */
LPSPI_CheckTransferArgument(LPSPI_Type * base,lpspi_transfer_t * transfer,bool isEdma)733 bool LPSPI_CheckTransferArgument(LPSPI_Type *base, lpspi_transfer_t *transfer, bool isEdma)
734 {
735     assert(transfer != NULL);
736     uint32_t bitsPerFrame  = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1U;
737     uint32_t bytesPerFrame = (bitsPerFrame + 7U) / 8U;
738     uint32_t temp          = (base->CFGR1 & LPSPI_CFGR1_PINCFG_MASK);
739     /* If the transfer count is zero, then return immediately.*/
740     if (transfer->dataSize == 0U)
741     {
742         return false;
743     }
744 
745     /* If both send buffer and receive buffer is null */
746     if ((NULL == (transfer->txData)) && (NULL == (transfer->rxData)))
747     {
748         return false;
749     }
750 
751     /*The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4 .
752      *For bytesPerFrame greater than 4 situation:
753      *the transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4 ,
754      *otherwise , the transfer data size can be integer multiples of bytesPerFrame.
755      */
756     if (bytesPerFrame <= 4U)
757     {
758         if ((transfer->dataSize % bytesPerFrame) != 0U)
759         {
760             return false;
761         }
762     }
763     else
764     {
765         if ((bytesPerFrame % 4U) != 0U)
766         {
767             if (transfer->dataSize != bytesPerFrame)
768             {
769                 return false;
770             }
771         }
772         else
773         {
774             if ((transfer->dataSize % bytesPerFrame) != 0U)
775             {
776                 return false;
777             }
778         }
779     }
780 
781     /* Check if using 3-wire mode and the txData is NULL, set the output pin to tristated. */
782     if ((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut)))
783     {
784         /* The 3-wire mode can't send and receive data at the same time. */
785         if ((transfer->txData != NULL) && (transfer->rxData != NULL))
786         {
787             return false;
788         }
789         if (NULL == transfer->txData)
790         {
791             base->CFGR1 |= LPSPI_CFGR1_OUTCFG_MASK;
792         }
793     }
794 
795     if (isEdma && ((bytesPerFrame % 4U) == 3U))
796     {
797         return false;
798     }
799 
800     return true;
801 }
802 
803 /*!
804  * brief LPSPI master transfer data using a polling method.
805  *
806  * This function transfers data using a  polling method. This is a blocking function, which does not return until all
807  * transfers have been completed.
808  *
809  * Note:
810  * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4.
811  * For bytesPerFrame greater than 4:
812  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4.
813  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
814  *
815  * param base LPSPI peripheral address.
816  * param transfer pointer to lpspi_transfer_t structure.
817  * return status of status_t.
818  */
LPSPI_MasterTransferBlocking(LPSPI_Type * base,lpspi_transfer_t * transfer)819 status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer)
820 {
821     assert(transfer != NULL);
822 
823     /* Check that LPSPI is not busy.*/
824     if ((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_ModuleBusyFlag) != 0U)
825     {
826         return kStatus_LPSPI_Busy;
827     }
828     LPSPI_Enable(base, false);
829     /* Check arguements */
830     if (!LPSPI_CheckTransferArgument(base, transfer, false))
831     {
832         return kStatus_InvalidArgument;
833     }
834 
835     LPSPI_FlushFifo(base, true, true);
836     LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
837 
838     /* Variables */
839     bool isTxMask   = false;
840     bool isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
841     uint8_t bytesEachWrite;
842     uint8_t bytesEachRead;
843     uint8_t *txData               = transfer->txData;
844     uint8_t *rxData               = transfer->rxData;
845     uint8_t dummyData             = g_lpspiDummyData[LPSPI_GetInstance(base)];
846     uint32_t readData             = 0U;
847     uint32_t txRemainingByteCount = transfer->dataSize;
848     uint32_t rxRemainingByteCount = transfer->dataSize;
849     uint32_t wordToSend =
850         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
851     /*The TX and RX FIFO sizes are always the same*/
852     uint32_t fifoSize      = LPSPI_GetRxFifoSize(base);
853     uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
854     /* No need to configure PCS continous if the transfer byte count is smaller than frame size */
855     bool isPcsContinuous    = (((transfer->configFlags & (uint32_t)kLPSPI_MasterPcsContinuous) != 0U) &&
856                             (bytesPerFrame < transfer->dataSize));
857     uint32_t rxFifoMaxBytes = MIN(bytesPerFrame, 4U) * fifoSize;
858     uint32_t whichPcs       = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
859     uint32_t temp           = (base->CFGR1 & LPSPI_CFGR1_PINCFG_MASK);
860 
861 #if SPI_RETRY_TIMES
862     uint32_t waitTimes;
863 #endif
864 
865     /* Mask tx data in half duplex mode */
866     if (((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut))) &&
867         (txData == NULL))
868     {
869         isTxMask = true;
870     }
871 
872     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
873     LPSPI_Enable(base, true);
874 
875     /* Configure transfer control register. */
876     base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK |
877                                LPSPI_TCR_TXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
878                 LPSPI_TCR_PCS(whichPcs);
879 
880     /*TCR is also shared the FIFO, so wait for TCR written.*/
881     if (!LPSPI_TxFifoReady(base))
882     {
883         return kStatus_LPSPI_Timeout;
884     }
885 
886     /* PCS should be configured separately from the other bits, otherwise it will not take effect. */
887     base->TCR |= LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(isPcsContinuous) | LPSPI_TCR_RXMSK(NULL == rxData);
888 
889     /*TCR is also shared the FIFO, so wait for TCR written.*/
890     if (!LPSPI_TxFifoReady(base))
891     {
892         return kStatus_LPSPI_Timeout;
893     }
894 
895     if (bytesPerFrame <= 4U)
896     {
897         bytesEachWrite = (uint8_t)bytesPerFrame;
898         bytesEachRead  = (uint8_t)bytesPerFrame;
899     }
900     else
901     {
902         bytesEachWrite = 4U;
903         bytesEachRead  = 4U;
904     }
905 
906     /*Write the TX data until txRemainingByteCount is equal to 0 */
907     while (txRemainingByteCount > 0U)
908     {
909         if (txRemainingByteCount < bytesEachWrite)
910         {
911             bytesEachWrite = (uint8_t)txRemainingByteCount;
912         }
913 
914         /*Wait until TX FIFO is not full*/
915 #if SPI_RETRY_TIMES
916         waitTimes = SPI_RETRY_TIMES;
917         while ((LPSPI_GetTxFifoCount(base) == fifoSize) && (--waitTimes != 0U))
918 #else
919         while (LPSPI_GetTxFifoCount(base) == fifoSize)
920 #endif
921         {
922         }
923 #if SPI_RETRY_TIMES
924         if (waitTimes == 0U)
925         {
926             return kStatus_LPSPI_Timeout;
927         }
928 #endif
929 
930         /* To prevent rxfifo overflow, ensure transmitting and receiving are executed in parallel */
931         if (((NULL == rxData) || (rxRemainingByteCount - txRemainingByteCount) < rxFifoMaxBytes))
932         {
933             if (isTxMask)
934             {
935                 /* When TCR[TXMSK]=1, transfer is initiate by writting a new command word to TCR. TCR[TXMSK] is cleared
936                    by hardware every time when TCR[FRAMESZ] bit of data is transfered.
937                    In this case TCR[TXMSK] should be set to initiate each transfer. */
938                 base->TCR |= LPSPI_TCR_TXMSK_MASK;
939                 if (isPcsContinuous && (txRemainingByteCount == bytesPerFrame))
940                 {
941                     /* For the last piece of frame size of data, if is PCS continous mode(TCR[CONT]), TCR[CONTC] should
942                      * be cleared to de-assert the PCS. Be sure to clear the TXMSK as well otherwise another FRAMESZ
943                      * of data will be received. */
944                     base->TCR &= ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK | LPSPI_TCR_TXMSK_MASK);
945                 }
946                 txRemainingByteCount -= bytesPerFrame;
947             }
948             else
949             {
950                 if (txData != NULL)
951                 {
952                     wordToSend = LPSPI_CombineWriteData(txData, bytesEachWrite, isByteSwap);
953                     txData += bytesEachWrite;
954                 }
955                 /* Otherwise push data to tx FIFO to initiate transfer */
956                 LPSPI_WriteData(base, wordToSend);
957                 txRemainingByteCount -= bytesEachWrite;
958             }
959         }
960 
961         /* Check whether there is RX data in RX FIFO . Read out the RX data so that the RX FIFO would not overrun. */
962         if ((rxData != NULL) && (rxRemainingByteCount != 0U))
963         {
964             /* To ensure parallel execution in 3-wire mode, after writting 1 to TXMSK to generate clock of
965                bytesPerFrame's data wait until bytesPerFrame's data is received. */
966             while (isTxMask && (LPSPI_GetRxFifoCount(base) == 0U))
967             {
968             }
969 #if SPI_RETRY_TIMES
970             waitTimes = SPI_RETRY_TIMES;
971             while ((LPSPI_GetRxFifoCount(base) != 0U) && (--waitTimes != 0U))
972 #else
973             while (LPSPI_GetRxFifoCount(base) != 0U)
974 #endif
975             {
976                 readData = LPSPI_ReadData(base);
977                 if (rxRemainingByteCount < bytesEachRead)
978                 {
979                     bytesEachRead = (uint8_t)rxRemainingByteCount;
980                 }
981 
982                 LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap);
983                 rxData += bytesEachRead;
984 
985                 rxRemainingByteCount -= bytesEachRead;
986             }
987 #if SPI_RETRY_TIMES
988             if (waitTimes == 0U)
989             {
990                 return kStatus_LPSPI_Timeout;
991             }
992 #endif
993         }
994     }
995 
996     if (isPcsContinuous && !isTxMask)
997     {
998         /* In PCS continous mode(TCR[CONT]), after write all the data in TX FIFO, TCR[CONTC] and TCR[CONT] should be
999            cleared to de-assert the PCS. Note that TCR register also use the TX FIFO. Also CONTC should be cleared when
1000            tx is not masked, otherwise written to TCR register with TXMSK bit wet will initiate a new transfer. */
1001 #if SPI_RETRY_TIMES
1002         waitTimes = SPI_RETRY_TIMES;
1003         while ((LPSPI_GetTxFifoCount(base) == fifoSize) && (--waitTimes != 0U))
1004 #else
1005         while (LPSPI_GetTxFifoCount(base) == fifoSize)
1006 #endif
1007         {
1008         }
1009 #if SPI_RETRY_TIMES
1010         if (waitTimes == 0U)
1011         {
1012             return kStatus_LPSPI_Timeout;
1013         }
1014 #endif
1015         base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK));
1016     }
1017 
1018     /*Read out the RX data in FIFO*/
1019     if (rxData != NULL)
1020     {
1021         while (rxRemainingByteCount > 0U)
1022         {
1023 #if SPI_RETRY_TIMES
1024             waitTimes = SPI_RETRY_TIMES;
1025             while ((LPSPI_GetRxFifoCount(base) != 0U) && (--waitTimes != 0U))
1026 #else
1027             while (LPSPI_GetRxFifoCount(base) != 0U)
1028 #endif
1029             {
1030                 readData = LPSPI_ReadData(base);
1031 
1032                 if (rxRemainingByteCount < bytesEachRead)
1033                 {
1034                     bytesEachRead = (uint8_t)rxRemainingByteCount;
1035                 }
1036 
1037                 LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap);
1038                 rxData += bytesEachRead;
1039 
1040                 rxRemainingByteCount -= bytesEachRead;
1041             }
1042 #if SPI_RETRY_TIMES
1043             if (waitTimes == 0U)
1044             {
1045                 return kStatus_LPSPI_Timeout;
1046             }
1047 #endif
1048         }
1049     }
1050     else
1051     {
1052         /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
1053 #if SPI_RETRY_TIMES
1054         waitTimes = SPI_RETRY_TIMES;
1055         while (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) == 0U) && (--waitTimes != 0U))
1056 #else
1057         while ((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) == 0U)
1058 #endif
1059         {
1060         }
1061 #if SPI_RETRY_TIMES
1062         if (waitTimes == 0U)
1063         {
1064             return kStatus_LPSPI_Timeout;
1065         }
1066 #endif
1067     }
1068 
1069     return kStatus_Success;
1070 }
1071 
1072 /*!
1073  * brief LPSPI master transfer data using an interrupt method.
1074  *
1075  * This function transfers data using an interrupt method. This is a non-blocking function, which returns right away.
1076  * When all data is transferred, the callback function is called.
1077  *
1078  * Note:
1079  * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4.
1080  * For bytesPerFrame greater than 4:
1081  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4.
1082  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
1083  *
1084  * param base LPSPI peripheral address.
1085  * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1086  * param transfer pointer to lpspi_transfer_t structure.
1087  * return status of status_t.
1088  */
LPSPI_MasterTransferNonBlocking(LPSPI_Type * base,lpspi_master_handle_t * handle,lpspi_transfer_t * transfer)1089 status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer)
1090 {
1091     assert(handle != NULL);
1092     assert(transfer != NULL);
1093 
1094     /* Check that we're not busy.*/
1095     if (handle->state == (uint8_t)kLPSPI_Busy)
1096     {
1097         return kStatus_LPSPI_Busy;
1098     }
1099 
1100     LPSPI_Enable(base, false);
1101     /* Check arguements */
1102     if (!LPSPI_CheckTransferArgument(base, transfer, false))
1103     {
1104         return kStatus_InvalidArgument;
1105     }
1106 
1107     /* Flush FIFO, clear status, disable all the interrupts. */
1108     LPSPI_FlushFifo(base, true, true);
1109     LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
1110     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1111 
1112     /* Variables */
1113     bool isRxMask = false;
1114     uint8_t txWatermark;
1115     uint8_t dummyData = g_lpspiDummyData[LPSPI_GetInstance(base)];
1116     uint32_t tmpTimes;
1117     uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
1118     uint32_t temp     = (base->CFGR1 & LPSPI_CFGR1_PINCFG_MASK);
1119 
1120     /* Assign the original value for members of transfer handle. */
1121     handle->state                = (uint8_t)kLPSPI_Busy;
1122     handle->txData               = transfer->txData;
1123     handle->rxData               = transfer->rxData;
1124     handle->txRemainingByteCount = transfer->dataSize;
1125     handle->rxRemainingByteCount = transfer->dataSize;
1126     handle->totalByteCount       = transfer->dataSize;
1127     handle->writeTcrInIsr        = false;
1128     handle->bytesPerFrame = (uint16_t)((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
1129     /* No need to configure PCS continous if the transfer byte count is smaller than frame size */
1130     bool isPcsContinuous = (((transfer->configFlags & (uint32_t)kLPSPI_MasterPcsContinuous) != 0U) &&
1131                             (transfer->dataSize > handle->bytesPerFrame));
1132     handle->writeRegRemainingTimes =
1133         (transfer->dataSize / (uint32_t)handle->bytesPerFrame) * (((uint32_t)handle->bytesPerFrame + 3U) / 4U);
1134     handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
1135     handle->txBuffIfNull =
1136         ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
1137     /*The TX and RX FIFO sizes are always the same*/
1138     handle->fifoSize        = LPSPI_GetRxFifoSize(base);
1139     handle->isPcsContinuous = isPcsContinuous;
1140     handle->isByteSwap      = ((transfer->configFlags & (uint32_t)kLPSPI_MasterByteSwap) != 0U);
1141     /*Calculate the bytes for write/read the TX/RX register each time*/
1142     if (handle->bytesPerFrame <= 4U)
1143     {
1144         handle->bytesEachWrite = (uint8_t)handle->bytesPerFrame;
1145         handle->bytesEachRead  = (uint8_t)handle->bytesPerFrame;
1146     }
1147     else
1148     {
1149         handle->bytesEachWrite = 4U;
1150         handle->bytesEachRead  = 4U;
1151     }
1152 
1153     /*Set the RX and TX watermarks to reduce the ISR times.*/
1154     if (handle->fifoSize > 1U)
1155     {
1156         txWatermark         = 1U;
1157         handle->rxWatermark = handle->fifoSize - 2U;
1158     }
1159     else
1160     {
1161         txWatermark         = 0U;
1162         handle->rxWatermark = 0U;
1163     }
1164     LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
1165 
1166     /* If there is no rxData, mask the receive data so that receive data is not stored in receive FIFO. */
1167     if (handle->rxData == NULL)
1168     {
1169         isRxMask                     = true;
1170         handle->rxRemainingByteCount = 0;
1171     }
1172 
1173     /* Mask tx data in half duplex mode since the tx/rx share the same pin, so that the data received from slave is not
1174      * interfered. */
1175     if (((temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdiInSdiOut)) || (temp == LPSPI_CFGR1_PINCFG(kLPSPI_SdoInSdoOut))) &&
1176         (handle->txData == NULL))
1177     {
1178         handle->isTxMask = true;
1179     }
1180 
1181     /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
1182     base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
1183 
1184     /* Enable module for following configuration of TCR to take effect. */
1185     LPSPI_Enable(base, true);
1186 
1187     /* Configure transfer control register. */
1188     base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK |
1189                                LPSPI_TCR_TXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
1190                 LPSPI_TCR_PCS(whichPcs);
1191 
1192     /*TCR is also shared the FIFO , so wait for TCR written.*/
1193     if (!LPSPI_TxFifoReady(base))
1194     {
1195         return kStatus_LPSPI_Timeout;
1196     }
1197 
1198     /* PCS should be configured separately from the other bits, otherwise it will not take effect. */
1199     base->TCR |= LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(isPcsContinuous) | LPSPI_TCR_RXMSK(isRxMask);
1200 
1201     /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
1202      * and you should also enable the INTMUX interupt in your application.
1203      */
1204     (void)EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
1205 
1206     /*TCR is also shared the FIFO , so wait for TCR written.*/
1207     if (!LPSPI_TxFifoReady(base))
1208     {
1209         return kStatus_LPSPI_Timeout;
1210     }
1211 
1212     if (handle->isTxMask)
1213     {
1214         /* When TCR[TXMSK]=1, transfer is initiate by writting a new command word to TCR. TCR[TXMSK] is cleared by
1215            hardware every time when TCR[FRAMESZ] bit of data is transfered. In this case TCR[TXMSK] should be set to
1216            initiate each transfer. */
1217 
1218         base->TCR |= LPSPI_TCR_TXMSK_MASK;
1219         handle->txRemainingByteCount -= (uint32_t)handle->bytesPerFrame;
1220     }
1221     else
1222     {
1223         /* Fill up the TX data in FIFO to initiate transfer */
1224         LPSPI_MasterTransferFillUpTxFifo(base, handle);
1225     }
1226 
1227     /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
1228      * The IRQ handler will get the status of RX and TX interrupt flags.
1229      */
1230     if (handle->rxData != NULL)
1231     {
1232         if (handle->isTxMask)
1233         {
1234             /* if tx data is masked, transfer is initiated by writing 1 to TCR[TXMSK] and TCR[FRMESZ] bits of data is
1235                read. If rx water mark is set larger than TCR[FRMESZ], rx interrupt will not be generated. Lower the rx
1236                water mark setting */
1237             if ((handle->bytesPerFrame / 4U) < (uint16_t)handle->rxWatermark)
1238             {
1239                 handle->rxWatermark =
1240                     (uint8_t)(handle->bytesPerFrame / 4U) > 0U ? (uint8_t)(handle->bytesPerFrame / 4U - 1U) : 0U;
1241                 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->rxWatermark);
1242             }
1243         }
1244         else
1245         {
1246             /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise
1247              *there is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1248              */
1249             tmpTimes = handle->readRegRemainingTimes;
1250             if (tmpTimes <= handle->rxWatermark)
1251             {
1252                 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(tmpTimes - 1U);
1253             }
1254         }
1255 
1256         LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable);
1257     }
1258     else
1259     {
1260         LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable);
1261     }
1262 
1263     return kStatus_Success;
1264 }
1265 
LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type * base,lpspi_master_handle_t * handle)1266 static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_master_handle_t *handle)
1267 {
1268     assert(handle != NULL);
1269 
1270     uint32_t wordToSend             = 0;
1271     uint8_t fifoSize                = handle->fifoSize;
1272     uint32_t writeRegRemainingTimes = handle->writeRegRemainingTimes;
1273     uint32_t readRegRemainingTimes  = handle->readRegRemainingTimes;
1274     size_t txRemainingByteCount     = handle->txRemainingByteCount;
1275     uint8_t bytesEachWrite          = handle->bytesEachWrite;
1276     bool isByteSwap                 = handle->isByteSwap;
1277 
1278     /* Make sure the difference in remaining TX and RX byte counts does not exceed FIFO depth
1279      * and that the number of TX FIFO entries does not exceed the FIFO depth.
1280      * But no need to make the protection if there is no rxData.
1281      */
1282     while ((LPSPI_GetTxFifoCount(base) < fifoSize) &&
1283            (((readRegRemainingTimes - writeRegRemainingTimes) < (uint32_t)fifoSize) || (handle->rxData == NULL)))
1284     {
1285         if (txRemainingByteCount < (size_t)bytesEachWrite)
1286         {
1287             handle->bytesEachWrite = (uint8_t)txRemainingByteCount;
1288             bytesEachWrite         = handle->bytesEachWrite;
1289         }
1290 
1291         if (handle->txData != NULL)
1292         {
1293             wordToSend = LPSPI_CombineWriteData(handle->txData, bytesEachWrite, isByteSwap);
1294             handle->txData += bytesEachWrite;
1295         }
1296         else
1297         {
1298             wordToSend = handle->txBuffIfNull;
1299         }
1300 
1301         /*Write the word to TX register*/
1302         LPSPI_WriteData(base, wordToSend);
1303 
1304         /*Decrease the write TX register times.*/
1305         --handle->writeRegRemainingTimes;
1306         writeRegRemainingTimes = handle->writeRegRemainingTimes;
1307 
1308         /*Decrease the remaining TX byte count.*/
1309         handle->txRemainingByteCount -= (size_t)bytesEachWrite;
1310         txRemainingByteCount = handle->txRemainingByteCount;
1311 
1312         if (handle->txRemainingByteCount == 0U)
1313         {
1314             /* If PCS is continuous, update TCR to de-assert PCS */
1315             if (handle->isPcsContinuous)
1316             {
1317                 /* Only write to the TCR if the FIFO has room */
1318                 if (LPSPI_GetTxFifoCount(base) < fifoSize)
1319                 {
1320                     base->TCR             = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
1321                     handle->writeTcrInIsr = false;
1322                 }
1323                 /* Else, set a global flag to tell the ISR to do write to the TCR */
1324                 else
1325                 {
1326                     handle->writeTcrInIsr = true;
1327                 }
1328             }
1329             break;
1330         }
1331     }
1332 }
1333 
LPSPI_MasterTransferComplete(LPSPI_Type * base,lpspi_master_handle_t * handle)1334 static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle)
1335 {
1336     assert(handle != NULL);
1337 
1338     /* Disable interrupt requests*/
1339     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1340 
1341     handle->state = (uint8_t)kLPSPI_Idle;
1342 
1343     if (handle->callback != NULL)
1344     {
1345         handle->callback(base, handle, kStatus_Success, handle->userData);
1346     }
1347 }
1348 
1349 /*!
1350  * brief Gets the master transfer remaining bytes.
1351  *
1352  * This function gets the master transfer remaining bytes.
1353  *
1354  * param base LPSPI peripheral address.
1355  * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1356  * param count Number of bytes transferred so far by the non-blocking transaction.
1357  * return status of status_t.
1358  */
LPSPI_MasterTransferGetCount(LPSPI_Type * base,lpspi_master_handle_t * handle,size_t * count)1359 status_t LPSPI_MasterTransferGetCount(LPSPI_Type *base, lpspi_master_handle_t *handle, size_t *count)
1360 {
1361     assert(handle != NULL);
1362 
1363     if (NULL == count)
1364     {
1365         return kStatus_InvalidArgument;
1366     }
1367 
1368     /* Catch when there is not an active transfer. */
1369     if (handle->state != (uint8_t)kLPSPI_Busy)
1370     {
1371         *count = 0;
1372         return kStatus_NoTransferInProgress;
1373     }
1374 
1375     size_t remainingByte;
1376 
1377     if (handle->rxData != NULL)
1378     {
1379         remainingByte = handle->rxRemainingByteCount;
1380     }
1381     else
1382     {
1383         remainingByte = handle->txRemainingByteCount;
1384     }
1385 
1386     *count = handle->totalByteCount - remainingByte;
1387 
1388     return kStatus_Success;
1389 }
1390 
1391 /*!
1392  * brief LPSPI master abort transfer which uses an interrupt method.
1393  *
1394  * This function aborts a transfer which uses an interrupt method.
1395  *
1396  * param base LPSPI peripheral address.
1397  * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1398  */
LPSPI_MasterTransferAbort(LPSPI_Type * base,lpspi_master_handle_t * handle)1399 void LPSPI_MasterTransferAbort(LPSPI_Type *base, lpspi_master_handle_t *handle)
1400 {
1401     assert(handle != NULL);
1402 
1403     /* Disable interrupt requests*/
1404     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1405 
1406     LPSPI_Reset(base);
1407 
1408     handle->state                = (uint8_t)kLPSPI_Idle;
1409     handle->txRemainingByteCount = 0;
1410     handle->rxRemainingByteCount = 0;
1411 }
1412 
1413 /*!
1414  * brief LPSPI Master IRQ handler function.
1415  *
1416  * This function processes the LPSPI transmit and receive IRQ.
1417  *
1418  * param base LPSPI peripheral address.
1419  * param handle pointer to lpspi_master_handle_t structure which stores the transfer state.
1420  */
LPSPI_MasterTransferHandleIRQ(LPSPI_Type * base,lpspi_master_handle_t * handle)1421 void LPSPI_MasterTransferHandleIRQ(LPSPI_Type *base, lpspi_master_handle_t *handle)
1422 {
1423     assert(handle != NULL);
1424 
1425     uint32_t readData;
1426     uint8_t bytesEachRead          = handle->bytesEachRead;
1427     bool isByteSwap                = handle->isByteSwap;
1428     uint32_t readRegRemainingTimes = handle->readRegRemainingTimes;
1429 
1430     if (handle->rxData != NULL)
1431     {
1432         if (handle->rxRemainingByteCount != 0U)
1433         {
1434             /* First, disable the interrupts to avoid potentially triggering another interrupt
1435              * while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll
1436              * re-enable the interrupts based on the LPSPI state after reading out the FIFO.
1437              */
1438             LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable);
1439 
1440             while ((LPSPI_GetRxFifoCount(base) != 0U) && (handle->rxRemainingByteCount != 0U))
1441             {
1442                 /*Read out the data*/
1443                 readData = LPSPI_ReadData(base);
1444 
1445                 /*Decrease the read RX register times.*/
1446                 --handle->readRegRemainingTimes;
1447                 readRegRemainingTimes = handle->readRegRemainingTimes;
1448 
1449                 if (handle->rxRemainingByteCount < (size_t)bytesEachRead)
1450                 {
1451                     handle->bytesEachRead = (uint8_t)(handle->rxRemainingByteCount);
1452                     bytesEachRead         = handle->bytesEachRead;
1453                 }
1454 
1455                 LPSPI_SeparateReadData(handle->rxData, readData, bytesEachRead, isByteSwap);
1456                 handle->rxData += bytesEachRead;
1457 
1458                 /*Decrease the remaining RX byte count.*/
1459                 handle->rxRemainingByteCount -= (size_t)bytesEachRead;
1460             }
1461 
1462             /* Re-enable the interrupts only if rxCount indicates there is more data to receive,
1463              * else we may get a spurious interrupt.
1464              * */
1465             if (handle->rxRemainingByteCount != 0U)
1466             {
1467                 /* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */
1468                 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable);
1469             }
1470         }
1471 
1472         /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1473          *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1474          */
1475         if (readRegRemainingTimes <= (uint32_t)handle->rxWatermark)
1476         {
1477             base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
1478                         LPSPI_FCR_RXWATER((readRegRemainingTimes > 1U) ? (readRegRemainingTimes - 1U) : (0U));
1479         }
1480     }
1481 
1482     if (handle->txRemainingByteCount != 0U)
1483     {
1484         if (handle->isTxMask)
1485         {
1486             /* When TCR[TXMSK]=1, transfer is initiate by writting a new command word to TCR. TCR[TXMSK] is cleared by
1487                hardware every time when TCR[FRAMESZ] bit of data is transfered.
1488                In this case TCR[TXMSK] should be set to initiate each transfer. */
1489             base->TCR |= LPSPI_TCR_TXMSK_MASK;
1490             if ((handle->txRemainingByteCount == (uint32_t)handle->bytesPerFrame) && (handle->isPcsContinuous))
1491             {
1492                 /* For the last piece of frame size of data, if is PCS continous mode(TCR[CONT]), TCR[CONTC] should
1493                  * be cleared to de-assert the PCS. Be sure to clear the TXMSK as well otherwise another FRAMESZ
1494                  * of data will be received. */
1495                 base->TCR &= ~(LPSPI_TCR_CONTC_MASK | LPSPI_TCR_CONT_MASK | LPSPI_TCR_TXMSK_MASK);
1496             }
1497             handle->txRemainingByteCount -= (uint32_t)handle->bytesPerFrame;
1498         }
1499         else
1500         {
1501             LPSPI_MasterTransferFillUpTxFifo(base, handle);
1502         }
1503     }
1504     else
1505     {
1506         if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)))
1507         {
1508             if ((handle->isPcsContinuous) && (handle->writeTcrInIsr) && (!handle->isTxMask))
1509             {
1510                 base->TCR             = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
1511                 handle->writeTcrInIsr = false;
1512             }
1513         }
1514     }
1515 
1516     if ((handle->txRemainingByteCount == 0U) && (handle->rxRemainingByteCount == 0U) && (!handle->writeTcrInIsr))
1517     {
1518         /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
1519         if (handle->rxData == NULL)
1520         {
1521             if ((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransferCompleteFlag) != 0U)
1522             {
1523                 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_TransferCompleteFlag);
1524                 /* Complete the transfer and disable the interrupts */
1525                 LPSPI_MasterTransferComplete(base, handle);
1526             }
1527             else
1528             {
1529                 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TransferCompleteInterruptEnable);
1530                 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable | (uint32_t)kLPSPI_RxInterruptEnable);
1531             }
1532         }
1533         else
1534         {
1535             /* Complete the transfer and disable the interrupts */
1536             LPSPI_MasterTransferComplete(base, handle);
1537         }
1538     }
1539 }
1540 
1541 /*Transactional APIs -- Slave*/
1542 /*!
1543  * brief Initializes the LPSPI slave handle.
1544  *
1545  * This function initializes the LPSPI handle, which can be used for other LPSPI transactional APIs.  Usually, for a
1546  * specified LPSPI instance, call this API once to get the initialized handle.
1547  *
1548  * param base LPSPI peripheral address.
1549  * param handle LPSPI handle pointer to lpspi_slave_handle_t.
1550  * param callback DSPI callback.
1551  * param userData callback function parameter.
1552  */
LPSPI_SlaveTransferCreateHandle(LPSPI_Type * base,lpspi_slave_handle_t * handle,lpspi_slave_transfer_callback_t callback,void * userData)1553 void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base,
1554                                      lpspi_slave_handle_t *handle,
1555                                      lpspi_slave_transfer_callback_t callback,
1556                                      void *userData)
1557 {
1558     assert(handle != NULL);
1559 
1560     /* Zero the handle. */
1561     (void)memset(handle, 0, sizeof(*handle));
1562 
1563     s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
1564 
1565     /* Set irq handler. */
1566     s_lpspiSlaveIsr = LPSPI_SlaveTransferHandleIRQ;
1567 
1568     handle->callback = callback;
1569     handle->userData = userData;
1570 }
1571 
1572 /*!
1573  * brief LPSPI slave transfer data using an interrupt method.
1574  *
1575  * This function transfer data using an interrupt method. This is a non-blocking function, which returns right away.
1576  * When all data is transferred, the callback function is called.
1577  *
1578  * Note:
1579  * The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4.
1580  * For bytesPerFrame greater than 4:
1581  * The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
1582  * Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
1583  *
1584  * param base LPSPI peripheral address.
1585  * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
1586  * param transfer pointer to lpspi_transfer_t structure.
1587  * return status of status_t.
1588  */
LPSPI_SlaveTransferNonBlocking(LPSPI_Type * base,lpspi_slave_handle_t * handle,lpspi_transfer_t * transfer)1589 status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer)
1590 {
1591     assert(handle != NULL);
1592     assert(transfer != NULL);
1593 
1594     /* Check that we're not busy.*/
1595     if (handle->state == (uint8_t)kLPSPI_Busy)
1596     {
1597         return kStatus_LPSPI_Busy;
1598     }
1599     LPSPI_Enable(base, false);
1600     /* Check arguements */
1601     if (!LPSPI_CheckTransferArgument(base, transfer, false))
1602     {
1603         return kStatus_InvalidArgument;
1604     }
1605 
1606     /* Flush FIFO, clear status, disable all the inerrupts. */
1607     LPSPI_FlushFifo(base, true, true);
1608     LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_AllStatusFlag);
1609     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1610 
1611     /* Variables */
1612     bool isRxMask = false;
1613     bool isTxMask = false;
1614     uint8_t txWatermark;
1615     uint32_t readRegRemainingTimes;
1616     uint32_t whichPcs      = (transfer->configFlags & LPSPI_SLAVE_PCS_MASK) >> LPSPI_SLAVE_PCS_SHIFT;
1617     uint32_t bytesPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) / 8U + 1U;
1618 
1619     /* Assign the original value for members of transfer handle. */
1620     handle->state                  = (uint8_t)kLPSPI_Busy;
1621     handle->txData                 = transfer->txData;
1622     handle->rxData                 = transfer->rxData;
1623     handle->txRemainingByteCount   = transfer->dataSize;
1624     handle->rxRemainingByteCount   = transfer->dataSize;
1625     handle->totalByteCount         = transfer->dataSize;
1626     handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3U) / 4U);
1627     handle->readRegRemainingTimes  = handle->writeRegRemainingTimes;
1628     /*The TX and RX FIFO sizes are always the same*/
1629     handle->fifoSize   = LPSPI_GetRxFifoSize(base);
1630     handle->isByteSwap = ((transfer->configFlags & (uint32_t)kLPSPI_SlaveByteSwap) != 0U);
1631     /*Calculate the bytes for write/read the TX/RX register each time*/
1632     if (bytesPerFrame <= 4U)
1633     {
1634         handle->bytesEachWrite = (uint8_t)bytesPerFrame;
1635         handle->bytesEachRead  = (uint8_t)bytesPerFrame;
1636     }
1637     else
1638     {
1639         handle->bytesEachWrite = 4U;
1640         handle->bytesEachRead  = 4U;
1641     }
1642     /* Set proper RX and TX watermarks to reduce the ISR response times. */
1643     if (handle->fifoSize > 1U)
1644     {
1645         txWatermark         = 1U;
1646         handle->rxWatermark = handle->fifoSize - 2U;
1647     }
1648     else
1649     {
1650         txWatermark         = 0U;
1651         handle->rxWatermark = 0U;
1652     }
1653     LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
1654 
1655     /* If there is no rxData, mask the receive data so that receive data is not stored in receive FIFO. */
1656     if (handle->rxData == NULL)
1657     {
1658         isRxMask                     = true;
1659         handle->rxRemainingByteCount = 0U;
1660     }
1661     /* If there is no txData, mask the transmit data so that no data is loaded from transmit FIFO and output pin
1662      * is tristated. */
1663     if (handle->txData == NULL)
1664     {
1665         isTxMask                     = true;
1666         handle->txRemainingByteCount = 0U;
1667     }
1668 
1669     /* Enable module for following configuration of TCR to take effect. */
1670     LPSPI_Enable(base, true);
1671 
1672     base->TCR = (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK |
1673                                LPSPI_TCR_TXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
1674                 LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_TXMSK(isTxMask) | LPSPI_TCR_PCS(whichPcs);
1675 
1676     /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
1677      * and you should also enable the INTMUX interupt in your application.
1678      */
1679     (void)EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
1680 
1681     /*TCR is also shared the FIFO, so wait for TCR written.*/
1682     if (!LPSPI_TxFifoReady(base))
1683     {
1684         return kStatus_LPSPI_Timeout;
1685     }
1686 
1687     /* Fill up the TX data in FIFO */
1688     if (handle->txData != NULL)
1689     {
1690         LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1691     }
1692 
1693     /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
1694      * The IRQ handler will get the status of RX and TX interrupt flags.
1695      */
1696     if (handle->rxData != NULL)
1697     {
1698         /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1699          *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1700          */
1701         readRegRemainingTimes = handle->readRegRemainingTimes;
1702         if (readRegRemainingTimes <= (uint32_t)handle->rxWatermark)
1703         {
1704             base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(readRegRemainingTimes - 1U);
1705         }
1706 
1707         /* RX request and FIFO overflow request enable */
1708         LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_RxInterruptEnable | (uint32_t)kLPSPI_ReceiveErrorInterruptEnable);
1709     }
1710     else
1711     {
1712         LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable);
1713     }
1714 
1715     if (handle->txData != NULL)
1716     {
1717         /* TX FIFO underflow request enable */
1718         LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_TransmitErrorInterruptEnable);
1719     }
1720 
1721     return kStatus_Success;
1722 }
1723 
LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type * base,lpspi_slave_handle_t * handle)1724 static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1725 {
1726     assert(handle != NULL);
1727 
1728     uint32_t wordToSend    = 0U;
1729     uint8_t bytesEachWrite = handle->bytesEachWrite;
1730     bool isByteSwap        = handle->isByteSwap;
1731 
1732     while (LPSPI_GetTxFifoCount(base) < (handle->fifoSize))
1733     {
1734         if (handle->txRemainingByteCount < (size_t)bytesEachWrite)
1735         {
1736             handle->bytesEachWrite = (uint8_t)handle->txRemainingByteCount;
1737             bytesEachWrite         = handle->bytesEachWrite;
1738         }
1739 
1740         wordToSend = LPSPI_CombineWriteData(handle->txData, bytesEachWrite, isByteSwap);
1741         handle->txData += bytesEachWrite;
1742 
1743         /*Decrease the remaining TX byte count.*/
1744         handle->txRemainingByteCount -= (size_t)bytesEachWrite;
1745 
1746         /*Write the word to TX register*/
1747         LPSPI_WriteData(base, wordToSend);
1748 
1749         if (handle->txRemainingByteCount == 0U)
1750         {
1751             break;
1752         }
1753     }
1754 }
1755 
LPSPI_SlaveTransferComplete(LPSPI_Type * base,lpspi_slave_handle_t * handle)1756 static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1757 {
1758     assert(handle != NULL);
1759 
1760     status_t status = kStatus_Success;
1761 
1762     /* Disable interrupt requests*/
1763     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_AllInterruptEnable);
1764 
1765     if (handle->state == (uint8_t)kLPSPI_Error)
1766     {
1767         status = kStatus_LPSPI_Error;
1768     }
1769     else
1770     {
1771         status = kStatus_Success;
1772     }
1773 
1774     handle->state = (uint8_t)kLPSPI_Idle;
1775 
1776     if (handle->callback != NULL)
1777     {
1778         handle->callback(base, handle, status, handle->userData);
1779     }
1780 }
1781 
1782 /*!
1783  * brief Gets the slave transfer remaining bytes.
1784  *
1785  * This function gets the slave transfer remaining bytes.
1786  *
1787  * param base LPSPI peripheral address.
1788  * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
1789  * param count Number of bytes transferred so far by the non-blocking transaction.
1790  * return status of status_t.
1791  */
LPSPI_SlaveTransferGetCount(LPSPI_Type * base,lpspi_slave_handle_t * handle,size_t * count)1792 status_t LPSPI_SlaveTransferGetCount(LPSPI_Type *base, lpspi_slave_handle_t *handle, size_t *count)
1793 {
1794     assert(handle != NULL);
1795 
1796     if (NULL == count)
1797     {
1798         return kStatus_InvalidArgument;
1799     }
1800 
1801     /* Catch when there is not an active transfer. */
1802     if (handle->state != (uint8_t)kLPSPI_Busy)
1803     {
1804         *count = 0;
1805         return kStatus_NoTransferInProgress;
1806     }
1807 
1808     size_t remainingByte;
1809 
1810     if (handle->rxData != NULL)
1811     {
1812         remainingByte = handle->rxRemainingByteCount;
1813     }
1814     else
1815     {
1816         remainingByte = handle->txRemainingByteCount;
1817     }
1818 
1819     *count = handle->totalByteCount - remainingByte;
1820 
1821     return kStatus_Success;
1822 }
1823 
1824 /*!
1825  * brief LPSPI slave aborts a transfer which uses an interrupt method.
1826  *
1827  * This function aborts a transfer which uses an interrupt method.
1828  *
1829  * param base LPSPI peripheral address.
1830  * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
1831  */
LPSPI_SlaveTransferAbort(LPSPI_Type * base,lpspi_slave_handle_t * handle)1832 void LPSPI_SlaveTransferAbort(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1833 {
1834     assert(handle != NULL);
1835 
1836     /* Disable interrupt requests*/
1837     LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable | (uint32_t)kLPSPI_RxInterruptEnable);
1838 
1839     LPSPI_Reset(base);
1840 
1841     handle->state                = (uint8_t)kLPSPI_Idle;
1842     handle->txRemainingByteCount = 0U;
1843     handle->rxRemainingByteCount = 0U;
1844 }
1845 
1846 /*!
1847  * brief LPSPI Slave IRQ handler function.
1848  *
1849  * This function processes the LPSPI transmit and receives an IRQ.
1850  *
1851  * param base LPSPI peripheral address.
1852  * param handle pointer to lpspi_slave_handle_t structure which stores the transfer state.
1853  */
LPSPI_SlaveTransferHandleIRQ(LPSPI_Type * base,lpspi_slave_handle_t * handle)1854 void LPSPI_SlaveTransferHandleIRQ(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1855 {
1856     assert(handle != NULL);
1857 
1858     uint32_t readData; /* variable to store word read from RX FIFO */
1859     uint8_t bytesEachRead = handle->bytesEachRead;
1860     bool isByteSwap       = handle->isByteSwap;
1861     uint32_t readRegRemainingTimes;
1862 
1863     if (handle->rxData != NULL)
1864     {
1865         if (handle->rxRemainingByteCount > 0U)
1866         {
1867             while (LPSPI_GetRxFifoCount(base) != 0U)
1868             {
1869                 /*Read out the data*/
1870                 readData = LPSPI_ReadData(base);
1871 
1872                 /*Decrease the read RX register times.*/
1873                 --handle->readRegRemainingTimes;
1874 
1875                 if (handle->rxRemainingByteCount < (size_t)bytesEachRead)
1876                 {
1877                     handle->bytesEachRead = (uint8_t)handle->rxRemainingByteCount;
1878                     bytesEachRead         = handle->bytesEachRead;
1879                 }
1880 
1881                 LPSPI_SeparateReadData(handle->rxData, readData, bytesEachRead, isByteSwap);
1882                 handle->rxData += bytesEachRead;
1883 
1884                 /*Decrease the remaining RX byte count.*/
1885                 handle->rxRemainingByteCount -= (size_t)bytesEachRead;
1886 
1887                 if ((handle->txRemainingByteCount > 0U) && (handle->txData != NULL))
1888                 {
1889                     LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1890                 }
1891 
1892                 if (handle->rxRemainingByteCount == 0U)
1893                 {
1894                     break;
1895                 }
1896             }
1897         }
1898 
1899         /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1900          *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1901          */
1902         readRegRemainingTimes = handle->readRegRemainingTimes;
1903         if (readRegRemainingTimes <= (uint32_t)handle->rxWatermark)
1904         {
1905             base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
1906                         LPSPI_FCR_RXWATER((readRegRemainingTimes > 1U) ? (readRegRemainingTimes - 1U) : (0U));
1907         }
1908     }
1909     if ((handle->rxData == NULL) && (handle->txRemainingByteCount != 0U) && (handle->txData != NULL))
1910     {
1911         LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1912     }
1913 
1914     if ((handle->txRemainingByteCount == 0U) && (handle->rxRemainingByteCount == 0U))
1915     {
1916         /* If no RX buffer, then transfer is not complete until transfer complete flag sets and the TX FIFO empty*/
1917         if (handle->rxData == NULL)
1918         {
1919             if (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_FrameCompleteFlag) != 0U) &&
1920                 (LPSPI_GetTxFifoCount(base) == 0U))
1921             {
1922                 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_FrameCompleteFlag);
1923                 /* Complete the transfer and disable the interrupts */
1924                 LPSPI_SlaveTransferComplete(base, handle);
1925             }
1926             else
1927             {
1928                 LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_FrameCompleteFlag);
1929                 LPSPI_EnableInterrupts(base, (uint32_t)kLPSPI_FrameCompleteInterruptEnable);
1930                 LPSPI_DisableInterrupts(base, (uint32_t)kLPSPI_TxInterruptEnable | (uint32_t)kLPSPI_RxInterruptEnable);
1931             }
1932         }
1933         else
1934         {
1935             /* Complete the transfer and disable the interrupts */
1936             LPSPI_SlaveTransferComplete(base, handle);
1937         }
1938     }
1939 
1940     /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */
1941     if (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_TransmitErrorFlag) != 0U) &&
1942         ((base->IER & LPSPI_IER_TEIE_MASK) != 0U))
1943     {
1944         LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_TransmitErrorFlag);
1945         /* Change state to error and clear flag */
1946         if (handle->txData != NULL)
1947         {
1948             handle->state = (uint8_t)kLPSPI_Error;
1949         }
1950         handle->errorCount++;
1951     }
1952     /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */
1953     if (((LPSPI_GetStatusFlags(base) & (uint32_t)kLPSPI_ReceiveErrorFlag) != 0U) &&
1954         ((base->IER & LPSPI_IER_REIE_MASK) != 0U))
1955     {
1956         LPSPI_ClearStatusFlags(base, (uint32_t)kLPSPI_ReceiveErrorFlag);
1957         /* Change state to error and clear flag */
1958         if (handle->txData != NULL)
1959         {
1960             handle->state = (uint8_t)kLPSPI_Error;
1961         }
1962         handle->errorCount++;
1963     }
1964 }
1965 
LPSPI_CombineWriteData(uint8_t * txData,uint8_t bytesEachWrite,bool isByteSwap)1966 static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint8_t bytesEachWrite, bool isByteSwap)
1967 {
1968     assert(txData != NULL);
1969 
1970     uint32_t wordToSend = 0U;
1971 
1972     switch (bytesEachWrite)
1973     {
1974         case 1:
1975             wordToSend = *txData;
1976             ++txData;
1977             break;
1978 
1979         case 2:
1980             if (!isByteSwap)
1981             {
1982                 wordToSend = *txData;
1983                 ++txData;
1984                 wordToSend |= (unsigned)(*txData) << 8U;
1985                 ++txData;
1986             }
1987             else
1988             {
1989                 wordToSend = (unsigned)(*txData) << 8U;
1990                 ++txData;
1991                 wordToSend |= *txData;
1992                 ++txData;
1993             }
1994 
1995             break;
1996 
1997         case 3:
1998             if (!isByteSwap)
1999             {
2000                 wordToSend = *txData;
2001                 ++txData;
2002                 wordToSend |= (unsigned)(*txData) << 8U;
2003                 ++txData;
2004                 wordToSend |= (unsigned)(*txData) << 16U;
2005                 ++txData;
2006             }
2007             else
2008             {
2009                 wordToSend = (unsigned)(*txData) << 16U;
2010                 ++txData;
2011                 wordToSend |= (unsigned)(*txData) << 8U;
2012                 ++txData;
2013                 wordToSend |= *txData;
2014                 ++txData;
2015             }
2016             break;
2017 
2018         case 4:
2019             if (!isByteSwap)
2020             {
2021                 wordToSend = *txData;
2022                 ++txData;
2023                 wordToSend |= (unsigned)(*txData) << 8U;
2024                 ++txData;
2025                 wordToSend |= (unsigned)(*txData) << 16U;
2026                 ++txData;
2027                 wordToSend |= (unsigned)(*txData) << 24U;
2028                 ++txData;
2029             }
2030             else
2031             {
2032                 wordToSend = (unsigned)(*txData) << 24U;
2033                 ++txData;
2034                 wordToSend |= (unsigned)(*txData) << 16U;
2035                 ++txData;
2036                 wordToSend |= (unsigned)(*txData) << 8U;
2037                 ++txData;
2038                 wordToSend |= *txData;
2039                 ++txData;
2040             }
2041             break;
2042 
2043         default:
2044             assert(false);
2045             break;
2046     }
2047     return wordToSend;
2048 }
2049 
LPSPI_SeparateReadData(uint8_t * rxData,uint32_t readData,uint8_t bytesEachRead,bool isByteSwap)2050 static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint8_t bytesEachRead, bool isByteSwap)
2051 {
2052     assert(rxData != NULL);
2053 
2054     switch (bytesEachRead)
2055     {
2056         case 1:
2057             *rxData = (uint8_t)readData;
2058             ++rxData;
2059             break;
2060 
2061         case 2:
2062             if (!isByteSwap)
2063             {
2064                 *rxData = (uint8_t)readData;
2065                 ++rxData;
2066                 *rxData = (uint8_t)(readData >> 8);
2067                 ++rxData;
2068             }
2069             else
2070             {
2071                 *rxData = (uint8_t)(readData >> 8);
2072                 ++rxData;
2073                 *rxData = (uint8_t)readData;
2074                 ++rxData;
2075             }
2076             break;
2077 
2078         case 3:
2079             if (!isByteSwap)
2080             {
2081                 *rxData = (uint8_t)readData;
2082                 ++rxData;
2083                 *rxData = (uint8_t)(readData >> 8);
2084                 ++rxData;
2085                 *rxData = (uint8_t)(readData >> 16);
2086                 ++rxData;
2087             }
2088             else
2089             {
2090                 *rxData = (uint8_t)(readData >> 16);
2091                 ++rxData;
2092                 *rxData = (uint8_t)(readData >> 8);
2093                 ++rxData;
2094                 *rxData = (uint8_t)readData;
2095                 ++rxData;
2096             }
2097             break;
2098 
2099         case 4:
2100             if (!isByteSwap)
2101             {
2102                 *rxData = (uint8_t)readData;
2103                 ++rxData;
2104                 *rxData = (uint8_t)(readData >> 8);
2105                 ++rxData;
2106                 *rxData = (uint8_t)(readData >> 16);
2107                 ++rxData;
2108                 *rxData = (uint8_t)(readData >> 24);
2109                 ++rxData;
2110             }
2111             else
2112             {
2113                 *rxData = (uint8_t)(readData >> 24);
2114                 ++rxData;
2115                 *rxData = (uint8_t)(readData >> 16);
2116                 ++rxData;
2117                 *rxData = (uint8_t)(readData >> 8);
2118                 ++rxData;
2119                 *rxData = (uint8_t)readData;
2120                 ++rxData;
2121             }
2122             break;
2123 
2124         default:
2125             assert(false);
2126             break;
2127     }
2128 }
2129 
LPSPI_TxFifoReady(LPSPI_Type * base)2130 static bool LPSPI_TxFifoReady(LPSPI_Type *base)
2131 {
2132 #if SPI_RETRY_TIMES
2133     uint32_t waitTimes = SPI_RETRY_TIMES;
2134     while (((uint8_t)LPSPI_GetTxFifoCount(base) != 0U) && (--waitTimes != 0U))
2135 #else
2136     while ((uint8_t)LPSPI_GetTxFifoCount(base) != 0U)
2137 #endif
2138     {
2139     }
2140 #if SPI_RETRY_TIMES
2141     if (waitTimes == 0U)
2142     {
2143         return false;
2144     }
2145 #endif
2146     return true;
2147 }
2148 
LPSPI_CommonIRQHandler(LPSPI_Type * base,void * param)2149 static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param)
2150 {
2151     if (LPSPI_IsMaster(base))
2152     {
2153         s_lpspiMasterIsr(base, (lpspi_master_handle_t *)param);
2154     }
2155     else
2156     {
2157         s_lpspiSlaveIsr(base, (lpspi_slave_handle_t *)param);
2158     }
2159     SDK_ISR_EXIT_BARRIER;
2160 }
2161 
2162 #if defined(LPSPI0)
2163 void LPSPI0_DriverIRQHandler(void);
LPSPI0_DriverIRQHandler(void)2164 void LPSPI0_DriverIRQHandler(void)
2165 {
2166     assert(s_lpspiHandle[0] != NULL);
2167     LPSPI_CommonIRQHandler(LPSPI0, s_lpspiHandle[0]);
2168 }
2169 #endif
2170 
2171 #if defined(LPSPI1)
2172 void LPSPI1_DriverIRQHandler(void);
LPSPI1_DriverIRQHandler(void)2173 void LPSPI1_DriverIRQHandler(void)
2174 {
2175     assert(s_lpspiHandle[1] != NULL);
2176     LPSPI_CommonIRQHandler(LPSPI1, s_lpspiHandle[1]);
2177 }
2178 #endif
2179 
2180 #if defined(LPSPI2)
2181 void LPSPI2_DriverIRQHandler(void);
LPSPI2_DriverIRQHandler(void)2182 void LPSPI2_DriverIRQHandler(void)
2183 {
2184     assert(s_lpspiHandle[2] != NULL);
2185     LPSPI_CommonIRQHandler(LPSPI2, s_lpspiHandle[2]);
2186 }
2187 #endif
2188 
2189 #if defined(LPSPI3)
2190 void LPSPI3_DriverIRQHandler(void);
LPSPI3_DriverIRQHandler(void)2191 void LPSPI3_DriverIRQHandler(void)
2192 {
2193     assert(s_lpspiHandle[3] != NULL);
2194     LPSPI_CommonIRQHandler(LPSPI3, s_lpspiHandle[3]);
2195 }
2196 #endif
2197 
2198 #if defined(LPSPI4)
2199 void LPSPI4_DriverIRQHandler(void);
LPSPI4_DriverIRQHandler(void)2200 void LPSPI4_DriverIRQHandler(void)
2201 {
2202     assert(s_lpspiHandle[4] != NULL);
2203     LPSPI_CommonIRQHandler(LPSPI4, s_lpspiHandle[4]);
2204 }
2205 #endif
2206 
2207 #if defined(LPSPI5)
2208 void LPSPI5_DriverIRQHandler(void);
LPSPI5_DriverIRQHandler(void)2209 void LPSPI5_DriverIRQHandler(void)
2210 {
2211     assert(s_lpspiHandle[5] != NULL);
2212     LPSPI_CommonIRQHandler(LPSPI5, s_lpspiHandle[5]);
2213 }
2214 #endif
2215 
2216 #if defined(DMA__LPSPI0)
2217 void DMA_SPI0_INT_DriverIRQHandler(void);
DMA_SPI0_INT_DriverIRQHandler(void)2218 void DMA_SPI0_INT_DriverIRQHandler(void)
2219 {
2220     assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI0)] != NULL);
2221     LPSPI_CommonIRQHandler(DMA__LPSPI0, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI0)]);
2222 }
2223 #endif
2224 
2225 #if defined(DMA__LPSPI1)
2226 void DMA_SPI1_INT_DriverIRQHandler(void);
DMA_SPI1_INT_DriverIRQHandler(void)2227 void DMA_SPI1_INT_DriverIRQHandler(void)
2228 {
2229     assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI1)] != NULL);
2230     LPSPI_CommonIRQHandler(DMA__LPSPI1, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI1)]);
2231 }
2232 #endif
2233 #if defined(DMA__LPSPI2)
2234 void DMA_SPI2_INT_DriverIRQHandler(void);
DMA_SPI2_INT_DriverIRQHandler(void)2235 void DMA_SPI2_INT_DriverIRQHandler(void)
2236 {
2237     assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI2)] != NULL);
2238     LPSPI_CommonIRQHandler(DMA__LPSPI2, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI2)]);
2239 }
2240 #endif
2241 
2242 #if defined(DMA__LPSPI3)
2243 void DMA_SPI3_INT_DriverIRQHandler(void);
DMA_SPI3_INT_DriverIRQHandler(void)2244 void DMA_SPI3_INT_DriverIRQHandler(void)
2245 {
2246     assert(s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI3)] != NULL);
2247     LPSPI_CommonIRQHandler(DMA__LPSPI3, s_lpspiHandle[LPSPI_GetInstance(DMA__LPSPI3)]);
2248 }
2249 #endif
2250 
2251 #if defined(ADMA__LPSPI0)
2252 void ADMA_SPI0_INT_DriverIRQHandler(void);
ADMA_SPI0_INT_DriverIRQHandler(void)2253 void ADMA_SPI0_INT_DriverIRQHandler(void)
2254 {
2255     assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI0)] != NULL);
2256     LPSPI_CommonIRQHandler(ADMA__LPSPI0, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI0)]);
2257 }
2258 #endif
2259 
2260 #if defined(ADMA__LPSPI1)
2261 void ADMA_SPI1_INT_DriverIRQHandler(void);
ADMA_SPI1_INT_DriverIRQHandler(void)2262 void ADMA_SPI1_INT_DriverIRQHandler(void)
2263 {
2264     assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI1)] != NULL);
2265     LPSPI_CommonIRQHandler(ADMA__LPSPI1, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI1)]);
2266 }
2267 #endif
2268 #if defined(ADMA__LPSPI2)
2269 void ADMA_SPI2_INT_DriverIRQHandler(void);
ADMA_SPI2_INT_DriverIRQHandler(void)2270 void ADMA_SPI2_INT_DriverIRQHandler(void)
2271 {
2272     assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI2)] != NULL);
2273     LPSPI_CommonIRQHandler(ADMA__LPSPI2, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI2)]);
2274 }
2275 #endif
2276 
2277 #if defined(ADMA__LPSPI3)
2278 void ADMA_SPI3_INT_DriverIRQHandler(void);
ADMA_SPI3_INT_DriverIRQHandler(void)2279 void ADMA_SPI3_INT_DriverIRQHandler(void)
2280 {
2281     assert(s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI3)] != NULL);
2282     LPSPI_CommonIRQHandler(ADMA__LPSPI3, s_lpspiHandle[LPSPI_GetInstance(ADMA__LPSPI3)]);
2283 }
2284 #endif
2285