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