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