1 /*
2 * Copyright 2017-2020,2022 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_spi.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.lpc_minispi"
18 #endif
19
20 /*******************************************************************************
21 * Variables
22 ******************************************************************************/
23 #if defined(FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS) && (FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS)
24 /*! @brief SPI internal handle pointer array */
25 static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT];
26
27 /*! @brief IRQ name array */
28 static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
29
30 /*! @brief Typedef for spi master interrupt handler. spi master and slave handle is the same. */
31 typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle);
32
33 /*! @brief Pointer to master IRQ handler for each instance. */
34 static spi_isr_t s_spiMasterIsr;
35 static spi_isr_t s_spiSlaveIsr;
36 #endif /* FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS */
37
38 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
39 /* @brief Array to map SPI instance number to CLOCK names */
40 static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS;
41 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
42
43 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
44 /* @brief Array to map SPI reset. */
45 static const SYSCON_RSTn_t s_spiReset[] = SPI_RSTS_N;
46 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
47
48 /*! @brief Array to map SPI instance number to base address. */
49 static const uint32_t s_spiBaseAddrs[FSL_FEATURE_SOC_SPI_COUNT] = SPI_BASE_ADDRS;
50
51 /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
52 volatile uint16_t s_dummyData[FSL_FEATURE_SOC_SPI_COUNT] = {0};
53
54 /*******************************************************************************
55 * Code
56 ******************************************************************************/
57
58 #if defined(FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS) && (FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS)
59 /*!
60 * @brief Send a piece of data for SPI.
61 *
62 * This function will check if TXDAT register ready, and write the data into it.
63 * At the same time, this function updates the values in master handle structure.
64 *
65 * @param base SPI base pointer
66 * @param handle Pointer to SPI master handle structure.
67 */
SPI_SendTransfer(SPI_Type * base,spi_master_handle_t * handle)68 static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
69 {
70 uint32_t tmp32 = 0U;
71 uint32_t instance = SPI_GetInstance(base);
72
73 /* If transmit is ready, write data to TXDAT register. */
74 if (((uint32_t)kSPI_TxReadyFlag & SPI_GetStatusFlags(base)) != 0U)
75 {
76 if ((handle->txData) != NULL)
77 {
78 tmp32 = *(handle->txData++);
79 handle->txRemainingBytes--;
80 if (handle->dataWidth > (uint8_t)kSPI_Data8Bits)
81 {
82 tmp32 |= ((uint32_t)(*(handle->txData++)) << 8U);
83 handle->txRemainingBytes--;
84 }
85 }
86 else
87 {
88 tmp32 = (uint32_t)s_dummyData[instance];
89 handle->txRemainingBytes--;
90 if (handle->dataWidth > (uint8_t)kSPI_Data8Bits)
91 {
92 handle->txRemainingBytes--;
93 }
94 }
95 /* If this transmit is the last to send, Set the control bits. */
96 if (handle->txRemainingBytes == 0U)
97 {
98 base->TXCTL = handle->lastCommand;
99 }
100
101 base->TXDAT = tmp32;
102 }
103 }
104
105 /*!
106 * @brief Receive a piece of data for SPI.
107 *
108 * This function will check if RX register is ready, and write the data to destination address.
109 * At the same time, this function updates the values in master handle structure.
110 *
111 * @param base SPI base pointer
112 * @param handle Pointer to SPI master handle structure.
113 */
SPI_ReceiveTransfer(SPI_Type * base,spi_master_handle_t * handle)114 static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle)
115 {
116 uint32_t tmp32 = 0U;
117
118 /* If receive is ready, read data from RXDAT register. */
119 if (((uint32_t)kSPI_RxReadyFlag & SPI_GetStatusFlags(base)) != 0U)
120 {
121 tmp32 = SPI_ReadData(base);
122 /* Check If receive buffer is NULL. */
123 if ((handle->rxData) != NULL)
124 {
125 *(handle->rxData++) = (uint8_t)tmp32;
126 handle->rxRemainingBytes--;
127 if (handle->dataWidth > (uint8_t)kSPI_Data8Bits)
128 {
129 *(handle->rxData++) = (uint8_t)(tmp32 >> 8U);
130 handle->rxRemainingBytes--;
131 }
132 }
133 }
134 }
135 #endif /* FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS */
136
137 /*!
138 * @brief Get the instance for SPI module.
139 *
140 * @param base SPI base address
141 */
142 /*! brief Returns instance number for SPI peripheral base address. */
SPI_GetInstance(SPI_Type * base)143 uint32_t SPI_GetInstance(SPI_Type *base)
144 {
145 assert(NULL != base);
146
147 uint32_t i = 0U;
148
149 for (i = 0; i < (uint32_t)FSL_FEATURE_SOC_SPI_COUNT; i++)
150 {
151 if ((uint32_t)base == s_spiBaseAddrs[i])
152 {
153 break;
154 }
155 }
156
157 assert(i < (uint32_t)FSL_FEATURE_SOC_SPI_COUNT);
158 return i;
159 }
160
161 /*!
162 * brief Set up the dummy data. This API can change the default data to be transferred
163 * when users set the tx buffer to NULL.
164 *
165 * param base SPI peripheral address.
166 * param dummyData Data to be transferred when tx buffer is NULL.
167 */
SPI_SetDummyData(SPI_Type * base,uint16_t dummyData)168 void SPI_SetDummyData(SPI_Type *base, uint16_t dummyData)
169 {
170 uint32_t instance = SPI_GetInstance(base);
171 s_dummyData[instance] = dummyData;
172 }
173
174 /* Set delay time for SPI transfer. */
175 /*!
176 * brief Set delay time for transfer.
177 * the delay uint is SPI clock time, maximum value is 0xF.
178 * param base SPI base pointer
179 * param config configuration for delay option ref spi_delay_config_t.
180 */
SPI_SetTransferDelay(SPI_Type * base,const spi_delay_config_t * config)181 void SPI_SetTransferDelay(SPI_Type *base, const spi_delay_config_t *config)
182 {
183 assert(NULL != config);
184 /* Set the delay configuration. */
185 base->DLY = (SPI_DLY_PRE_DELAY(config->preDelay) | SPI_DLY_POST_DELAY(config->postDelay) |
186 SPI_DLY_FRAME_DELAY(config->frameDelay) | SPI_DLY_TRANSFER_DELAY(config->transferDelay));
187 }
188
189 /*!
190 * brief Sets the SPI master configuration structure to default values.
191 *
192 * The purpose of this API is to get the configuration structure initialized for use in SPI_MasterInit().
193 * User may use the initialized structure unchanged in SPI_MasterInit(), or modify
194 * some fields of the structure before calling SPI_MasterInit(). After calling this API,
195 * the master is ready to transfer.
196 * Example:
197 code
198 spi_master_config_t config;
199 SPI_MasterGetDefaultConfig(&config);
200 endcode
201 *
202 * param config pointer to master config structure
203 */
SPI_MasterGetDefaultConfig(spi_master_config_t * config)204 void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
205 {
206 assert(NULL != config);
207
208 /* Initializes the configure structure to zero. */
209 (void)memset(config, 0, sizeof(*config));
210
211 config->enableLoopback = false;
212 config->enableMaster = true;
213 config->clockPolarity = kSPI_ClockPolarityActiveHigh;
214 config->clockPhase = kSPI_ClockPhaseFirstEdge;
215 config->direction = kSPI_MsbFirst;
216 config->baudRate_Bps = 500000U;
217 config->dataWidth = (uint8_t)kSPI_Data8Bits;
218 config->sselNumber = kSPI_Ssel0Assert;
219 config->sselPolarity = kSPI_SpolActiveAllLow;
220 config->delayConfig.frameDelay = 0U;
221 config->delayConfig.postDelay = 0U;
222 config->delayConfig.preDelay = 0U;
223 config->delayConfig.transferDelay = 0U;
224 }
225
226 /*!
227 * brief Initializes the SPI with master configuration.
228 *
229 * The configuration structure can be filled by user from scratch, or be set with default
230 * values by SPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
231 * Example
232 code
233 spi_master_config_t config = {
234 .baudRate_Bps = 500000,
235 ...
236 };
237 SPI_MasterInit(SPI0, &config);
238 endcode
239 *
240 * param base SPI base pointer
241 * param config pointer to master configuration structure
242 * param srcClock_Hz Source clock frequency.
243 */
SPI_MasterInit(SPI_Type * base,const spi_master_config_t * config,uint32_t srcClock_Hz)244 status_t SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
245 {
246 uint32_t instance = 0U;
247 status_t result = 0;
248 uint32_t tmp = 0U;
249
250 /* assert params */
251 assert(!((NULL == base) || (NULL == config) || (0U == srcClock_Hz)));
252
253 /* Get instance number */
254 instance = SPI_GetInstance(base);
255
256 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
257 /* Enable the clock. */
258 CLOCK_EnableClock(s_spiClock[instance]);
259 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
260
261 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
262 /* Reset the module. */
263 RESET_PeripheralReset(s_spiReset[instance]);
264 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
265
266 /* set divider */
267 result = SPI_MasterSetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
268 if (kStatus_Success != result)
269 {
270 return result;
271 }
272 /* Set CFG register to configure phase/polarity/direction/master mode/loopback/ssel pin select. */
273 tmp |= (SPI_CFG_CPHA(config->clockPhase) | SPI_CFG_CPOL(config->clockPolarity) | SPI_CFG_LSBF(config->direction) |
274 SPI_CFG_MASTER(1) | SPI_CFG_LOOP(config->enableLoopback) |
275 ((uint32_t)config->sselPolarity & (uint32_t)kSPI_SpolActiveAllHigh));
276 base->CFG = tmp;
277
278 /* Set delay configuration. */
279 SPI_SetTransferDelay(base, &(config->delayConfig));
280
281 /* Set dummy data. */
282 SPI_SetDummyData(base, (uint8_t)SPI_DUMMYDATA);
283
284 /* Set TXCTL register. */
285 base->TXCTL |= (SPI_TXCTL_LEN(config->dataWidth) | ((uint32_t)config->sselNumber & (uint32_t)kSPI_SselDeAssertAll));
286
287 /* Enable the SPI module. */
288 SPI_Enable(base, config->enableMaster);
289
290 return kStatus_Success;
291 }
292
293 /*!
294 * brief Sets the SPI slave configuration structure to default values.
295 *
296 * The purpose of this API is to get the configuration structure initialized for use in SPI_SlaveInit().
297 * Modify some fields of the structure before calling SPI_SlaveInit().
298 * Example:
299 code
300 spi_slave_config_t config;
301 SPI_SlaveGetDefaultConfig(&config);
302 endcode
303 *
304 * param config pointer to slave configuration structure
305 */
SPI_SlaveGetDefaultConfig(spi_slave_config_t * config)306 void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
307 {
308 assert(NULL != config);
309
310 /* Initializes the configure structure to zero. */
311 (void)memset(config, 0, sizeof(*config));
312
313 config->enableSlave = true;
314 config->clockPolarity = kSPI_ClockPolarityActiveHigh;
315 config->clockPhase = kSPI_ClockPhaseFirstEdge;
316 config->direction = kSPI_MsbFirst;
317 config->dataWidth = (uint8_t)kSPI_Data8Bits;
318 config->sselPolarity = kSPI_SpolActiveAllLow;
319 }
320
321 /*!
322 * brief Initializes the SPI with slave configuration.
323 *
324 * The configuration structure can be filled by user from scratch or be set with
325 * default values by SPI_SlaveGetDefaultConfig().
326 * After calling this API, the slave is ready to transfer.
327 * Example
328 code
329 spi_slave_config_t config = {
330 .polarity = kSPI_ClockPolarityActiveHigh;
331 .phase = kSPI_ClockPhaseFirstEdge;
332 .direction = kSPI_MsbFirst;
333 ...
334 };
335 SPI_SlaveInit(SPI0, &config);
336 endcode
337 *
338 * param base SPI base pointer
339 * param config pointer to slave configuration structure
340 */
SPI_SlaveInit(SPI_Type * base,const spi_slave_config_t * config)341 status_t SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
342 {
343 uint32_t instance = 0U;
344 uint32_t tmp = 0U;
345
346 /* assert params */
347 assert(!((NULL == base) || (NULL == config)));
348 /* Get the instance of SPI. */
349 instance = SPI_GetInstance(base);
350
351 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
352 /* Enable the clock. */
353 CLOCK_EnableClock(s_spiClock[instance]);
354 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
355
356 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
357 /* Reset the module. */
358 RESET_PeripheralReset(s_spiReset[instance]);
359 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
360
361 /* Set confiuration for phase/polarity/direction/active level for SSEL pins. */
362 tmp |= SPI_CFG_CPHA(config->clockPhase) | SPI_CFG_CPOL(config->clockPolarity) | SPI_CFG_LSBF(config->direction) |
363 ((uint32_t)config->sselPolarity & (uint32_t)kSPI_SpolActiveAllHigh);
364 base->CFG = tmp;
365
366 /* Set dummy data. */
367 SPI_SetDummyData(base, (uint8_t)SPI_DUMMYDATA);
368
369 /* Set TXCTL register. */
370 base->TXCTL |= SPI_TXCTL_LEN(config->dataWidth);
371
372 /* Enable the SPI module. */
373 SPI_Enable(base, config->enableSlave);
374
375 return kStatus_Success;
376 }
377
378 /*!
379 * brief De-initializes the SPI.
380 *
381 * Calling this API resets the SPI module, gates the SPI clock.
382 * Disable the fifo if enabled.
383 * The SPI module can't work unless calling the SPI_MasterInit/SPI_SlaveInit to initialize module.
384 *
385 * param base SPI base pointer
386 */
SPI_Deinit(SPI_Type * base)387 void SPI_Deinit(SPI_Type *base)
388 {
389 /* Assert arguments */
390 assert(NULL != base);
391 uint32_t instance = SPI_GetInstance(base);
392 /* Disable SPI module before shutting down the clock. */
393 SPI_Enable(base, false);
394
395 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
396 /* Disable the clock. */
397 CLOCK_DisableClock(s_spiClock[instance]);
398 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
399 }
400
401 /*!
402 * brief Sets the baud rate for SPI transfer. This is only used in master.
403 *
404 * param base SPI base pointer
405 * param baudrate_Bps baud rate needed in Hz.
406 * param srcClock_Hz SPI source clock frequency in Hz.
407 */
SPI_MasterSetBaudRate(SPI_Type * base,uint32_t baudrate_Bps,uint32_t srcClock_Hz)408 status_t SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudrate_Bps, uint32_t srcClock_Hz)
409 {
410 uint32_t tmp;
411
412 /* assert params */
413 assert(!((NULL == base) || (0U == baudrate_Bps) || (0U == srcClock_Hz)));
414
415 /* calculate baudrate */
416 tmp = (srcClock_Hz / baudrate_Bps) - 1U;
417 if (tmp > 0xFFFFU)
418 {
419 return kStatus_SPI_BaudrateNotSupport;
420 }
421 base->DIV &= ~SPI_DIV_DIVVAL_MASK;
422 base->DIV |= SPI_DIV_DIVVAL(tmp);
423 return kStatus_Success;
424 }
425
426 /*!
427 * brief Writes a data control info and data into the SPI TX register directly.
428 *
429 * param base SPI base pointer
430 * param value needs to be write.
431 */
SPI_WriteDataWithConfigFlags(SPI_Type * base,uint16_t data,uint32_t configFlags)432 void SPI_WriteDataWithConfigFlags(SPI_Type *base, uint16_t data, uint32_t configFlags)
433 {
434 uint32_t control = 0;
435 /* check params */
436 assert(NULL != base);
437 /* Read origin command from TXCTL register. */
438 control = base->TXCTL & (~(SPI_TXDATCTL_EOT_MASK | SPI_TXDATCTL_EOF_MASK | SPI_TXDATCTL_RXIGNORE_MASK));
439 /* Mask configFlags */
440 control |= (configFlags & (SPI_TXDATCTL_EOT_MASK | SPI_TXDATCTL_EOF_MASK | SPI_TXDATCTL_RXIGNORE_MASK));
441 /* Write data and command to register. */
442 base->TXDATCTL = (data | control);
443 }
444
445 /*!
446 * brief Transfers a block of data using a polling method.
447 *
448 * param base SPI base pointer
449 * param xfer pointer to spi_xfer_config_t structure
450 * retval kStatus_Success Successfully start a transfer.
451 * retval kStatus_InvalidArgument Input argument is invalid.
452 * retval kStatus_SPI_Timeout The transfer timed out and was aborted.
453 */
SPI_MasterTransferBlocking(SPI_Type * base,spi_transfer_t * xfer)454 status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
455 {
456 uint32_t tx_ctrl = 0, last_ctrl = 0;
457 uint32_t tmp32, remainingBytes, dataWidth;
458 uint32_t instance = SPI_GetInstance(base);
459 #if SPI_RETRY_TIMES
460 uint32_t waitTimes;
461 #endif
462 /* Check params */
463 assert(!((NULL == base) || (NULL == xfer) || ((NULL == xfer->txData) && (NULL == xfer->rxData))));
464
465 remainingBytes = xfer->dataSize;
466 /* Read datawidth and ssel info from TXCTL. */
467 tx_ctrl = base->TXCTL & (SPI_TXCTL_LEN_MASK | (uint32_t)kSPI_SselDeAssertAll);
468 dataWidth = ((tx_ctrl & SPI_TXCTL_LEN_MASK) >> SPI_TXCTL_LEN_SHIFT);
469
470 /* Set end of frame configuration. */
471 tx_ctrl |= ((xfer->configFlags & (uint32_t)kSPI_EndOfFrame) != 0U) ? (uint32_t)kSPI_EndOfFrame : 0U;
472 /* Set ignore configuration. */
473 tx_ctrl |= (xfer->configFlags & (uint32_t)kSPI_ReceiveIgnore);
474
475 /* If rxData is NULL, ignore the receive. */
476 if (NULL == xfer->rxData)
477 {
478 tx_ctrl |= (uint32_t)kSPI_ReceiveIgnore;
479 }
480
481 /* Setup last command for transfer. */
482 last_ctrl = tx_ctrl;
483 /* Set end of transfer configuration for last command. */
484 last_ctrl |= ((xfer->configFlags & (uint32_t)kSPI_EndOfTransfer) != 0U) ? (uint32_t)kSPI_EndOfTransfer : 0U;
485
486 /* If only on frame to be sent, set the command to last command. */
487 if (((remainingBytes == 1U) && (dataWidth < (uint32_t)kSPI_Data9Bits)) ||
488 ((remainingBytes == 2U) && (dataWidth >= (uint32_t)kSPI_Data9Bits)))
489 {
490 SPI_WriteConfigFlags(base, last_ctrl);
491 }
492 else
493 {
494 SPI_WriteConfigFlags(base, tx_ctrl);
495 }
496
497 /* Index of loop */
498 while (remainingBytes != 0U)
499 {
500 tmp32 = 0U;
501 #if SPI_RETRY_TIMES
502 waitTimes = SPI_RETRY_TIMES;
503 while (((base->STAT & SPI_STAT_TXRDY_MASK) == 0U) && (--waitTimes != 0U))
504 #else
505 while ((base->STAT & SPI_STAT_TXRDY_MASK) == 0U)
506 #endif
507 {
508 }
509 #if SPI_RETRY_TIMES
510 if (waitTimes == 0U)
511 {
512 return kStatus_SPI_Timeout;
513 }
514 #endif
515
516 /* If txdata is not NULL. */
517 if (xfer->txData != NULL)
518 {
519 tmp32 = *(xfer->txData++);
520 if (dataWidth > (uint32_t)kSPI_Data8Bits)
521 {
522 tmp32 |= ((uint32_t)(*(xfer->txData++))) << 8U;
523 }
524 }
525 else
526 {
527 tmp32 = (uint32_t)s_dummyData[instance];
528 }
529 if ((dataWidth > (uint32_t)kSPI_Data8Bits) ? (remainingBytes == 2U) : (remainingBytes == 1U))
530 {
531 base->TXDATCTL = (tmp32 | last_ctrl);
532 }
533 else
534 {
535 /* Write data to the Transmit register. */
536 base->TXDAT = tmp32;
537 }
538 /* If the RX ignore bits is not set. */
539 if ((xfer->configFlags & (uint32_t)kSPI_ReceiveIgnore) == 0U)
540 {
541 /* Read data from the receive register. */
542 #if SPI_RETRY_TIMES
543 waitTimes = SPI_RETRY_TIMES;
544 while (((base->STAT & SPI_STAT_RXRDY_MASK) == 0U) && (--waitTimes != 0U))
545 #else
546 while ((base->STAT & SPI_STAT_RXRDY_MASK) == 0U)
547 #endif
548 {
549 }
550 #if SPI_RETRY_TIMES
551 if (waitTimes == 0U)
552 {
553 return kStatus_SPI_Timeout;
554 }
555 #endif
556 tmp32 = base->RXDAT;
557
558 /* If receive buffer is not NULL. */
559 if (xfer->rxData != NULL)
560 {
561 *(xfer->rxData++) = (uint8_t)tmp32;
562 if (dataWidth > (uint32_t)kSPI_Data8Bits)
563 {
564 *(xfer->rxData++) = (uint8_t)(tmp32 >> 8U);
565 }
566 }
567 }
568 remainingBytes--;
569 if (dataWidth > (uint32_t)kSPI_Data8Bits)
570 {
571 remainingBytes--;
572 }
573 }
574
575 /* Note that: the MSTIDLE status is related to the EOT bit, if the EOT is not set, the MSTIDLE bit will never be set
576 * even though there is no data in the FIFO and no data will be shifted by the bus line. so, please don't check the
577 * MSTIDLE status if the EOT bit is not set.
578 */
579 if ((xfer->configFlags & (uint32_t)kSPI_EndOfTransfer) != 0U)
580 {
581 #if SPI_RETRY_TIMES
582 waitTimes = SPI_RETRY_TIMES;
583 while (((base->STAT & SPI_STAT_MSTIDLE_MASK) == 0U) && (--waitTimes != 0U))
584 #else
585 while ((base->STAT & SPI_STAT_MSTIDLE_MASK) == 0U)
586 #endif
587 {
588 }
589 #if SPI_RETRY_TIMES
590 if (waitTimes == 0U)
591 {
592 return kStatus_SPI_Timeout;
593 }
594 #endif
595 }
596 return kStatus_Success;
597 }
598
599 #if defined(FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS) && (FSL_SDK_ENABLE_SPI_DRIVER_TRANSACTIONAL_APIS)
600 /*!
601 * brief Initializes the SPI master handle.
602 *
603 * This function initializes the SPI master handle which can be used for other SPI master transactional APIs. Usually,
604 * for a specified SPI instance, call this API once to get the initialized handle.
605 *
606 * param base SPI peripheral base address.
607 * param handle SPI handle pointer.
608 * param callback Callback function.
609 * param userData User data.
610 */
SPI_MasterTransferCreateHandle(SPI_Type * base,spi_master_handle_t * handle,spi_master_callback_t callback,void * userData)611 status_t SPI_MasterTransferCreateHandle(SPI_Type *base,
612 spi_master_handle_t *handle,
613 spi_master_callback_t callback,
614 void *userData)
615 {
616 /* check 'base' and 'handle'. */
617 assert((NULL != base) || (NULL != handle));
618
619 /* Get SPI instance by 'base' param */
620 uint32_t instance = SPI_GetInstance(base);
621
622 (void)memset(handle, 0, sizeof(*handle));
623 handle->dataWidth = (uint8_t)((base->TXCTL & SPI_TXCTL_LEN_MASK) >> SPI_TXCTL_LEN_SHIFT);
624 handle->callback = callback;
625 handle->userData = userData;
626 s_spiHandle[instance] = handle;
627 s_spiMasterIsr = SPI_MasterTransferHandleIRQ;
628 /* Enable SPI NVIC */
629 (void)EnableIRQ(s_spiIRQ[instance]);
630
631 return kStatus_Success;
632 }
633
634 /*!
635 * brief Initializes the SPI slave handle.
636 *
637 * This function initializes the SPI slave handle which can be used for other SPI slave transactional APIs. Usually,
638 * for a specified SPI instance, call this API once to get the initialized handle.
639 *
640 * param base SPI peripheral base address.
641 * param handle SPI handle pointer.
642 * param callback Callback function.
643 * param userData User data.
644 */
SPI_SlaveTransferCreateHandle(SPI_Type * base,spi_slave_handle_t * handle,spi_slave_callback_t callback,void * userData)645 status_t SPI_SlaveTransferCreateHandle(SPI_Type *base,
646 spi_slave_handle_t *handle,
647 spi_slave_callback_t callback,
648 void *userData)
649 {
650 (void)SPI_MasterTransferCreateHandle(base, handle, callback, userData);
651 s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
652 return kStatus_Success;
653 }
654
655 /*!
656 * brief Performs a non-blocking SPI interrupt transfer.
657 *
658 * param base SPI peripheral base address.
659 * param handle pointer to spi_master_handle_t structure which stores the transfer state
660 * param xfer pointer to spi_xfer_config_t structure
661 * retval kStatus_Success Successfully start a transfer.
662 * retval kStatus_InvalidArgument Input argument is invalid.
663 * retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
664 */
SPI_MasterTransferNonBlocking(SPI_Type * base,spi_master_handle_t * handle,spi_transfer_t * xfer)665 status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
666 {
667 /* check params */
668 assert(
669 !((NULL == base) || (NULL == handle) || (NULL == xfer) || ((NULL == xfer->txData) && (NULL == xfer->rxData))));
670 uint16_t temp = 0U;
671 uint32_t instance;
672
673 /* dataSize (in bytes) is not aligned to 16bit (2B) transfer */
674 if ((handle->dataWidth > (uint8_t)kSPI_Data8Bits) && ((xfer->dataSize & 0x1U) != 0U))
675 {
676 return kStatus_InvalidArgument;
677 }
678
679 /* Check if SPI is busy */
680 if (handle->state == (uint32_t)kStatus_SPI_Busy)
681 {
682 return kStatus_SPI_Busy;
683 }
684
685 /* Set the handle information */
686 handle->txData = xfer->txData;
687 handle->rxData = xfer->rxData;
688 /* Set count */
689 handle->txRemainingBytes = (NULL == xfer->txData) ? 0U : xfer->dataSize;
690 handle->rxRemainingBytes = (NULL == xfer->rxData) ? 0U : xfer->dataSize;
691 handle->totalByteCount = xfer->dataSize;
692 /* If the rxData is NULL, ignore the receive. */
693 if (NULL == xfer->rxData)
694 {
695 xfer->configFlags |= (uint32_t)kSPI_ReceiveIgnore;
696 }
697
698 /* If only on frame to be sent, set the command to last command. */
699 if (((xfer->dataSize == 1U) && (handle->dataWidth < (uint8_t)kSPI_Data9Bits)) ||
700 ((xfer->dataSize == 2U) && (handle->dataWidth >= (uint8_t)kSPI_Data9Bits)))
701 {
702 SPI_WriteConfigFlags(base, xfer->configFlags);
703 }
704 else
705 {
706 SPI_WriteConfigFlags(base, (xfer->configFlags & (~SPI_TXDATCTL_EOT_MASK)));
707 }
708
709 /* Set the last command. */
710 handle->lastCommand = base->TXCTL & (SPI_TXCTL_LEN_MASK | SPI_TXCTL_RXIGNORE_MASK | SPI_TXCTL_EOF_MASK |
711 SPI_TXCTL_EOT_MASK | (uint32_t)kSPI_SselDeAssertAll);
712 if ((xfer->configFlags & (uint32_t)kSPI_EndOfTransfer) != 0U)
713 {
714 handle->lastCommand |= SPI_TXDATCTL_EOT_MASK;
715 }
716 /* Set the SPI state to busy */
717 handle->state = (uint32_t)kStatus_SPI_Busy;
718
719 /* Write data to TXDAT register to trigger a SPI receive. */
720 if (NULL == handle->txData)
721 {
722 instance = SPI_GetInstance(base);
723 temp = s_dummyData[instance];
724 }
725 else
726 {
727 temp = *handle->txData++;
728 handle->txRemainingBytes--;
729 if (handle->dataWidth > (uint8_t)kSPI_Data8Bits)
730 {
731 temp |= (uint16_t)(*handle->txData++) << 8U;
732 handle->txRemainingBytes--;
733 }
734 }
735
736 SPI_WriteData(base, temp);
737
738 /* Enable generating IRQ.
739 * If RX ignore bit was set, only enable TX ready interrupt, otherwise,
740 * enable RX ready interrupt.
741 */
742 if (((uint32_t)kSPI_ReceiveIgnore & xfer->configFlags) != 0U)
743 {
744 SPI_EnableInterrupts(base, (uint32_t)kSPI_TxReadyInterruptEnable);
745 }
746 else
747 {
748 SPI_EnableInterrupts(base, (uint32_t)kSPI_RxReadyInterruptEnable);
749 }
750
751 return kStatus_Success;
752 }
753
754 /*!
755 * brief Performs a non-blocking SPI slave interrupt transfer.
756 *
757 * note The API returns immediately after the transfer initialization is finished.
758 *
759 * param base SPI peripheral base address.
760 * param handle pointer to spi_master_handle_t structure which stores the transfer state
761 * param xfer pointer to spi_xfer_config_t structure
762 * retval kStatus_Success Successfully start a transfer.
763 * retval kStatus_InvalidArgument Input argument is invalid.
764 * retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
765 */
SPI_SlaveTransferNonBlocking(SPI_Type * base,spi_slave_handle_t * handle,spi_transfer_t * xfer)766 status_t SPI_SlaveTransferNonBlocking(SPI_Type *base, spi_slave_handle_t *handle, spi_transfer_t *xfer)
767 {
768 status_t status = kStatus_Success;
769
770 s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
771 status = SPI_MasterTransferNonBlocking(base, handle, xfer);
772
773 return status;
774 }
775
776 /*!
777 * brief Gets the master transfer count.
778 *
779 * This function gets the master transfer count.
780 *
781 * param base SPI peripheral base address.
782 * param handle Pointer to the spi_master_handle_t structure which stores the transfer state.
783 * param count The number of bytes transferred by using the non-blocking transaction.
784 * return status of status_t.
785 */
SPI_MasterTransferGetCount(SPI_Type * base,spi_master_handle_t * handle,size_t * count)786 status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
787 {
788 assert(NULL != handle);
789
790 if (count == NULL)
791 {
792 return kStatus_InvalidArgument;
793 }
794
795 /* Catch when there is not an active transfer. */
796 if (handle->state != (uint32_t)kStatus_SPI_Busy)
797 {
798 *count = 0U;
799 return kStatus_NoTransferInProgress;
800 }
801
802 *count = handle->totalByteCount - handle->rxRemainingBytes;
803 return kStatus_Success;
804 }
805
806 /*!
807 * brief SPI master aborts a transfer using an interrupt.
808 *
809 * This function aborts a transfer using an interrupt.
810 *
811 * param base SPI peripheral base address.
812 * param handle Pointer to the spi_master_handle_t structure which stores the transfer state.
813 */
SPI_MasterTransferAbort(SPI_Type * base,spi_master_handle_t * handle)814 void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
815 {
816 assert(NULL != handle);
817
818 SPI_DisableInterrupts(base, (uint32_t)kSPI_TxReadyInterruptEnable | (uint32_t)kSPI_RxReadyInterruptEnable);
819
820 handle->state = (uint32_t)kStatus_SPI_Idle;
821 handle->txRemainingBytes = 0U;
822 handle->rxRemainingBytes = 0U;
823 }
824
825 /*!
826 * brief Interrupts the handler for the SPI.
827 *
828 * param base SPI peripheral base address.
829 * param handle pointer to spi_master_handle_t structure which stores the transfer state.
830 */
SPI_MasterTransferHandleIRQ(SPI_Type * base,spi_master_handle_t * handle)831 void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
832 {
833 assert((NULL != base) && (NULL != handle));
834
835 /* IRQ behaviour:
836 * - First interrupt is triggered by receive ready interrupt. The transfer function then
837 * tries read data and transmit data interleaved that results to strategy to process
838 * as many items as possible.
839 * - In last interrupt, the last state is known by empty rxBuffer and txBuffer. If there
840 * is nothing to receive or send - both operations have been finished and interrupts can be disabled.
841 * If the callback function is not NULL, trigger it.
842 */
843
844 /* Data to send or read or expected to receive */
845 if ((handle->rxRemainingBytes) != 0U)
846 {
847 SPI_ReceiveTransfer(base, handle);
848 }
849 if ((handle->txRemainingBytes) != 0U)
850 {
851 SPI_SendTransfer(base, handle);
852 }
853 if ((0U == handle->txRemainingBytes) && (0U == handle->rxRemainingBytes))
854 {
855 /* Only finalize the transfer when kSPI_TxReadyFlag is set which means
856 the tx register is empty and all data is sent out to bus */
857 if ((SPI_GetStatusFlags(base) & (uint32_t)kSPI_TxReadyFlag) != 0U)
858 {
859 /* Disable TX and RX interrupt. */
860 SPI_DisableInterrupts(base, (uint32_t)kSPI_RxReadyInterruptEnable | (uint32_t)kSPI_TxReadyInterruptEnable);
861
862 /* Set transfer state to idle. */
863 handle->state = (uint32_t)kStatus_SPI_Idle;
864 /* If callback is not NULL, call this function. */
865 if (handle->callback != NULL)
866 {
867 (handle->callback)(base, handle, handle->state, handle->userData);
868 }
869 }
870 }
871 }
872
873 /*!
874 * brief Interrupts a handler for the SPI slave.
875 *
876 * param base SPI peripheral base address.
877 * param handle pointer to spi_slave_handle_t structure which stores the transfer state
878 */
SPI_SlaveTransferHandleIRQ(SPI_Type * base,spi_slave_handle_t * handle)879 void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
880 {
881 assert((NULL != base) && (NULL != handle));
882
883 /* IRQ behaviour:
884 * - First interrupt is triggered by receive ready interrupt. The transfer function then
885 * tries read data and transmit data interleaved that results to strategy to process
886 * as many items as possible.
887 * - In the last interrupt, the last state is known by empty rxBuffer. If there is nothing
888 * to receive or send - both operations have been finished and interrupt can be disabled.
889 * If the callback function is not NULL, call it.
890 */
891
892 /* Sending data to TXDAT first in case of data missing. */
893 if (handle->txRemainingBytes != 0U)
894 {
895 SPI_SendTransfer(base, handle);
896 }
897
898 /* Read data from RXDAT. */
899 if (handle->rxRemainingBytes != 0U)
900 {
901 SPI_ReceiveTransfer(base, handle);
902 }
903
904 if ((0U == handle->txRemainingBytes) && (0U == handle->rxRemainingBytes))
905 {
906 /* Only finalize the transfer when kSPI_TxReadyFlag is set which means
907 the tx register is empty and all data is sent out to bus */
908 if ((SPI_GetStatusFlags(base) & (uint32_t)kSPI_TxReadyFlag) != 0U)
909 {
910 /* Disable RX interrupt. */
911 SPI_DisableInterrupts(base, (uint32_t)kSPI_RxReadyInterruptEnable | (uint32_t)kSPI_TxReadyInterruptEnable);
912 /* Set transfer state to idle. */
913 handle->state = (uint32_t)kStatus_SPI_Idle;
914 /* If callback is not NULL, call this function. */
915 if (handle->callback != NULL)
916 {
917 (handle->callback)(base, handle, handle->state, handle->userData);
918 }
919 }
920 }
921 }
922
SPI_CommonIRQHandler(SPI_Type * base,void * param)923 static void SPI_CommonIRQHandler(SPI_Type *base, void *param)
924 {
925 if (SPI_IsMaster(base))
926 {
927 s_spiMasterIsr(base, (spi_master_handle_t *)param);
928 }
929 else
930 {
931 s_spiSlaveIsr(base, (spi_slave_handle_t *)param);
932 }
933 }
934
935 #if defined(SPI0)
936 void SPI0_DriverIRQHandler(void);
SPI0_DriverIRQHandler(void)937 void SPI0_DriverIRQHandler(void)
938 {
939 assert(s_spiHandle[0] != NULL);
940 SPI_CommonIRQHandler(SPI0, s_spiHandle[0]);
941 }
942 #endif
943
944 #if defined(SPI1)
945 void SPI1_DriverIRQHandler(void);
SPI1_DriverIRQHandler(void)946 void SPI1_DriverIRQHandler(void)
947 {
948 assert(s_spiHandle[1] != NULL);
949 SPI_CommonIRQHandler(SPI1, s_spiHandle[1]);
950 }
951 #endif
952 #endif /* FSL_SDK_ENABLE_SPI_TRANSACTIONAL_API */
953