1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 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 * @brief Default watermark values.
16 *
17 * The default watermarks are set to zero.
18 */
19 enum _lpspi_default_watermarks
20 {
21 kLpspiDefaultTxWatermark = 0,
22 kLpspiDefaultRxWatermark = 0,
23 };
24
25 /*! @brief Typedef for master interrupt handler. */
26 typedef void (*lpspi_master_isr_t)(LPSPI_Type *base, lpspi_master_handle_t *handle);
27
28 /*! @brief Typedef for slave interrupt handler. */
29 typedef void (*lpspi_slave_isr_t)(LPSPI_Type *base, lpspi_slave_handle_t *handle);
30
31 /*******************************************************************************
32 * Prototypes
33 ******************************************************************************/
34 /*!
35 * @brief Get instance number for LPSPI module.
36 *
37 * @param base LPSPI peripheral base address.
38 */
39 uint32_t LPSPI_GetInstance(LPSPI_Type *base);
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, uint32_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, uint32_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 Check the argument for transfer .
97 * This is not a public API. Not static because lpspi_edma.c will use this API.
98 */
99 bool LPSPI_CheckTransferArgument(lpspi_transfer_t *transfer, uint32_t bitsPerFrame, uint32_t bytesPerFrame);
100
101 /*!
102 * @brief LPSPI common interrupt handler.
103 *
104 * @param handle pointer to s_lpspiHandle which stores the transfer state.
105 */
106 static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param);
107
108 /*******************************************************************************
109 * Variables
110 ******************************************************************************/
111
112 /* Defines constant value arrays for the baud rate pre-scalar and scalar divider values.*/
113 static const uint8_t s_baudratePrescaler[] = {1, 2, 4, 8, 16, 32, 64, 128};
114
115 /*! @brief Pointers to lpspi bases for each instance. */
116 static LPSPI_Type *const s_lpspiBases[] = LPSPI_BASE_PTRS;
117
118 /*! @brief Pointers to lpspi IRQ number for each instance. */
119 static const IRQn_Type s_lpspiIRQ[] = LPSPI_IRQS;
120
121 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
122 /*! @brief Pointers to lpspi clocks for each instance. */
123 static const clock_ip_name_t s_lpspiClocks[] = LPSPI_CLOCKS;
124
125 #if defined(LPSPI_PERIPH_CLOCKS)
126 static const clock_ip_name_t s_LpspiPeriphClocks[] = LPSPI_PERIPH_CLOCKS;
127 #endif
128
129 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
130
131 /*! @brief Pointers to lpspi handles for each instance. */
132 static void *s_lpspiHandle[FSL_FEATURE_SOC_LPSPI_COUNT] = {NULL};
133
134 /*! @brief Pointer to master IRQ handler for each instance. */
135 static lpspi_master_isr_t s_lpspiMasterIsr;
136 /*! @brief Pointer to slave IRQ handler for each instance. */
137 static lpspi_slave_isr_t s_lpspiSlaveIsr;
138 /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
139 volatile uint8_t s_dummyData[ARRAY_SIZE(s_lpspiBases)] = {0};
140 /**********************************************************************************************************************
141 * Code
142 *********************************************************************************************************************/
LPSPI_GetInstance(LPSPI_Type * base)143 uint32_t LPSPI_GetInstance(LPSPI_Type *base)
144 {
145 uint8_t instance = 0;
146
147 /* Find the instance index from base address mappings. */
148 for (instance = 0; instance < ARRAY_SIZE(s_lpspiBases); instance++)
149 {
150 if (s_lpspiBases[instance] == base)
151 {
152 break;
153 }
154 }
155
156 assert(instance < ARRAY_SIZE(s_lpspiBases));
157
158 return instance;
159 }
160
LPSPI_SetDummyData(LPSPI_Type * base,uint8_t dummyData)161 void LPSPI_SetDummyData(LPSPI_Type *base, uint8_t dummyData)
162 {
163 uint32_t instance = LPSPI_GetInstance(base);
164 s_dummyData[instance] = dummyData;
165 }
166
LPSPI_MasterInit(LPSPI_Type * base,const lpspi_master_config_t * masterConfig,uint32_t srcClock_Hz)167 void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz)
168 {
169 assert(masterConfig);
170
171 uint32_t tcrPrescaleValue = 0;
172
173 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
174
175 uint32_t instance = LPSPI_GetInstance(base);
176 /* Enable LPSPI clock */
177 CLOCK_EnableClock(s_lpspiClocks[instance]);
178
179 #if defined(LPSPI_PERIPH_CLOCKS)
180 CLOCK_EnableClock(s_LpspiPeriphClocks[instance]);
181 #endif
182
183 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
184
185 /* Reset to known status */
186 LPSPI_Reset(base);
187
188 /* Set LPSPI to master */
189 LPSPI_SetMasterSlaveMode(base, kLPSPI_Master);
190
191 /* Set specific PCS to active high or low */
192 LPSPI_SetOnePcsPolarity(base, masterConfig->whichPcs, masterConfig->pcsActiveHighOrLow);
193
194 /* Set Configuration Register 1 related setting.*/
195 base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK | LPSPI_CFGR1_NOSTALL_MASK)) |
196 LPSPI_CFGR1_OUTCFG(masterConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(masterConfig->pinCfg) |
197 LPSPI_CFGR1_NOSTALL(0);
198
199 /* Set baudrate and delay times*/
200 LPSPI_MasterSetBaudRate(base, masterConfig->baudRate, srcClock_Hz, &tcrPrescaleValue);
201
202 /* Set default watermarks */
203 LPSPI_SetFifoWatermarks(base, kLpspiDefaultTxWatermark, kLpspiDefaultRxWatermark);
204
205 /* Set Transmit Command Register*/
206 base->TCR = LPSPI_TCR_CPOL(masterConfig->cpol) | LPSPI_TCR_CPHA(masterConfig->cpha) |
207 LPSPI_TCR_LSBF(masterConfig->direction) | LPSPI_TCR_FRAMESZ(masterConfig->bitsPerFrame - 1) |
208 LPSPI_TCR_PRESCALE(tcrPrescaleValue) | LPSPI_TCR_PCS(masterConfig->whichPcs);
209
210 LPSPI_Enable(base, true);
211
212 LPSPI_MasterSetDelayTimes(base, masterConfig->pcsToSckDelayInNanoSec, kLPSPI_PcsToSck, srcClock_Hz);
213 LPSPI_MasterSetDelayTimes(base, masterConfig->lastSckToPcsDelayInNanoSec, kLPSPI_LastSckToPcs, srcClock_Hz);
214 LPSPI_MasterSetDelayTimes(base, masterConfig->betweenTransferDelayInNanoSec, kLPSPI_BetweenTransfer, srcClock_Hz);
215
216 LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA);
217 }
218
LPSPI_MasterGetDefaultConfig(lpspi_master_config_t * masterConfig)219 void LPSPI_MasterGetDefaultConfig(lpspi_master_config_t *masterConfig)
220 {
221 assert(masterConfig);
222
223 masterConfig->baudRate = 500000;
224 masterConfig->bitsPerFrame = 8;
225 masterConfig->cpol = kLPSPI_ClockPolarityActiveHigh;
226 masterConfig->cpha = kLPSPI_ClockPhaseFirstEdge;
227 masterConfig->direction = kLPSPI_MsbFirst;
228
229 masterConfig->pcsToSckDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2;
230 masterConfig->lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2;
231 masterConfig->betweenTransferDelayInNanoSec = 1000000000 / masterConfig->baudRate * 2;
232
233 masterConfig->whichPcs = kLPSPI_Pcs0;
234 masterConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow;
235
236 masterConfig->pinCfg = kLPSPI_SdiInSdoOut;
237 masterConfig->dataOutConfig = kLpspiDataOutRetained;
238 }
239
LPSPI_SlaveInit(LPSPI_Type * base,const lpspi_slave_config_t * slaveConfig)240 void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig)
241 {
242 assert(slaveConfig);
243
244 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
245
246 uint32_t instance = LPSPI_GetInstance(base);
247 /* Enable LPSPI clock */
248 CLOCK_EnableClock(s_lpspiClocks[instance]);
249
250 #if defined(LPSPI_PERIPH_CLOCKS)
251 CLOCK_EnableClock(s_LpspiPeriphClocks[instance]);
252 #endif
253
254 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
255
256 /* Reset to known status */
257 LPSPI_Reset(base);
258
259 LPSPI_SetMasterSlaveMode(base, kLPSPI_Slave);
260
261 LPSPI_SetOnePcsPolarity(base, slaveConfig->whichPcs, slaveConfig->pcsActiveHighOrLow);
262
263 base->CFGR1 = (base->CFGR1 & ~(LPSPI_CFGR1_OUTCFG_MASK | LPSPI_CFGR1_PINCFG_MASK)) |
264 LPSPI_CFGR1_OUTCFG(slaveConfig->dataOutConfig) | LPSPI_CFGR1_PINCFG(slaveConfig->pinCfg);
265
266 LPSPI_SetFifoWatermarks(base, kLpspiDefaultTxWatermark, kLpspiDefaultRxWatermark);
267
268 base->TCR = LPSPI_TCR_CPOL(slaveConfig->cpol) | LPSPI_TCR_CPHA(slaveConfig->cpha) |
269 LPSPI_TCR_LSBF(slaveConfig->direction) | LPSPI_TCR_FRAMESZ(slaveConfig->bitsPerFrame - 1) | LPSPI_TCR_PCS(slaveConfig->whichPcs);
270
271 /* This operation will set the dummy data for edma transfer, no effect in interrupt way. */
272 LPSPI_SetDummyData(base, LPSPI_DUMMY_DATA);
273
274 LPSPI_Enable(base, true);
275 }
276
LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t * slaveConfig)277 void LPSPI_SlaveGetDefaultConfig(lpspi_slave_config_t *slaveConfig)
278 {
279 assert(slaveConfig);
280
281 slaveConfig->bitsPerFrame = 8; /*!< Bits per frame, minimum 8, maximum 4096.*/
282 slaveConfig->cpol = kLPSPI_ClockPolarityActiveHigh; /*!< Clock polarity. */
283 slaveConfig->cpha = kLPSPI_ClockPhaseFirstEdge; /*!< Clock phase. */
284 slaveConfig->direction = kLPSPI_MsbFirst; /*!< MSB or LSB data shift direction. */
285
286 slaveConfig->whichPcs = kLPSPI_Pcs0; /*!< Desired Peripheral Chip Select (pcs) */
287 slaveConfig->pcsActiveHighOrLow = kLPSPI_PcsActiveLow; /*!< Desired PCS active high or low */
288
289 slaveConfig->pinCfg = kLPSPI_SdiInSdoOut;
290 slaveConfig->dataOutConfig = kLpspiDataOutRetained;
291 }
292
LPSPI_Reset(LPSPI_Type * base)293 void LPSPI_Reset(LPSPI_Type *base)
294 {
295 /* Reset all internal logic and registers, except the Control Register. Remains set until cleared by software.*/
296 base->CR |= LPSPI_CR_RST_MASK;
297
298 /* Software reset doesn't reset the CR, so manual reset the FIFOs */
299 base->CR |= LPSPI_CR_RRF_MASK | LPSPI_CR_RTF_MASK;
300
301 /* Master logic is not reset and module is disabled.*/
302 base->CR = 0x00U;
303 }
304
LPSPI_Deinit(LPSPI_Type * base)305 void LPSPI_Deinit(LPSPI_Type *base)
306 {
307 /* Reset to default value */
308 LPSPI_Reset(base);
309
310 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
311
312 uint32_t instance = LPSPI_GetInstance(base);
313 /* Enable LPSPI clock */
314 CLOCK_DisableClock(s_lpspiClocks[instance]);
315
316 #if defined(LPSPI_PERIPH_CLOCKS)
317 CLOCK_DisableClock(s_LpspiPeriphClocks[instance]);
318 #endif
319
320 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
321 }
322
LPSPI_SetOnePcsPolarity(LPSPI_Type * base,lpspi_which_pcs_t pcs,lpspi_pcs_polarity_config_t activeLowOrHigh)323 static void LPSPI_SetOnePcsPolarity(LPSPI_Type *base,
324 lpspi_which_pcs_t pcs,
325 lpspi_pcs_polarity_config_t activeLowOrHigh)
326 {
327 uint32_t cfgr1Value = 0;
328 /* Clear the PCS polarity bit */
329 cfgr1Value = base->CFGR1 & ~(1U << (LPSPI_CFGR1_PCSPOL_SHIFT + pcs));
330
331 /* Configure the PCS polarity bit according to the activeLowOrHigh setting */
332 base->CFGR1 = cfgr1Value | ((uint32_t)activeLowOrHigh << (LPSPI_CFGR1_PCSPOL_SHIFT + pcs));
333 }
334
LPSPI_MasterSetBaudRate(LPSPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz,uint32_t * tcrPrescaleValue)335 uint32_t LPSPI_MasterSetBaudRate(LPSPI_Type *base,
336 uint32_t baudRate_Bps,
337 uint32_t srcClock_Hz,
338 uint32_t *tcrPrescaleValue)
339 {
340 assert(tcrPrescaleValue);
341
342 /* For master mode configuration only, if slave mode detected, return 0.
343 * Also, the LPSPI module needs to be disabled first, if enabled, return 0
344 */
345 if ((!LPSPI_IsMaster(base)) || (base->CR & LPSPI_CR_MEN_MASK))
346 {
347 return 0;
348 }
349
350 uint32_t prescaler, bestPrescaler;
351 uint32_t scaler, bestScaler;
352 uint32_t realBaudrate, bestBaudrate;
353 uint32_t diff, min_diff;
354 uint32_t desiredBaudrate = baudRate_Bps;
355
356 /* find combination of prescaler and scaler resulting in baudrate closest to the
357 * requested value
358 */
359 min_diff = 0xFFFFFFFFU;
360
361 /* Set to maximum divisor value bit settings so that if baud rate passed in is less
362 * than the minimum possible baud rate, then the SPI will be configured to the lowest
363 * possible baud rate
364 */
365 bestPrescaler = 7;
366 bestScaler = 255;
367
368 bestBaudrate = 0; /* required to avoid compilation warning */
369
370 /* In all for loops, if min_diff = 0, the exit for loop*/
371 for (prescaler = 0; (prescaler < 8) && min_diff; prescaler++)
372 {
373 for (scaler = 0; (scaler < 256) && min_diff; scaler++)
374 {
375 realBaudrate = (srcClock_Hz / (s_baudratePrescaler[prescaler] * (scaler + 2U)));
376
377 /* calculate the baud rate difference based on the conditional statement
378 * that states that the calculated baud rate must not exceed the desired baud rate
379 */
380 if (desiredBaudrate >= realBaudrate)
381 {
382 diff = desiredBaudrate - realBaudrate;
383 if (min_diff > diff)
384 {
385 /* a better match found */
386 min_diff = diff;
387 bestPrescaler = prescaler;
388 bestScaler = scaler;
389 bestBaudrate = realBaudrate;
390 }
391 }
392 }
393 }
394
395 /* Write the best baud rate scalar to the CCR.
396 * Note, no need to check for error since we've already checked to make sure the module is
397 * disabled and in master mode. Also, there is a limit on the maximum divider so we will not
398 * exceed this.
399 */
400 base->CCR = (base->CCR & ~LPSPI_CCR_SCKDIV_MASK) | LPSPI_CCR_SCKDIV(bestScaler);
401
402 /* return the best prescaler value for user to use later */
403 *tcrPrescaleValue = bestPrescaler;
404
405 /* return the actual calculated baud rate */
406 return bestBaudrate;
407 }
408
LPSPI_MasterSetDelayScaler(LPSPI_Type * base,uint32_t scaler,lpspi_delay_type_t whichDelay)409 void LPSPI_MasterSetDelayScaler(LPSPI_Type *base, uint32_t scaler, lpspi_delay_type_t whichDelay)
410 {
411 /*These settings are only relevant in master mode */
412 switch (whichDelay)
413 {
414 case kLPSPI_PcsToSck:
415 base->CCR = (base->CCR & (~LPSPI_CCR_PCSSCK_MASK)) | LPSPI_CCR_PCSSCK(scaler);
416
417 break;
418 case kLPSPI_LastSckToPcs:
419 base->CCR = (base->CCR & (~LPSPI_CCR_SCKPCS_MASK)) | LPSPI_CCR_SCKPCS(scaler);
420
421 break;
422 case kLPSPI_BetweenTransfer:
423 base->CCR = (base->CCR & (~LPSPI_CCR_DBT_MASK)) | LPSPI_CCR_DBT(scaler);
424
425 break;
426 default:
427 assert(false);
428 break;
429 }
430 }
431
LPSPI_MasterSetDelayTimes(LPSPI_Type * base,uint32_t delayTimeInNanoSec,lpspi_delay_type_t whichDelay,uint32_t srcClock_Hz)432 uint32_t LPSPI_MasterSetDelayTimes(LPSPI_Type *base,
433 uint32_t delayTimeInNanoSec,
434 lpspi_delay_type_t whichDelay,
435 uint32_t srcClock_Hz)
436 {
437 uint64_t realDelay, bestDelay;
438 uint32_t scaler, bestScaler;
439 uint32_t diff, min_diff;
440 uint64_t initialDelayNanoSec;
441 uint32_t clockDividedPrescaler;
442
443 /* For delay between transfer, an additional scaler value is needed */
444 uint32_t additionalScaler = 0;
445
446 /*As the RM note, the LPSPI baud rate clock is itself divided by the PRESCALE setting, which can vary between
447 * transfers.*/
448 clockDividedPrescaler =
449 srcClock_Hz / s_baudratePrescaler[(base->TCR & LPSPI_TCR_PRESCALE_MASK) >> LPSPI_TCR_PRESCALE_SHIFT];
450
451 /* Find combination of prescaler and scaler resulting in the delay closest to the requested value.*/
452 min_diff = 0xFFFFFFFFU;
453
454 /* Initialize scaler to max value to generate the max delay */
455 bestScaler = 0xFFU;
456
457 /* Calculate the initial (min) delay and maximum possible delay based on the specific delay as
458 * the delay divisors are slightly different based on which delay we are configuring.
459 */
460 if (whichDelay == kLPSPI_BetweenTransfer)
461 {
462 /* First calculate the initial, default delay, note min delay is 2 clock cycles. Due to large size of
463 calculated values (uint64_t), we need to break up the calculation into several steps to ensure
464 accurate calculated results
465 */
466 initialDelayNanoSec = 1000000000U;
467 initialDelayNanoSec *= 2U;
468 initialDelayNanoSec /= clockDividedPrescaler;
469
470 /* Calculate the maximum delay */
471 bestDelay = 1000000000U;
472 bestDelay *= 257U; /* based on DBT+2, or 255 + 2 */
473 bestDelay /= clockDividedPrescaler;
474
475 additionalScaler = 1U;
476 }
477 else
478 {
479 /* First calculate the initial, default delay, min delay is 1 clock cycle. Due to large size of calculated
480 values (uint64_t), we need to break up the calculation into several steps to ensure accurate calculated
481 results.
482 */
483 initialDelayNanoSec = 1000000000U;
484 initialDelayNanoSec /= clockDividedPrescaler;
485
486 /* Calculate the maximum delay */
487 bestDelay = 1000000000U;
488 bestDelay *= 256U; /* based on SCKPCS+1 or PCSSCK+1, or 255 + 1 */
489 bestDelay /= clockDividedPrescaler;
490
491 additionalScaler = 0;
492 }
493
494 /* If the initial, default delay is already greater than the desired delay, then
495 * set the delay to their initial value (0) and return the delay. In other words,
496 * there is no way to decrease the delay value further.
497 */
498 if (initialDelayNanoSec >= delayTimeInNanoSec)
499 {
500 LPSPI_MasterSetDelayScaler(base, 0, whichDelay);
501 return initialDelayNanoSec;
502 }
503
504 /* If min_diff = 0, the exit for loop */
505 for (scaler = 0; (scaler < 256U) && min_diff; scaler++)
506 {
507 /* Calculate the real delay value as we cycle through the scaler values.
508 Due to large size of calculated values (uint64_t), we need to break up the
509 calculation into several steps to ensure accurate calculated results
510 */
511 realDelay = 1000000000U;
512 realDelay *= (scaler + 1 + additionalScaler);
513 realDelay /= clockDividedPrescaler;
514
515 /* calculate the delay difference based on the conditional statement
516 * that states that the calculated delay must not be less then the desired delay
517 */
518 if (realDelay >= delayTimeInNanoSec)
519 {
520 diff = realDelay - delayTimeInNanoSec;
521 if (min_diff > diff)
522 {
523 /* a better match found */
524 min_diff = diff;
525 bestScaler = scaler;
526 bestDelay = realDelay;
527 }
528 }
529 }
530
531 /* write the best scaler value for the delay */
532 LPSPI_MasterSetDelayScaler(base, bestScaler, whichDelay);
533
534 /* return the actual calculated delay value (in ns) */
535 return bestDelay;
536 }
537
538 /*Transactional APIs -- Master*/
539
LPSPI_MasterTransferCreateHandle(LPSPI_Type * base,lpspi_master_handle_t * handle,lpspi_master_transfer_callback_t callback,void * userData)540 void LPSPI_MasterTransferCreateHandle(LPSPI_Type *base,
541 lpspi_master_handle_t *handle,
542 lpspi_master_transfer_callback_t callback,
543 void *userData)
544 {
545 assert(handle);
546
547 /* Zero the handle. */
548 memset(handle, 0, sizeof(*handle));
549
550 s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
551
552 /* Set irq handler. */
553 s_lpspiMasterIsr = LPSPI_MasterTransferHandleIRQ;
554
555 handle->callback = callback;
556 handle->userData = userData;
557 }
558
LPSPI_CheckTransferArgument(lpspi_transfer_t * transfer,uint32_t bitsPerFrame,uint32_t bytesPerFrame)559 bool LPSPI_CheckTransferArgument(lpspi_transfer_t *transfer, uint32_t bitsPerFrame, uint32_t bytesPerFrame)
560 {
561 assert(transfer);
562
563 /* If the transfer count is zero, then return immediately.*/
564 if (transfer->dataSize == 0)
565 {
566 return false;
567 }
568
569 /* If both send buffer and receive buffer is null */
570 if ((!(transfer->txData)) && (!(transfer->rxData)))
571 {
572 return false;
573 }
574
575 /*The transfer data size should be integer multiples of bytesPerFrame if bytesPerFrame is less than or equal to 4 .
576 *For bytesPerFrame greater than 4 situation:
577 *the transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not integer multiples of 4 ,
578 *otherwise , the transfer data size can be integer multiples of bytesPerFrame.
579 */
580 if (bytesPerFrame <= 4)
581 {
582 if ((transfer->dataSize % bytesPerFrame) != 0)
583 {
584 return false;
585 }
586 }
587 else
588 {
589 if ((bytesPerFrame % 4U) != 0)
590 {
591 if (transfer->dataSize != bytesPerFrame)
592 {
593 return false;
594 }
595 }
596 else
597 {
598 if ((transfer->dataSize % bytesPerFrame) != 0)
599 {
600 return false;
601 }
602 }
603 }
604
605 return true;
606 }
607
LPSPI_MasterTransferBlocking(LPSPI_Type * base,lpspi_transfer_t * transfer)608 status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer)
609 {
610 assert(transfer);
611
612 uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1;
613 uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8;
614 uint8_t dummyData = s_dummyData[LPSPI_GetInstance(base)];
615
616 if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
617 {
618 return kStatus_InvalidArgument;
619 }
620
621 /* Check that LPSPI is not busy.*/
622 if (LPSPI_GetStatusFlags(base) & kLPSPI_ModuleBusyFlag)
623 {
624 return kStatus_LPSPI_Busy;
625 }
626
627 uint8_t *txData = transfer->txData;
628 uint8_t *rxData = transfer->rxData;
629 uint32_t txRemainingByteCount = transfer->dataSize;
630 uint32_t rxRemainingByteCount = transfer->dataSize;
631
632 uint8_t bytesEachWrite;
633 uint8_t bytesEachRead;
634
635 uint32_t readData = 0;
636 uint32_t wordToSend =
637 ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
638
639 /*The TX and RX FIFO sizes are always the same*/
640 uint32_t fifoSize = LPSPI_GetRxFifoSize(base);
641
642 uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
643
644 bool isPcsContinuous = (bool)(transfer->configFlags & kLPSPI_MasterPcsContinuous);
645 bool isRxMask = false;
646 bool isByteSwap = (bool)(transfer->configFlags & kLPSPI_MasterByteSwap);
647
648 LPSPI_FlushFifo(base, true, true);
649 LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag);
650
651 if (!rxData)
652 {
653 isRxMask = true;
654 }
655
656 LPSPI_Enable(base, false);
657 base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
658 LPSPI_Enable(base, true);
659
660 base->TCR =
661 (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
662 LPSPI_TCR_CONT(isPcsContinuous) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_PCS(whichPcs);
663
664 if (bytesPerFrame <= 4)
665 {
666 bytesEachWrite = bytesPerFrame;
667 bytesEachRead = bytesPerFrame;
668 }
669 else
670 {
671 bytesEachWrite = 4;
672 bytesEachRead = 4;
673 }
674
675 /*Write the TX data until txRemainingByteCount is equal to 0 */
676 while (txRemainingByteCount > 0)
677 {
678 if (txRemainingByteCount < bytesEachWrite)
679 {
680 bytesEachWrite = txRemainingByteCount;
681 }
682
683 /*Wait until TX FIFO is not full*/
684 while (LPSPI_GetTxFifoCount(base) == fifoSize)
685 {
686 }
687
688 if (txData)
689 {
690 wordToSend = LPSPI_CombineWriteData(txData, bytesEachWrite, isByteSwap);
691 txData += bytesEachWrite;
692 }
693
694 LPSPI_WriteData(base, wordToSend);
695 txRemainingByteCount -= bytesEachWrite;
696
697 /*Check whether there is RX data in RX FIFO . Read out the RX data so that the RX FIFO would not overrun.*/
698 if (rxData)
699 {
700 while (LPSPI_GetRxFifoCount(base))
701 {
702 readData = LPSPI_ReadData(base);
703 if (rxRemainingByteCount < bytesEachRead)
704 {
705 bytesEachRead = rxRemainingByteCount;
706 }
707
708 LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap);
709 rxData += bytesEachRead;
710
711 rxRemainingByteCount -= bytesEachRead;
712 }
713 }
714 }
715
716 /* After write all the data in TX FIFO , should write the TCR_CONTC to 0 to de-assert the PCS. Note that TCR
717 * register also use the TX FIFO.
718 */
719 while ((LPSPI_GetTxFifoCount(base) == fifoSize))
720 {
721 }
722 base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
723
724 /*Read out the RX data in FIFO*/
725 if (rxData)
726 {
727 while (rxRemainingByteCount > 0)
728 {
729 while (LPSPI_GetRxFifoCount(base))
730 {
731 readData = LPSPI_ReadData(base);
732
733 if (rxRemainingByteCount < bytesEachRead)
734 {
735 bytesEachRead = rxRemainingByteCount;
736 }
737
738 LPSPI_SeparateReadData(rxData, readData, bytesEachRead, isByteSwap);
739 rxData += bytesEachRead;
740
741 rxRemainingByteCount -= bytesEachRead;
742 }
743 }
744 }
745 else
746 {
747 /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
748 while (!(LPSPI_GetStatusFlags(base) & kLPSPI_TransferCompleteFlag))
749 {
750 }
751 }
752
753 return kStatus_Success;
754 }
755
LPSPI_MasterTransferNonBlocking(LPSPI_Type * base,lpspi_master_handle_t * handle,lpspi_transfer_t * transfer)756 status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer)
757 {
758 assert(handle);
759 assert(transfer);
760
761 uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1;
762 uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8;
763 uint8_t dummyData = s_dummyData[LPSPI_GetInstance(base)];
764
765 if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
766 {
767 return kStatus_InvalidArgument;
768 }
769
770 /* Check that we're not busy.*/
771 if (handle->state == kLPSPI_Busy)
772 {
773 return kStatus_LPSPI_Busy;
774 }
775
776 handle->state = kLPSPI_Busy;
777
778 bool isRxMask = false;
779
780 uint8_t txWatermark;
781
782 uint32_t whichPcs = (transfer->configFlags & LPSPI_MASTER_PCS_MASK) >> LPSPI_MASTER_PCS_SHIFT;
783
784 handle->txData = transfer->txData;
785 handle->rxData = transfer->rxData;
786 handle->txRemainingByteCount = transfer->dataSize;
787 handle->rxRemainingByteCount = transfer->dataSize;
788 handle->totalByteCount = transfer->dataSize;
789
790 handle->writeTcrInIsr = false;
791
792 handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3) / 4);
793 handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
794
795 handle->txBuffIfNull =
796 ((uint32_t)dummyData) | ((uint32_t)dummyData << 8) | ((uint32_t)dummyData << 16) | ((uint32_t)dummyData << 24);
797
798 /*The TX and RX FIFO sizes are always the same*/
799 handle->fifoSize = LPSPI_GetRxFifoSize(base);
800
801 handle->isPcsContinuous = (bool)(transfer->configFlags & kLPSPI_MasterPcsContinuous);
802 handle->isByteSwap = (bool)(transfer->configFlags & kLPSPI_MasterByteSwap);
803
804 /*Set the RX and TX watermarks to reduce the ISR times.*/
805 if (handle->fifoSize > 1)
806 {
807 txWatermark = 1;
808 handle->rxWatermark = handle->fifoSize - 2;
809 }
810 else
811 {
812 txWatermark = 0;
813 handle->rxWatermark = 0;
814 }
815
816 LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
817
818 /*Transfers will stall when transmit FIFO is empty or receive FIFO is full. */
819 LPSPI_Enable(base, false);
820 base->CFGR1 &= (~LPSPI_CFGR1_NOSTALL_MASK);
821 LPSPI_Enable(base, true);
822
823 /*Flush FIFO , clear status , disable all the inerrupts.*/
824 LPSPI_FlushFifo(base, true, true);
825 LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag);
826 LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
827
828 /* If there is not rxData , can mask the receive data (receive data is not stored in receive FIFO).
829 * For master transfer , we'd better not masked the transmit data in TCR since the transfer flow is hard to
830 * controlled by software.*/
831 if (handle->rxData == NULL)
832 {
833 isRxMask = true;
834 handle->rxRemainingByteCount = 0;
835 }
836
837 base->TCR =
838 (base->TCR & ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_PCS_MASK)) |
839 LPSPI_TCR_CONT(handle->isPcsContinuous) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) |
840 LPSPI_TCR_PCS(whichPcs);
841
842 /*Calculate the bytes for write/read the TX/RX register each time*/
843 if (bytesPerFrame <= 4)
844 {
845 handle->bytesEachWrite = bytesPerFrame;
846 handle->bytesEachRead = bytesPerFrame;
847 }
848 else
849 {
850 handle->bytesEachWrite = 4;
851 handle->bytesEachRead = 4;
852 }
853
854 /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
855 * and you should also enable the INTMUX interupt in your application.
856 */
857 EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
858
859 /*TCR is also shared the FIFO , so wait for TCR written.*/
860 while (LPSPI_GetTxFifoCount(base) != 0)
861 {
862 }
863 /*Fill up the TX data in FIFO */
864 LPSPI_MasterTransferFillUpTxFifo(base, handle);
865
866 /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
867 * The IRQ handler will get the status of RX and TX interrupt flags.
868 */
869 if (handle->rxData)
870 {
871 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
872 *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
873 */
874 if ((handle->readRegRemainingTimes) <= handle->rxWatermark)
875 {
876 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->readRegRemainingTimes - 1);
877 }
878
879 LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable);
880 }
881 else
882 {
883 LPSPI_EnableInterrupts(base, kLPSPI_TxInterruptEnable);
884 }
885
886 return kStatus_Success;
887 }
888
LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type * base,lpspi_master_handle_t * handle)889 static void LPSPI_MasterTransferFillUpTxFifo(LPSPI_Type *base, lpspi_master_handle_t *handle)
890 {
891 assert(handle);
892
893 uint32_t wordToSend = 0;
894
895 /* Make sure the difference in remaining TX and RX byte counts does not exceed FIFO depth
896 * and that the number of TX FIFO entries does not exceed the FIFO depth.
897 * But no need to make the protection if there is no rxData.
898 */
899 while ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)) &&
900 (((handle->readRegRemainingTimes - handle->writeRegRemainingTimes) < handle->fifoSize) ||
901 (handle->rxData == NULL)))
902 {
903 if (handle->txRemainingByteCount < handle->bytesEachWrite)
904 {
905 handle->bytesEachWrite = handle->txRemainingByteCount;
906 }
907
908 if (handle->txData)
909 {
910 wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap);
911 handle->txData += handle->bytesEachWrite;
912 }
913 else
914 {
915 wordToSend = handle->txBuffIfNull;
916 }
917
918 /*Write the word to TX register*/
919 LPSPI_WriteData(base, wordToSend);
920
921 /*Decrease the write TX register times.*/
922 --handle->writeRegRemainingTimes;
923
924 /*Decrease the remaining TX byte count.*/
925 handle->txRemainingByteCount -= handle->bytesEachWrite;
926
927 if (handle->txRemainingByteCount == 0)
928 {
929 /* If PCS is continuous, update TCR to de-assert PCS */
930 if (handle->isPcsContinuous)
931 {
932 /* Only write to the TCR if the FIFO has room */
933 if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)))
934 {
935 base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
936 handle->writeTcrInIsr = false;
937 }
938 /* Else, set a global flag to tell the ISR to do write to the TCR */
939 else
940 {
941 handle->writeTcrInIsr = true;
942 }
943 }
944 break;
945 }
946 }
947 }
948
LPSPI_MasterTransferComplete(LPSPI_Type * base,lpspi_master_handle_t * handle)949 static void LPSPI_MasterTransferComplete(LPSPI_Type *base, lpspi_master_handle_t *handle)
950 {
951 assert(handle);
952
953 /* Disable interrupt requests*/
954 LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
955
956 handle->state = kLPSPI_Idle;
957
958 if (handle->callback)
959 {
960 handle->callback(base, handle, kStatus_Success, handle->userData);
961 }
962 }
963
LPSPI_MasterTransferGetCount(LPSPI_Type * base,lpspi_master_handle_t * handle,size_t * count)964 status_t LPSPI_MasterTransferGetCount(LPSPI_Type *base, lpspi_master_handle_t *handle, size_t *count)
965 {
966 assert(handle);
967
968 if (!count)
969 {
970 return kStatus_InvalidArgument;
971 }
972
973 /* Catch when there is not an active transfer. */
974 if (handle->state != kLPSPI_Busy)
975 {
976 *count = 0;
977 return kStatus_NoTransferInProgress;
978 }
979
980 size_t remainingByte;
981
982 if (handle->rxData)
983 {
984 remainingByte = handle->rxRemainingByteCount;
985 }
986 else
987 {
988 remainingByte = handle->txRemainingByteCount;
989 }
990
991 *count = handle->totalByteCount - remainingByte;
992
993 return kStatus_Success;
994 }
995
LPSPI_MasterTransferAbort(LPSPI_Type * base,lpspi_master_handle_t * handle)996 void LPSPI_MasterTransferAbort(LPSPI_Type *base, lpspi_master_handle_t *handle)
997 {
998 assert(handle);
999
1000 /* Disable interrupt requests*/
1001 LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
1002
1003 LPSPI_Reset(base);
1004
1005 handle->state = kLPSPI_Idle;
1006 handle->txRemainingByteCount = 0;
1007 handle->rxRemainingByteCount = 0;
1008 }
1009
LPSPI_MasterTransferHandleIRQ(LPSPI_Type * base,lpspi_master_handle_t * handle)1010 void LPSPI_MasterTransferHandleIRQ(LPSPI_Type *base, lpspi_master_handle_t *handle)
1011 {
1012 assert(handle);
1013
1014 uint32_t readData;
1015
1016 if (handle->rxData != NULL)
1017 {
1018 if (handle->rxRemainingByteCount)
1019 {
1020 /* First, disable the interrupts to avoid potentially triggering another interrupt
1021 * while reading out the RX FIFO as more data may be coming into the RX FIFO. We'll
1022 * re-enable the interrupts based on the LPSPI state after reading out the FIFO.
1023 */
1024 LPSPI_DisableInterrupts(base, kLPSPI_RxInterruptEnable);
1025
1026 while ((LPSPI_GetRxFifoCount(base)) && (handle->rxRemainingByteCount))
1027 {
1028 /*Read out the data*/
1029 readData = LPSPI_ReadData(base);
1030
1031 /*Decrease the read RX register times.*/
1032 --handle->readRegRemainingTimes;
1033
1034 if (handle->rxRemainingByteCount < handle->bytesEachRead)
1035 {
1036 handle->bytesEachRead = handle->rxRemainingByteCount;
1037 }
1038
1039 LPSPI_SeparateReadData(handle->rxData, readData, handle->bytesEachRead, handle->isByteSwap);
1040 handle->rxData += handle->bytesEachRead;
1041
1042 /*Decrease the remaining RX byte count.*/
1043 handle->rxRemainingByteCount -= handle->bytesEachRead;
1044 }
1045
1046 /* Re-enable the interrupts only if rxCount indicates there is more data to receive,
1047 * else we may get a spurious interrupt.
1048 * */
1049 if (handle->rxRemainingByteCount)
1050 {
1051 /* Set the TDF and RDF interrupt enables simultaneously to avoid race conditions */
1052 LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable);
1053 }
1054 }
1055
1056 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1057 *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1058 */
1059 if ((handle->readRegRemainingTimes) <= (handle->rxWatermark))
1060 {
1061 base->FCR =
1062 (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
1063 LPSPI_FCR_RXWATER((handle->readRegRemainingTimes > 1) ? (handle->readRegRemainingTimes - 1U) : (0U));
1064 }
1065 }
1066
1067 if (handle->txRemainingByteCount)
1068 {
1069 LPSPI_MasterTransferFillUpTxFifo(base, handle);
1070 }
1071 else
1072 {
1073 if ((LPSPI_GetTxFifoCount(base) < (handle->fifoSize)))
1074 {
1075 if ((handle->isPcsContinuous) && (handle->writeTcrInIsr))
1076 {
1077 base->TCR = (base->TCR & ~(LPSPI_TCR_CONTC_MASK));
1078 handle->writeTcrInIsr = false;
1079 }
1080 }
1081 }
1082
1083 if ((handle->txRemainingByteCount == 0) && (handle->rxRemainingByteCount == 0) && (!handle->writeTcrInIsr))
1084 {
1085 /* If no RX buffer, then transfer is not complete until transfer complete flag sets */
1086 if (handle->rxData == NULL)
1087 {
1088 if (LPSPI_GetStatusFlags(base) & kLPSPI_TransferCompleteFlag)
1089 {
1090 /* Complete the transfer and disable the interrupts */
1091 LPSPI_MasterTransferComplete(base, handle);
1092 }
1093 else
1094 {
1095 LPSPI_EnableInterrupts(base, kLPSPI_TransferCompleteInterruptEnable);
1096 LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable);
1097 }
1098 }
1099 else
1100 {
1101 /* Complete the transfer and disable the interrupts */
1102 LPSPI_MasterTransferComplete(base, handle);
1103 }
1104 }
1105 }
1106
1107 /*Transactional APIs -- Slave*/
LPSPI_SlaveTransferCreateHandle(LPSPI_Type * base,lpspi_slave_handle_t * handle,lpspi_slave_transfer_callback_t callback,void * userData)1108 void LPSPI_SlaveTransferCreateHandle(LPSPI_Type *base,
1109 lpspi_slave_handle_t *handle,
1110 lpspi_slave_transfer_callback_t callback,
1111 void *userData)
1112 {
1113 assert(handle);
1114
1115 /* Zero the handle. */
1116 memset(handle, 0, sizeof(*handle));
1117
1118 s_lpspiHandle[LPSPI_GetInstance(base)] = handle;
1119
1120 /* Set irq handler. */
1121 s_lpspiSlaveIsr = LPSPI_SlaveTransferHandleIRQ;
1122
1123 handle->callback = callback;
1124 handle->userData = userData;
1125 }
1126
LPSPI_SlaveTransferNonBlocking(LPSPI_Type * base,lpspi_slave_handle_t * handle,lpspi_transfer_t * transfer)1127 status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer)
1128 {
1129 assert(handle);
1130 assert(transfer);
1131
1132 uint32_t bitsPerFrame = ((base->TCR & LPSPI_TCR_FRAMESZ_MASK) >> LPSPI_TCR_FRAMESZ_SHIFT) + 1;
1133 uint32_t bytesPerFrame = (bitsPerFrame + 7) / 8;
1134
1135 if (!LPSPI_CheckTransferArgument(transfer, bitsPerFrame, bytesPerFrame))
1136 {
1137 return kStatus_InvalidArgument;
1138 }
1139
1140 /* Check that we're not busy.*/
1141 if (handle->state == kLPSPI_Busy)
1142 {
1143 return kStatus_LPSPI_Busy;
1144 }
1145 handle->state = kLPSPI_Busy;
1146
1147 bool isRxMask = false;
1148 bool isTxMask = false;
1149
1150 uint32_t whichPcs = (transfer->configFlags & LPSPI_SLAVE_PCS_MASK) >> LPSPI_SLAVE_PCS_SHIFT;
1151
1152 handle->txData = transfer->txData;
1153 handle->rxData = transfer->rxData;
1154 handle->txRemainingByteCount = transfer->dataSize;
1155 handle->rxRemainingByteCount = transfer->dataSize;
1156 handle->totalByteCount = transfer->dataSize;
1157
1158 handle->writeRegRemainingTimes = (transfer->dataSize / bytesPerFrame) * ((bytesPerFrame + 3) / 4);
1159 handle->readRegRemainingTimes = handle->writeRegRemainingTimes;
1160
1161 /*The TX and RX FIFO sizes are always the same*/
1162 handle->fifoSize = LPSPI_GetRxFifoSize(base);
1163
1164 handle->isByteSwap = (bool)(transfer->configFlags & kLPSPI_SlaveByteSwap);
1165
1166 /*Set the RX and TX watermarks to reduce the ISR times.*/
1167 uint8_t txWatermark;
1168 if (handle->fifoSize > 1)
1169 {
1170 txWatermark = 1;
1171 handle->rxWatermark = handle->fifoSize - 2;
1172 }
1173 else
1174 {
1175 txWatermark = 0;
1176 handle->rxWatermark = 0;
1177 }
1178 LPSPI_SetFifoWatermarks(base, txWatermark, handle->rxWatermark);
1179
1180 /*Flush FIFO , clear status , disable all the inerrupts.*/
1181 LPSPI_FlushFifo(base, true, true);
1182 LPSPI_ClearStatusFlags(base, kLPSPI_AllStatusFlag);
1183 LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
1184
1185 /*If there is not rxData , can mask the receive data (receive data is not stored in receive FIFO).*/
1186 if (handle->rxData == NULL)
1187 {
1188 isRxMask = true;
1189 handle->rxRemainingByteCount = 0;
1190 }
1191
1192 /*If there is not txData , can mask the transmit data (no data is loaded from transmit FIFO and output pin
1193 * is tristated).
1194 */
1195 if (handle->txData == NULL)
1196 {
1197 isTxMask = true;
1198 handle->txRemainingByteCount = 0;
1199 }
1200
1201 base->TCR = (base->TCR &
1202 ~(LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK | LPSPI_TCR_RXMSK_MASK | LPSPI_TCR_TXMSK_MASK |
1203 LPSPI_TCR_PCS_MASK)) |
1204 LPSPI_TCR_CONT(0) | LPSPI_TCR_CONTC(0) | LPSPI_TCR_RXMSK(isRxMask) | LPSPI_TCR_TXMSK(isTxMask) |
1205 LPSPI_TCR_PCS(whichPcs);
1206
1207 /*Calculate the bytes for write/read the TX/RX register each time*/
1208 if (bytesPerFrame <= 4)
1209 {
1210 handle->bytesEachWrite = bytesPerFrame;
1211 handle->bytesEachRead = bytesPerFrame;
1212 }
1213 else
1214 {
1215 handle->bytesEachWrite = 4;
1216 handle->bytesEachRead = 4;
1217 }
1218
1219 /* Enable the NVIC for LPSPI peripheral. Note that below code is useless if the LPSPI interrupt is in INTMUX ,
1220 * and you should also enable the INTMUX interupt in your application.
1221 */
1222 EnableIRQ(s_lpspiIRQ[LPSPI_GetInstance(base)]);
1223
1224 /*TCR is also shared the FIFO , so wait for TCR written.*/
1225 while (LPSPI_GetTxFifoCount(base) != 0)
1226 {
1227 }
1228
1229 /*Fill up the TX data in FIFO */
1230 if (handle->txData)
1231 {
1232 LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1233 }
1234
1235 /* Since SPI is a synchronous interface, we only need to enable the RX interrupt if there is RX data.
1236 * The IRQ handler will get the status of RX and TX interrupt flags.
1237 */
1238 if (handle->rxData)
1239 {
1240 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1241 *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1242 */
1243 if ((handle->readRegRemainingTimes) <= handle->rxWatermark)
1244 {
1245 base->FCR = (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) | LPSPI_FCR_RXWATER(handle->readRegRemainingTimes - 1);
1246 }
1247
1248 LPSPI_EnableInterrupts(base, kLPSPI_RxInterruptEnable);
1249 }
1250 else
1251 {
1252 LPSPI_EnableInterrupts(base, kLPSPI_TxInterruptEnable);
1253 }
1254
1255 if (handle->rxData)
1256 {
1257 /* RX FIFO overflow request enable */
1258 LPSPI_EnableInterrupts(base, kLPSPI_ReceiveErrorInterruptEnable);
1259 }
1260 if (handle->txData)
1261 {
1262 /* TX FIFO underflow request enable */
1263 LPSPI_EnableInterrupts(base, kLPSPI_TransmitErrorInterruptEnable);
1264 }
1265
1266 return kStatus_Success;
1267 }
1268
LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type * base,lpspi_slave_handle_t * handle)1269 static void LPSPI_SlaveTransferFillUpTxFifo(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1270 {
1271 assert(handle);
1272
1273 uint32_t wordToSend = 0;
1274
1275 while (LPSPI_GetTxFifoCount(base) < (handle->fifoSize))
1276 {
1277 if (handle->txRemainingByteCount < handle->bytesEachWrite)
1278 {
1279 handle->bytesEachWrite = handle->txRemainingByteCount;
1280 }
1281
1282 wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap);
1283 handle->txData += handle->bytesEachWrite;
1284
1285 /*Decrease the remaining TX byte count.*/
1286 handle->txRemainingByteCount -= handle->bytesEachWrite;
1287
1288 /*Write the word to TX register*/
1289 LPSPI_WriteData(base, wordToSend);
1290
1291 if (handle->txRemainingByteCount == 0)
1292 {
1293 break;
1294 }
1295 }
1296 }
1297
LPSPI_SlaveTransferComplete(LPSPI_Type * base,lpspi_slave_handle_t * handle)1298 static void LPSPI_SlaveTransferComplete(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1299 {
1300 assert(handle);
1301
1302 status_t status = 0;
1303
1304 /* Disable interrupt requests*/
1305 LPSPI_DisableInterrupts(base, kLPSPI_AllInterruptEnable);
1306
1307 if (handle->state == kLPSPI_Error)
1308 {
1309 status = kStatus_LPSPI_Error;
1310 }
1311 else
1312 {
1313 status = kStatus_Success;
1314 }
1315
1316 handle->state = kLPSPI_Idle;
1317
1318 if (handle->callback)
1319 {
1320 handle->callback(base, handle, status, handle->userData);
1321 }
1322 }
1323
LPSPI_SlaveTransferGetCount(LPSPI_Type * base,lpspi_slave_handle_t * handle,size_t * count)1324 status_t LPSPI_SlaveTransferGetCount(LPSPI_Type *base, lpspi_slave_handle_t *handle, size_t *count)
1325 {
1326 assert(handle);
1327
1328 if (!count)
1329 {
1330 return kStatus_InvalidArgument;
1331 }
1332
1333 /* Catch when there is not an active transfer. */
1334 if (handle->state != kLPSPI_Busy)
1335 {
1336 *count = 0;
1337 return kStatus_NoTransferInProgress;
1338 }
1339
1340 size_t remainingByte;
1341
1342 if (handle->rxData)
1343 {
1344 remainingByte = handle->rxRemainingByteCount;
1345 }
1346 else
1347 {
1348 remainingByte = handle->txRemainingByteCount;
1349 }
1350
1351 *count = handle->totalByteCount - remainingByte;
1352
1353 return kStatus_Success;
1354 }
1355
LPSPI_SlaveTransferAbort(LPSPI_Type * base,lpspi_slave_handle_t * handle)1356 void LPSPI_SlaveTransferAbort(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1357 {
1358 assert(handle);
1359
1360 /* Disable interrupt requests*/
1361 LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable);
1362
1363 LPSPI_Reset(base);
1364
1365 handle->state = kLPSPI_Idle;
1366 handle->txRemainingByteCount = 0;
1367 handle->rxRemainingByteCount = 0;
1368 }
1369
LPSPI_SlaveTransferHandleIRQ(LPSPI_Type * base,lpspi_slave_handle_t * handle)1370 void LPSPI_SlaveTransferHandleIRQ(LPSPI_Type *base, lpspi_slave_handle_t *handle)
1371 {
1372 assert(handle);
1373
1374 uint32_t readData; /* variable to store word read from RX FIFO */
1375 uint32_t wordToSend; /* variable to store word to write to TX FIFO */
1376
1377 if (handle->rxData != NULL)
1378 {
1379 if (handle->rxRemainingByteCount > 0)
1380 {
1381 while (LPSPI_GetRxFifoCount(base))
1382 {
1383 /*Read out the data*/
1384 readData = LPSPI_ReadData(base);
1385
1386 /*Decrease the read RX register times.*/
1387 --handle->readRegRemainingTimes;
1388
1389 if (handle->rxRemainingByteCount < handle->bytesEachRead)
1390 {
1391 handle->bytesEachRead = handle->rxRemainingByteCount;
1392 }
1393
1394 LPSPI_SeparateReadData(handle->rxData, readData, handle->bytesEachRead, handle->isByteSwap);
1395 handle->rxData += handle->bytesEachRead;
1396
1397 /*Decrease the remaining RX byte count.*/
1398 handle->rxRemainingByteCount -= handle->bytesEachRead;
1399
1400 if ((handle->txRemainingByteCount > 0) && (handle->txData != NULL))
1401 {
1402 if (handle->txRemainingByteCount < handle->bytesEachWrite)
1403 {
1404 handle->bytesEachWrite = handle->txRemainingByteCount;
1405 }
1406
1407 wordToSend = LPSPI_CombineWriteData(handle->txData, handle->bytesEachWrite, handle->isByteSwap);
1408 handle->txData += handle->bytesEachWrite;
1409
1410 /*Decrease the remaining TX byte count.*/
1411 handle->txRemainingByteCount -= handle->bytesEachWrite;
1412
1413 /*Write the word to TX register*/
1414 LPSPI_WriteData(base, wordToSend);
1415 }
1416
1417 if (handle->rxRemainingByteCount == 0)
1418 {
1419 break;
1420 }
1421 }
1422 }
1423
1424 /*Set rxWatermark to (readRegRemainingTimes-1) if readRegRemainingTimes less than rxWatermark. Otherwise there
1425 *is not RX interrupt for the last datas because the RX count is not greater than rxWatermark.
1426 */
1427 if ((handle->readRegRemainingTimes) <= (handle->rxWatermark))
1428 {
1429 base->FCR =
1430 (base->FCR & (~LPSPI_FCR_RXWATER_MASK)) |
1431 LPSPI_FCR_RXWATER((handle->readRegRemainingTimes > 1) ? (handle->readRegRemainingTimes - 1U) : (0U));
1432 }
1433 }
1434 else if ((handle->txRemainingByteCount) && (handle->txData != NULL))
1435 {
1436 LPSPI_SlaveTransferFillUpTxFifo(base, handle);
1437 }
1438 else
1439 {
1440 __NOP();
1441 }
1442
1443 if ((handle->txRemainingByteCount == 0) && (handle->rxRemainingByteCount == 0))
1444 {
1445 /* If no RX buffer, then transfer is not complete until transfer complete flag sets and the TX FIFO empty*/
1446 if (handle->rxData == NULL)
1447 {
1448 if ((LPSPI_GetStatusFlags(base) & kLPSPI_FrameCompleteFlag) && (LPSPI_GetTxFifoCount(base) == 0))
1449 {
1450 /* Complete the transfer and disable the interrupts */
1451 LPSPI_SlaveTransferComplete(base, handle);
1452 }
1453 else
1454 {
1455 LPSPI_ClearStatusFlags(base, kLPSPI_FrameCompleteFlag);
1456 LPSPI_EnableInterrupts(base, kLPSPI_FrameCompleteInterruptEnable);
1457 LPSPI_DisableInterrupts(base, kLPSPI_TxInterruptEnable | kLPSPI_RxInterruptEnable);
1458 }
1459 }
1460 else
1461 {
1462 /* Complete the transfer and disable the interrupts */
1463 LPSPI_SlaveTransferComplete(base, handle);
1464 }
1465 }
1466
1467 /* Catch tx fifo underflow conditions, service only if tx under flow interrupt enabled */
1468 if ((LPSPI_GetStatusFlags(base) & kLPSPI_TransmitErrorFlag) && (base->IER & LPSPI_IER_TEIE_MASK))
1469 {
1470 LPSPI_ClearStatusFlags(base, kLPSPI_TransmitErrorFlag);
1471 /* Change state to error and clear flag */
1472 if (handle->txData)
1473 {
1474 handle->state = kLPSPI_Error;
1475 }
1476 handle->errorCount++;
1477 }
1478 /* Catch rx fifo overflow conditions, service only if rx over flow interrupt enabled */
1479 if ((LPSPI_GetStatusFlags(base) & kLPSPI_ReceiveErrorFlag) && (base->IER & LPSPI_IER_REIE_MASK))
1480 {
1481 LPSPI_ClearStatusFlags(base, kLPSPI_ReceiveErrorFlag);
1482 /* Change state to error and clear flag */
1483 if (handle->txData)
1484 {
1485 handle->state = kLPSPI_Error;
1486 }
1487 handle->errorCount++;
1488 }
1489 }
1490
LPSPI_CombineWriteData(uint8_t * txData,uint32_t bytesEachWrite,bool isByteSwap)1491 static uint32_t LPSPI_CombineWriteData(uint8_t *txData, uint32_t bytesEachWrite, bool isByteSwap)
1492 {
1493 assert(txData);
1494
1495 uint32_t wordToSend = 0;
1496
1497 switch (bytesEachWrite)
1498 {
1499 case 1:
1500 wordToSend = *txData;
1501 ++txData;
1502 break;
1503
1504 case 2:
1505 if (!isByteSwap)
1506 {
1507 wordToSend = *txData;
1508 ++txData;
1509 wordToSend |= (unsigned)(*txData) << 8U;
1510 ++txData;
1511 }
1512 else
1513 {
1514 wordToSend = (unsigned)(*txData) << 8U;
1515 ++txData;
1516 wordToSend |= *txData;
1517 ++txData;
1518 }
1519
1520 break;
1521
1522 case 3:
1523 if (!isByteSwap)
1524 {
1525 wordToSend = *txData;
1526 ++txData;
1527 wordToSend |= (unsigned)(*txData) << 8U;
1528 ++txData;
1529 wordToSend |= (unsigned)(*txData) << 16U;
1530 ++txData;
1531 }
1532 else
1533 {
1534 wordToSend = (unsigned)(*txData) << 16U;
1535 ++txData;
1536 wordToSend |= (unsigned)(*txData) << 8U;
1537 ++txData;
1538 wordToSend |= *txData;
1539 ++txData;
1540 }
1541 break;
1542
1543 case 4:
1544 if (!isByteSwap)
1545 {
1546 wordToSend = *txData;
1547 ++txData;
1548 wordToSend |= (unsigned)(*txData) << 8U;
1549 ++txData;
1550 wordToSend |= (unsigned)(*txData) << 16U;
1551 ++txData;
1552 wordToSend |= (unsigned)(*txData) << 24U;
1553 ++txData;
1554 }
1555 else
1556 {
1557 wordToSend = (unsigned)(*txData) << 24U;
1558 ++txData;
1559 wordToSend |= (unsigned)(*txData) << 16U;
1560 ++txData;
1561 wordToSend |= (unsigned)(*txData) << 8U;
1562 ++txData;
1563 wordToSend |= *txData;
1564 ++txData;
1565 }
1566 break;
1567
1568 default:
1569 assert(false);
1570 break;
1571 }
1572 return wordToSend;
1573 }
1574
LPSPI_SeparateReadData(uint8_t * rxData,uint32_t readData,uint32_t bytesEachRead,bool isByteSwap)1575 static void LPSPI_SeparateReadData(uint8_t *rxData, uint32_t readData, uint32_t bytesEachRead, bool isByteSwap)
1576 {
1577 assert(rxData);
1578
1579 switch (bytesEachRead)
1580 {
1581 case 1:
1582 *rxData = readData;
1583 ++rxData;
1584 break;
1585
1586 case 2:
1587 if (!isByteSwap)
1588 {
1589 *rxData = readData;
1590 ++rxData;
1591 *rxData = readData >> 8;
1592 ++rxData;
1593 }
1594 else
1595 {
1596 *rxData = readData >> 8;
1597 ++rxData;
1598 *rxData = readData;
1599 ++rxData;
1600 }
1601 break;
1602
1603 case 3:
1604 if (!isByteSwap)
1605 {
1606 *rxData = readData;
1607 ++rxData;
1608 *rxData = readData >> 8;
1609 ++rxData;
1610 *rxData = readData >> 16;
1611 ++rxData;
1612 }
1613 else
1614 {
1615 *rxData = readData >> 16;
1616 ++rxData;
1617 *rxData = readData >> 8;
1618 ++rxData;
1619 *rxData = readData;
1620 ++rxData;
1621 }
1622 break;
1623
1624 case 4:
1625 if (!isByteSwap)
1626 {
1627 *rxData = readData;
1628 ++rxData;
1629 *rxData = readData >> 8;
1630 ++rxData;
1631 *rxData = readData >> 16;
1632 ++rxData;
1633 *rxData = readData >> 24;
1634 ++rxData;
1635 }
1636 else
1637 {
1638 *rxData = readData >> 24;
1639 ++rxData;
1640 *rxData = readData >> 16;
1641 ++rxData;
1642 *rxData = readData >> 8;
1643 ++rxData;
1644 *rxData = readData;
1645 ++rxData;
1646 }
1647 break;
1648
1649 default:
1650 assert(false);
1651 break;
1652 }
1653 }
1654
LPSPI_CommonIRQHandler(LPSPI_Type * base,void * param)1655 static void LPSPI_CommonIRQHandler(LPSPI_Type *base, void *param)
1656 {
1657 if (LPSPI_IsMaster(base))
1658 {
1659 s_lpspiMasterIsr(base, (lpspi_master_handle_t *)param);
1660 }
1661 else
1662 {
1663 s_lpspiSlaveIsr(base, (lpspi_slave_handle_t *)param);
1664 }
1665 }
1666
1667 #if defined(LPSPI0)
LPSPI0_DriverIRQHandler(void)1668 void LPSPI0_DriverIRQHandler(void)
1669 {
1670 assert(s_lpspiHandle[0]);
1671 LPSPI_CommonIRQHandler(LPSPI0, s_lpspiHandle[0]);
1672 }
1673 #endif
1674
1675 #if defined(LPSPI1)
LPSPI1_DriverIRQHandler(void)1676 void LPSPI1_DriverIRQHandler(void)
1677 {
1678 assert(s_lpspiHandle[1]);
1679 LPSPI_CommonIRQHandler(LPSPI1, s_lpspiHandle[1]);
1680 }
1681 #endif
1682
1683 #if defined(LPSPI2)
LPSPI2_DriverIRQHandler(void)1684 void LPSPI2_DriverIRQHandler(void)
1685 {
1686 assert(s_lpspiHandle[2]);
1687 LPSPI_CommonIRQHandler(LPSPI2, s_lpspiHandle[2]);
1688 }
1689 #endif
1690
1691 #if defined(LPSPI3)
LPSPI3_DriverIRQHandler(void)1692 void LPSPI3_DriverIRQHandler(void)
1693 {
1694 assert(s_lpspiHandle[3]);
1695 LPSPI_CommonIRQHandler(LPSPI3, s_lpspiHandle[3]);
1696 }
1697 #endif
1698
1699 #if defined(LPSPI4)
LPSPI4_DriverIRQHandler(void)1700 void LPSPI4_DriverIRQHandler(void)
1701 {
1702 assert(s_lpspiHandle[4]);
1703 LPSPI_CommonIRQHandler(LPSPI4, s_lpspiHandle[4]);
1704 }
1705 #endif
1706
1707 #if defined(LPSPI5)
LPSPI5_DriverIRQHandler(void)1708 void LPSPI5_DriverIRQHandler(void)
1709 {
1710 assert(s_lpspiHandle[5]);
1711 LPSPI_CommonIRQHandler(LPSPI5, s_lpspiHandle[5]);
1712 }
1713 #endif
1714
1715 #if defined(DMA_LPSPI0)
DMA_SPI0_INT_IRQHandler(void)1716 void DMA_SPI0_INT_IRQHandler(void)
1717 {
1718 assert(s_lpspiHandle[0]);
1719 LPSPI_CommonIRQHandler(DMA_LPSPI0, s_lpspiHandle[0]);
1720 }
1721 #endif
1722
1723 #if defined(DMA_LPSPI1)
DMA_SPI1_INT_IRQHandler(void)1724 void DMA_SPI1_INT_IRQHandler(void)
1725 {
1726 assert(s_lpspiHandle[1]);
1727 LPSPI_CommonIRQHandler(DMA_LPSPI1, s_lpspiHandle[1]);
1728 }
1729 #endif
1730 #if defined(DMA_LPSPI2)
DMA_SPI2_INT_IRQHandler(void)1731 void DMA_SPI2_INT_IRQHandler(void)
1732 {
1733 assert(s_lpspiHandle[2]);
1734 LPSPI_CommonIRQHandler(DMA_LPSPI2, s_lpspiHandle[2]);
1735 }
1736 #endif
1737
1738 #if defined(DMA_LPSPI3)
DMA_SPI3_INT_IRQHandler(void)1739 void DMA_SPI3_INT_IRQHandler(void)
1740 {
1741 assert(s_lpspiHandle[3]);
1742 LPSPI_CommonIRQHandler(DMA_LPSPI3, s_lpspiHandle[3]);
1743 }
1744 #endif
1745