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