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