1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2020 NXP
4 * All rights reserved.
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.spi"
18 #endif
19
20 /*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
21 enum _spi_transfer_states_t
22 {
23 kSPI_Idle = 0x0, /*!< SPI is idle state */
24 kSPI_Busy /*!< SPI is busy tranferring data. */
25 };
26
27 /*! @brief Typedef for spi master interrupt handler. spi master and slave handle is the same. */
28 typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle);
29
30 /*******************************************************************************
31 * Prototypes
32 ******************************************************************************/
33
34 /*!
35 * @brief Sends a buffer of data bytes in non-blocking way.
36 *
37 * @param base SPI base pointer
38 * @param buffer The data bytes to send
39 * @param size The number of data bytes to send
40 */
41 static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
42
43 /*!
44 * @brief Receive a buffer of data bytes in non-blocking way.
45 *
46 * @param base SPI base pointer
47 * @param buffer The data bytes to send
48 * @param size The number of data bytes to send
49 */
50 static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
51
52 /*!
53 * @brief Get the waterrmark value for this SPI instance.
54 *
55 * @param base SPI base pointer
56 * @return Watermark value for the SPI instance.
57 */
58 static uint8_t SPI_GetWatermark(SPI_Type *base);
59
60 /*!
61 * @brief Send a piece of data for SPI.
62 *
63 * This function computes the number of data to be written into D register or Tx FIFO,
64 * and write the data into it. At the same time, this function updates the values in
65 * master handle structure.
66 *
67 * @param base SPI base pointer
68 * @param handle Pointer to SPI master handle structure.
69 */
70 static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
71
72 /*!
73 * @brief Receive a piece of data for SPI master.
74 *
75 * This function computes the number of data to receive from D register or Rx FIFO,
76 * and write the data to destination address. At the same time, this function updates
77 * the values in master handle structure.
78 *
79 * @param base SPI base pointer
80 * @param handle Pointer to SPI master handle structure.
81 */
82 static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle);
83
84 /*!
85 * @brief Common IRQ handler for SPI.
86 *
87 * @param base SPI base pointer.
88 * @param instance SPI instance number.
89 */
90 static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance);
91 /*******************************************************************************
92 * Variables
93 ******************************************************************************/
94 /*! @brief SPI internal handle pointer array */
95 static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT];
96 /*! @brief Base pointer array */
97 static SPI_Type *const s_spiBases[] = SPI_BASE_PTRS;
98 /*! @brief IRQ name array */
99 static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
100 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
101 /*! @brief Clock array name */
102 static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS;
103 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
104
105 /*! @brief Pointer to master IRQ handler for each instance. */
106 static spi_isr_t s_spiMasterIsr;
107 static spi_isr_t s_spiSlaveIsr;
108
109 /* @brief Dummy data for each instance. This data is used when user's tx buffer is NULL*/
110 volatile uint8_t g_spiDummyData[ARRAY_SIZE(s_spiBases)] = {0};
111 /*******************************************************************************
112 * Code
113 ******************************************************************************/
114 /*!
115 * brief Get the instance for SPI module.
116 *
117 * param base SPI base address
118 */
SPI_GetInstance(SPI_Type * base)119 uint32_t SPI_GetInstance(SPI_Type *base)
120 {
121 uint32_t instance;
122
123 /* Find the instance index from base address mappings. */
124 for (instance = 0; instance < ARRAY_SIZE(s_spiBases); instance++)
125 {
126 if (s_spiBases[instance] == base)
127 {
128 break;
129 }
130 }
131
132 assert(instance < ARRAY_SIZE(s_spiBases));
133
134 return instance;
135 }
136
137 /*!
138 * brief Set up the dummy data.
139 *
140 * param base SPI peripheral address.
141 * param dummyData Data to be transferred when tx buffer is NULL.
142 */
SPI_SetDummyData(SPI_Type * base,uint8_t dummyData)143 void SPI_SetDummyData(SPI_Type *base, uint8_t dummyData)
144 {
145 uint32_t instance = SPI_GetInstance(base);
146 g_spiDummyData[instance] = dummyData;
147 }
148
SPI_WriteNonBlocking(SPI_Type * base,uint8_t * buffer,size_t size)149 static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
150 {
151 uint32_t i = 0;
152 uint8_t bytesPerFrame = 1U;
153 uint32_t instance = SPI_GetInstance(base);
154
155 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
156 /* Check if 16 bits or 8 bits */
157 bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
158 #endif
159
160 while (i < size)
161 {
162 if (buffer != NULL)
163 {
164 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
165 base->DL = *buffer++;
166 /*16 bit mode*/
167 if ((base->C2 & SPI_C2_SPIMODE_MASK) != 0U)
168 {
169 base->DH = *buffer++;
170 }
171 #else
172 base->D = *buffer++;
173 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
174 }
175 /* Send dummy data */
176 else
177 {
178 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
179 base->DL = g_spiDummyData[instance] & 0xFFU;
180 base->DH = g_spiDummyData[instance] & 0xFFU;
181 #else
182 base->D = g_spiDummyData[instance] & 0xFFU;
183 #endif
184 }
185 i += bytesPerFrame;
186 }
187 }
188
SPI_ReadNonBlocking(SPI_Type * base,uint8_t * buffer,size_t size)189 static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
190 {
191 uint32_t i = 0U;
192 uint8_t bytesPerFrame = 1U;
193
194 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
195 /* Check if 16 bits or 8 bits */
196 bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
197 #endif
198
199 while (i < size)
200 {
201 if (buffer != NULL)
202 {
203 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
204 *buffer++ = base->DL;
205 /*16 bit mode*/
206 if ((base->C2 & SPI_C2_SPIMODE_MASK) != 0U)
207 {
208 *buffer++ = base->DH;
209 }
210 #else
211 *buffer++ = base->D;
212 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
213 }
214 else
215 {
216 (void)SPI_ReadData(base);
217 }
218 i += bytesPerFrame;
219 }
220 }
221
222 /* Get the watermark value of transfer. Please note that the entery width of FIFO is 16 bits. */
SPI_GetWatermark(SPI_Type * base)223 static uint8_t SPI_GetWatermark(SPI_Type *base)
224 {
225 uint8_t ret = 0U;
226 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
227 uint8_t rxSize = 0U;
228 /* Get the number to be sent if there is FIFO */
229 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
230 {
231 rxSize = (base->C3 & SPI_C3_RNFULLF_MARK_MASK) >> SPI_C3_RNFULLF_MARK_SHIFT;
232 if (rxSize == 0U)
233 {
234 ret = (uint8_t)FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
235 }
236 else
237 {
238 ret = (uint8_t)FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
239 }
240 }
241 /* If no FIFO, just set the watermark to 1 */
242 else
243 {
244 ret = 1U;
245 }
246 #else
247 ret = 1U;
248 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
249 return ret;
250 }
251
SPI_SendInitialTransfer(SPI_Type * base,spi_master_handle_t * handle)252 static void SPI_SendInitialTransfer(SPI_Type *base, spi_master_handle_t *handle)
253 {
254 uint8_t bytestoTransfer = handle->bytePerFrame;
255
256 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
257 if (handle->watermark > 1U)
258 {
259 /* In the first time to send data to FIFO, if transfer size is not larger than
260 * the FIFO size, send all data to FIFO, or send data to make the FIFO full.
261 * Besides, The FIFO's entry width is 16 bits, need to translate it to bytes.
262 */
263 int32_t fifosize = FSL_FEATURE_SPI_FIFO_SIZEn(base);
264 assert(fifosize > 0);
265 bytestoTransfer = (uint8_t)MIN(handle->txRemainingBytes, ((uint32_t)fifosize * 2U));
266 }
267 #endif
268
269 SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
270
271 /* Update handle information */
272 if (handle->txData != NULL)
273 {
274 handle->txData += bytestoTransfer;
275 }
276 handle->txRemainingBytes -= bytestoTransfer;
277 }
278
SPI_SendTransfer(SPI_Type * base,spi_master_handle_t * handle)279 static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle)
280 {
281 uint8_t bytes = handle->bytePerFrame;
282
283 /* Read S register and ensure SPTEF is 1, otherwise the write would be ignored. */
284 if (handle->watermark == 1U)
285 {
286 /* Send data */
287 if ((base->C1 & SPI_C1_MSTR_MASK) != 0U)
288 {
289 /* As a master, only write once */
290 if ((base->S & SPI_S_SPTEF_MASK) != 0U)
291 {
292 SPI_WriteNonBlocking(base, handle->txData, bytes);
293 /* Update handle information */
294 if (handle->txData != NULL)
295 {
296 handle->txData += bytes;
297 }
298 handle->txRemainingBytes -= bytes;
299 }
300 }
301 else
302 {
303 /* As a slave, send data until SPTEF cleared */
304 while (((base->S & SPI_S_SPTEF_MASK) != 0U) && (handle->txRemainingBytes >= bytes))
305 {
306 SPI_WriteNonBlocking(base, handle->txData, bytes);
307
308 /* Update handle information */
309 if (handle->txData != NULL)
310 {
311 handle->txData += bytes;
312 }
313 handle->txRemainingBytes -= bytes;
314 }
315 }
316 }
317
318 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
319 /* If use FIFO */
320 else
321 {
322 /* The FIFO's entry width is 16 bits, need to translate it to bytes. */
323 uint8_t bytestoTransfer = (uint8_t)handle->watermark * 2U;
324
325 if (handle->txRemainingBytes < 8U)
326 {
327 bytestoTransfer = (uint8_t)handle->txRemainingBytes;
328 }
329
330 SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
331
332 /* Update handle information */
333 if (handle->txData != NULL)
334 {
335 handle->txData += bytestoTransfer;
336 }
337 handle->txRemainingBytes -= bytestoTransfer;
338 }
339 #endif
340 }
341
SPI_ReceiveTransfer(SPI_Type * base,spi_master_handle_t * handle)342 static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle)
343 {
344 uint8_t bytes = handle->bytePerFrame;
345
346 /* Read S register and ensure SPRF is 1, otherwise the write would be ignored. */
347 if (handle->watermark == 1U)
348 {
349 if ((base->S & SPI_S_SPRF_MASK) != 0U)
350 {
351 SPI_ReadNonBlocking(base, handle->rxData, bytes);
352
353 /* Update information in handle */
354 if (handle->rxData != NULL)
355 {
356 handle->rxData += bytes;
357 }
358 handle->rxRemainingBytes -= bytes;
359 }
360 }
361 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
362 /* If use FIFO */
363 else
364 {
365 /* While rx fifo not empty and remaining data can also trigger the last interrupt */
366 while ((base->S & SPI_S_RFIFOEF_MASK) == 0U)
367 {
368 SPI_ReadNonBlocking(base, handle->rxData, bytes);
369
370 /* Update information in handle */
371 if (handle->rxData != NULL)
372 {
373 handle->rxData += bytes;
374 }
375 handle->rxRemainingBytes -= bytes;
376
377 /* If the reamining data equals to watermark, leave to last interrupt */
378 if (handle->rxRemainingBytes == ((uint32_t)handle->watermark * 2U))
379 {
380 break;
381 }
382 }
383 }
384 #endif
385 }
386
387 /*!
388 * brief Sets the SPI master configuration structure to default values.
389 *
390 * The purpose of this API is to get the configuration structure initialized for use in SPI_MasterInit().
391 * User may use the initialized structure unchanged in SPI_MasterInit(), or modify
392 * some fields of the structure before calling SPI_MasterInit(). After calling this API,
393 * the master is ready to transfer.
394 * Example:
395 code
396 spi_master_config_t config;
397 SPI_MasterGetDefaultConfig(&config);
398 endcode
399 *
400 * param config pointer to master config structure
401 */
SPI_MasterGetDefaultConfig(spi_master_config_t * config)402 void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
403 {
404 /* Initializes the configure structure to zero. */
405 (void)(void) memset(config, 0, sizeof(*config));
406
407 config->enableMaster = true;
408 config->enableStopInWaitMode = false;
409 config->polarity = kSPI_ClockPolarityActiveHigh;
410 config->phase = kSPI_ClockPhaseFirstEdge;
411 config->direction = kSPI_MsbFirst;
412
413 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
414 config->dataMode = kSPI_8BitMode;
415 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
416
417 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
418 config->txWatermark = kSPI_TxFifoOneHalfEmpty;
419 config->rxWatermark = kSPI_RxFifoOneHalfFull;
420 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
421
422 config->pinMode = kSPI_PinModeNormal;
423 config->outputMode = kSPI_SlaveSelectAutomaticOutput;
424 config->baudRate_Bps = 500000U;
425 }
426
427 /*!
428 * brief Initializes the SPI with master configuration.
429 *
430 * The configuration structure can be filled by user from scratch, or be set with default
431 * values by SPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
432 * Example
433 code
434 spi_master_config_t config = {
435 .baudRate_Bps = 400000,
436 ...
437 };
438 SPI_MasterInit(SPI0, &config);
439 endcode
440 *
441 * param base SPI base pointer
442 * param config pointer to master configuration structure
443 * param srcClock_Hz Source clock frequency.
444 */
SPI_MasterInit(SPI_Type * base,const spi_master_config_t * config,uint32_t srcClock_Hz)445 void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
446 {
447 assert((config != NULL) && (srcClock_Hz != 0U));
448
449 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
450 /* Open clock gate for SPI and open interrupt */
451 CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
452 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
453
454 /* Disable SPI before configuration */
455 base->C1 &= (uint8_t)(~SPI_C1_SPE_MASK);
456
457 /* Configure clock polarity and phase, set SPI to master */
458 base->C1 = SPI_C1_MSTR(1U) | SPI_C1_CPOL(config->polarity) | SPI_C1_CPHA(config->phase) |
459 SPI_C1_SSOE((uint8_t)config->outputMode & 1U) | SPI_C1_LSBFE((uint8_t)config->direction);
460
461 /* Set data mode, and also pin mode and mode fault settings */
462 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
463 base->C2 = SPI_C2_MODFEN((uint8_t)config->outputMode >> 1U) | SPI_C2_BIDIROE((uint8_t)config->pinMode >> 1U) |
464 SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_SPC0((uint8_t)config->pinMode & 1U) |
465 SPI_C2_SPIMODE(config->dataMode);
466 #else
467 base->C2 = SPI_C2_MODFEN((uint8_t)config->outputMode >> 1U) | SPI_C2_BIDIROE((uint8_t)config->pinMode >> 1U) |
468 SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_SPC0((uint8_t)config->pinMode & 1U);
469 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
470
471 /* Set watermark, FIFO is enabled */
472 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
473 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
474 {
475 base->C3 = SPI_C3_TNEAREF_MARK(config->txWatermark) | SPI_C3_RNFULLF_MARK(config->rxWatermark) |
476 SPI_C3_INTCLR(0U) | SPI_C3_FIFOMODE(1U);
477 }
478 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
479
480 /* Set baud rate */
481 SPI_MasterSetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
482
483 /* Set the dummy data, this data will usefull when tx buffer is NULL. */
484 SPI_SetDummyData(base, SPI_DUMMYDATA);
485
486 /* Enable SPI */
487 if (config->enableMaster)
488 {
489 base->C1 |= SPI_C1_SPE_MASK;
490 }
491 }
492
493 /*!
494 * brief Sets the SPI slave configuration structure to default values.
495 *
496 * The purpose of this API is to get the configuration structure initialized for use in SPI_SlaveInit().
497 * Modify some fields of the structure before calling SPI_SlaveInit().
498 * Example:
499 code
500 spi_slave_config_t config;
501 SPI_SlaveGetDefaultConfig(&config);
502 endcode
503 *
504 * param config pointer to slave configuration structure
505 */
SPI_SlaveGetDefaultConfig(spi_slave_config_t * config)506 void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
507 {
508 /* Initializes the configure structure to zero. */
509 (void)(void) memset(config, 0, sizeof(*config));
510
511 config->enableSlave = true;
512 config->polarity = kSPI_ClockPolarityActiveHigh;
513 config->phase = kSPI_ClockPhaseFirstEdge;
514 config->direction = kSPI_MsbFirst;
515 config->enableStopInWaitMode = false;
516
517 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
518 config->dataMode = kSPI_8BitMode;
519 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
520
521 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
522 config->txWatermark = kSPI_TxFifoOneHalfEmpty;
523 config->rxWatermark = kSPI_RxFifoOneHalfFull;
524 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
525 config->pinMode = kSPI_PinModeNormal;
526 }
527
528 /*!
529 * brief Initializes the SPI with slave configuration.
530 *
531 * The configuration structure can be filled by user from scratch or be set with
532 * default values by SPI_SlaveGetDefaultConfig().
533 * After calling this API, the slave is ready to transfer.
534 * Example
535 code
536 spi_slave_config_t config = {
537 .polarity = kSPIClockPolarity_ActiveHigh;
538 .phase = kSPIClockPhase_FirstEdge;
539 .direction = kSPIMsbFirst;
540 ...
541 };
542 SPI_MasterInit(SPI0, &config);
543 endcode
544 *
545 * param base SPI base pointer
546 * param config pointer to master configuration structure
547 */
SPI_SlaveInit(SPI_Type * base,const spi_slave_config_t * config)548 void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
549 {
550 assert(config != NULL);
551
552 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
553 /* Open clock gate for SPI and open interrupt */
554 CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
555 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
556
557 /* Disable SPI before configuration */
558 base->C1 &= (uint8_t)(~SPI_C1_SPE_MASK);
559
560 /* Configure master and clock polarity and phase */
561 base->C1 =
562 SPI_C1_MSTR(0U) | SPI_C1_CPOL(config->polarity) | SPI_C1_CPHA(config->phase) | SPI_C1_LSBFE(config->direction);
563
564 /* Configure data mode if needed */
565 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
566 base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode) |
567 SPI_C2_BIDIROE((uint8_t)config->pinMode >> 1U) | SPI_C2_SPC0((uint8_t)config->pinMode & 1U);
568 #else
569 base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_BIDIROE((uint8_t)config->pinMode >> 1U) |
570 SPI_C2_SPC0((uint8_t)config->pinMode & 1U);
571 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
572
573 /* Set watermark */
574 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
575 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
576 {
577 base->C3 = SPI_C3_TNEAREF_MARK(config->txWatermark) | SPI_C3_RNFULLF_MARK(config->rxWatermark) |
578 SPI_C3_INTCLR(0U) | SPI_C3_FIFOMODE(1U);
579 }
580 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
581
582 /* Set the dummy data, this data will usefull when tx buffer is NULL. */
583 SPI_SetDummyData(base, SPI_DUMMYDATA);
584
585 /* Enable SPI */
586 if (config->enableSlave)
587 {
588 base->C1 |= SPI_C1_SPE_MASK;
589 }
590 }
591
592 /*!
593 * brief De-initializes the SPI.
594 *
595 * Calling this API resets the SPI module, gates the SPI clock.
596 * The SPI module can't work unless calling the SPI_MasterInit/SPI_SlaveInit to initialize module.
597 *
598 * param base SPI base pointer
599 */
SPI_Deinit(SPI_Type * base)600 void SPI_Deinit(SPI_Type *base)
601 {
602 /* Disable SPI module before shutting down */
603 base->C1 &= (uint8_t)(~SPI_C1_SPE_MASK);
604
605 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
606 /* Gate the clock */
607 CLOCK_DisableClock(s_spiClock[SPI_GetInstance(base)]);
608 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
609 }
610
611 /*!
612 * brief Gets the status flag.
613 *
614 * param base SPI base pointer
615 * return SPI Status, use status flag to AND #_spi_flags could get the related status.
616 */
SPI_GetStatusFlags(SPI_Type * base)617 uint32_t SPI_GetStatusFlags(SPI_Type *base)
618 {
619 uint32_t status = (uint32_t)base->S;
620 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
621 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
622 {
623 status |= (((uint32_t)base->CI) << 8U);
624 }
625 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
626 return status;
627 }
628
629 /*!
630 * brief Enables the interrupt for the SPI.
631 *
632 * param base SPI base pointer
633 * param mask SPI interrupt source. The parameter can be any combination of the following values:
634 * arg kSPI_RxFullAndModfInterruptEnable
635 * arg kSPI_TxEmptyInterruptEnable
636 * arg kSPI_MatchInterruptEnable
637 * arg kSPI_RxFifoNearFullInterruptEnable
638 * arg kSPI_TxFifoNearEmptyInterruptEnable
639 */
SPI_EnableInterrupts(SPI_Type * base,uint32_t mask)640 void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
641 {
642 /* Rx full interrupt */
643 if ((mask & (uint32_t)kSPI_RxFullAndModfInterruptEnable) != 0U)
644 {
645 base->C1 |= SPI_C1_SPIE_MASK;
646 }
647
648 /* Tx empty interrupt */
649 if ((mask & (uint32_t)kSPI_TxEmptyInterruptEnable) != 0U)
650 {
651 base->C1 |= SPI_C1_SPTIE_MASK;
652 }
653
654 /* Data match interrupt */
655 if ((mask & (uint32_t)kSPI_MatchInterruptEnable) != 0U)
656 {
657 base->C2 |= SPI_C2_SPMIE_MASK;
658 }
659
660 /* FIFO related interrupts */
661 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
662 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
663 {
664 /* Rx FIFO near full interrupt */
665 if ((mask & (uint32_t)kSPI_RxFifoNearFullInterruptEnable) != 0U)
666 {
667 base->C3 |= SPI_C3_RNFULLIEN_MASK;
668 }
669
670 /* Tx FIFO near empty interrupt */
671 if ((mask & (uint32_t)kSPI_TxFifoNearEmptyInterruptEnable) != 0U)
672 {
673 base->C3 |= SPI_C3_TNEARIEN_MASK;
674 }
675 }
676 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
677 }
678
679 /*!
680 * brief Disables the interrupt for the SPI.
681 *
682 * param base SPI base pointer
683 * param mask SPI interrupt source. The parameter can be any combination of the following values:
684 * arg kSPI_RxFullAndModfInterruptEnable
685 * arg kSPI_TxEmptyInterruptEnable
686 * arg kSPI_MatchInterruptEnable
687 * arg kSPI_RxFifoNearFullInterruptEnable
688 * arg kSPI_TxFifoNearEmptyInterruptEnable
689 */
SPI_DisableInterrupts(SPI_Type * base,uint32_t mask)690 void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
691 {
692 /* Rx full interrupt */
693 if ((mask & (uint32_t)kSPI_RxFullAndModfInterruptEnable) != 0U)
694 {
695 base->C1 &= (uint8_t)(~SPI_C1_SPIE_MASK);
696 }
697
698 /* Tx empty interrupt */
699 if ((mask & (uint32_t)kSPI_TxEmptyInterruptEnable) != 0U)
700 {
701 base->C1 &= (uint8_t)(~SPI_C1_SPTIE_MASK);
702 }
703
704 /* Data match interrupt */
705 if ((mask & (uint32_t)kSPI_MatchInterruptEnable) != 0U)
706 {
707 base->C2 &= (uint8_t)(~SPI_C2_SPMIE_MASK);
708 }
709
710 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
711 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
712 {
713 /* Rx FIFO near full interrupt */
714 if ((mask & (uint32_t)kSPI_RxFifoNearFullInterruptEnable) != 0U)
715 {
716 base->C3 &= (uint8_t)(~SPI_C3_RNFULLIEN_MASK);
717 }
718
719 /* Tx FIFO near empty interrupt */
720 if ((mask & (uint32_t)kSPI_TxFifoNearEmptyInterruptEnable) != 0U)
721 {
722 base->C3 &= (uint8_t)(~SPI_C3_TNEARIEN_MASK);
723 }
724 }
725 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
726 }
727
728 /*!
729 * brief Sets the baud rate for SPI transfer. This is only used in master.
730 *
731 * param base SPI base pointer
732 * param baudRate_Bps baud rate needed in Hz.
733 * param srcClock_Hz SPI source clock frequency in Hz.
734 */
SPI_MasterSetBaudRate(SPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)735 void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
736 {
737 uint32_t prescaler;
738 uint32_t bestPrescaler;
739 uint32_t rateDivisor;
740 uint32_t bestDivisor;
741 uint32_t rateDivisorValue;
742 uint32_t realBaudrate;
743 uint32_t diff;
744 uint32_t min_diff;
745 uint32_t freq = baudRate_Bps;
746
747 /* Find combination of prescaler and scaler resulting in baudrate closest to the requested value */
748 min_diff = 0xFFFFFFFFU;
749
750 /* Set the maximum divisor bit settings for each of the following divisors */
751 bestPrescaler = 7U;
752 bestDivisor = 8U;
753
754 /* In all for loops, if min_diff = 0, the exit for loop*/
755 for (prescaler = 0U; prescaler <= 7U; prescaler++)
756 {
757 if (min_diff == 0U)
758 {
759 break;
760 }
761 /* Initialize to div-by-2 */
762 rateDivisorValue = 2U;
763
764 for (rateDivisor = 0; rateDivisor <= 8U; rateDivisor++)
765 {
766 if (min_diff == 0U)
767 {
768 break;
769 }
770 /* Calculate actual baud rate, note need to add 1 to prescaler */
771 realBaudrate = ((srcClock_Hz) / ((prescaler + 1U) * rateDivisorValue));
772
773 /* Calculate the baud rate difference based on the conditional statement ,that states that the
774 calculated baud rate must not exceed the desired baud rate */
775 if (freq >= realBaudrate)
776 {
777 diff = freq - realBaudrate;
778 if (min_diff > diff)
779 {
780 /* A better match found */
781 min_diff = diff;
782 bestPrescaler = prescaler;
783 bestDivisor = rateDivisor;
784 }
785 }
786
787 /* Multiply by 2 for each iteration, possible divisor values: 2, 4, 8, 16, ... 512 */
788 rateDivisorValue *= 2U;
789 }
790 }
791
792 /* Write the best prescalar and baud rate scalar */
793 base->BR = SPI_BR_SPR(bestDivisor) | SPI_BR_SPPR(bestPrescaler);
794 }
795
796 /*!
797 * brief Sends a buffer of data bytes using a blocking method.
798 *
799 * note This function blocks via polling until all bytes have been sent.
800 *
801 * param base SPI base pointer
802 * param buffer The data bytes to send
803 * param size The number of data bytes to send
804 * retval kStatus_Success Successfully start a transfer.
805 * retval kStatus_SPI_Timeout The transfer timed out and was aborted.
806 */
SPI_WriteBlocking(SPI_Type * base,uint8_t * buffer,size_t size)807 status_t SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
808 {
809 uint32_t i = 0;
810 uint8_t bytesPerFrame = 1U;
811
812 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
813 /* Check if 16 bits or 8 bits */
814 bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
815 #endif
816
817 #if SPI_RETRY_TIMES
818 uint32_t waitTimes;
819 #endif
820
821 while (i < size)
822 {
823 #if SPI_RETRY_TIMES
824 waitTimes = SPI_RETRY_TIMES;
825 while (((base->S & SPI_S_SPTEF_MASK) == 0U) && (--waitTimes != 0U))
826 #else
827 while ((base->S & SPI_S_SPTEF_MASK) == 0U)
828 #endif
829 {
830 }
831 #if SPI_RETRY_TIMES
832 if (waitTimes == 0U)
833 {
834 return kStatus_SPI_Timeout;
835 }
836 #endif
837
838 /* Send a frame of data */
839 SPI_WriteNonBlocking(base, buffer, bytesPerFrame);
840
841 i += bytesPerFrame;
842 buffer += bytesPerFrame;
843 }
844
845 return kStatus_Success;
846 }
847
848 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
849 /*!
850 * brief Enables or disables the FIFO if there is a FIFO.
851 *
852 * param base SPI base pointer
853 * param enable True means enable FIFO, false means disable FIFO.
854 */
SPI_EnableFIFO(SPI_Type * base,bool enable)855 void SPI_EnableFIFO(SPI_Type *base, bool enable)
856 {
857 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
858 {
859 if (enable)
860 {
861 base->C3 |= SPI_C3_FIFOMODE_MASK;
862 }
863 else
864 {
865 base->C3 &= (uint8_t)(~SPI_C3_FIFOMODE_MASK);
866 }
867 }
868 }
869 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
870
871 /*!
872 * brief Writes a data into the SPI data register.
873 *
874 * param base SPI base pointer
875 * param data needs to be write.
876 */
SPI_WriteData(SPI_Type * base,uint16_t data)877 void SPI_WriteData(SPI_Type *base, uint16_t data)
878 {
879 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
880 base->DL = (uint8_t)data & 0xFFU;
881 base->DH = (uint8_t)(data >> 8U) & 0xFFU;
882 #else
883 base->D = (uint8_t)data & 0xFFU;
884 #endif
885 }
886
887 /*!
888 * brief Gets a data from the SPI data register.
889 *
890 * param base SPI base pointer
891 * return Data in the register.
892 */
SPI_ReadData(SPI_Type * base)893 uint16_t SPI_ReadData(SPI_Type *base)
894 {
895 uint16_t val = 0;
896 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
897 val = base->DL;
898 val |= (uint16_t)((uint16_t)(base->DH) << 8U);
899 #else
900 val = base->D;
901 #endif
902 return val;
903 }
904
905 /*!
906 * brief Transfers a block of data using a polling method.
907 *
908 * param base SPI base pointer
909 * param xfer pointer to spi_xfer_config_t structure
910 * retval kStatus_Success Successfully start a transfer.
911 * retval kStatus_InvalidArgument Input argument is invalid.
912 * retval kStatus_SPI_Timeout The transfer timed out and was aborted.
913 */
SPI_MasterTransferBlocking(SPI_Type * base,spi_transfer_t * xfer)914 status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
915 {
916 assert(xfer != NULL);
917
918 uint8_t bytesPerFrame = 1U;
919 #if SPI_RETRY_TIMES
920 uint32_t waitTimes = SPI_RETRY_TIMES;
921 #endif
922
923 /* Check if the argument is legal */
924 if ((xfer->txData == NULL) && (xfer->rxData == NULL))
925 {
926 return (status_t)kStatus_InvalidArgument;
927 }
928
929 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
930 /* Check if 16 bits or 8 bits */
931 bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
932 #endif
933
934 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
935
936 /* Disable FIFO, as the FIFO may cause data loss if the data size is not integer
937 times of 2bytes. As SPI cannot set watermark to 0, only can set to 1/2 FIFO size or 3/4 FIFO
938 size. */
939 if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
940 {
941 base->C3 &= (uint8_t)(~SPI_C3_FIFOMODE_MASK);
942 }
943
944 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
945
946 /* Begin the polling transfer until all data sent */
947 while (xfer->dataSize > 0U)
948 {
949 /* Data send */
950 #if SPI_RETRY_TIMES
951 waitTimes = SPI_RETRY_TIMES;
952 while (((base->S & SPI_S_SPTEF_MASK) == 0U) && (--waitTimes != 0U))
953 {
954 }
955 if (waitTimes == 0U)
956 {
957 return kStatus_SPI_Timeout;
958 }
959 #else
960 while ((base->S & SPI_S_SPTEF_MASK) == 0U)
961 {
962 }
963 #endif
964 SPI_WriteNonBlocking(base, xfer->txData, bytesPerFrame);
965 if (xfer->txData != NULL)
966 {
967 xfer->txData += bytesPerFrame;
968 }
969
970 #if SPI_RETRY_TIMES
971 waitTimes = SPI_RETRY_TIMES;
972 while (((base->S & SPI_S_SPRF_MASK) == 0U) && (--waitTimes != 0U))
973 {
974 }
975 if (waitTimes == 0U)
976 {
977 return kStatus_SPI_Timeout;
978 }
979 #else
980 while ((base->S & SPI_S_SPRF_MASK) == 0U)
981 {
982 }
983 #endif
984 SPI_ReadNonBlocking(base, xfer->rxData, bytesPerFrame);
985 if (xfer->rxData != NULL)
986 {
987 xfer->rxData += bytesPerFrame;
988 }
989
990 /* Decrease the number */
991 xfer->dataSize -= bytesPerFrame;
992 }
993
994 return kStatus_Success;
995 }
996
997 /*!
998 * brief Initializes the SPI master handle.
999 *
1000 * This function initializes the SPI master handle which can be used for other SPI master transactional APIs. Usually,
1001 * for a specified SPI instance, call this API once to get the initialized handle.
1002 *
1003 * param base SPI peripheral base address.
1004 * param handle SPI handle pointer.
1005 * param callback Callback function.
1006 * param userData User data.
1007 */
SPI_MasterTransferCreateHandle(SPI_Type * base,spi_master_handle_t * handle,spi_master_callback_t callback,void * userData)1008 void SPI_MasterTransferCreateHandle(SPI_Type *base,
1009 spi_master_handle_t *handle,
1010 spi_master_callback_t callback,
1011 void *userData)
1012 {
1013 assert(handle != NULL);
1014
1015 uint32_t instance = SPI_GetInstance(base);
1016
1017 /* Zero the handle */
1018 (void)memset(handle, 0, sizeof(*handle));
1019
1020 /* Initialize the handle */
1021 s_spiHandle[instance] = handle;
1022 handle->callback = callback;
1023 handle->userData = userData;
1024 s_spiMasterIsr = SPI_MasterTransferHandleIRQ;
1025 handle->watermark = SPI_GetWatermark(base);
1026
1027 /* Get the bytes per frame */
1028 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
1029 handle->bytePerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
1030 #else
1031 handle->bytePerFrame = 1U;
1032 #endif
1033
1034 /* Enable SPI NVIC */
1035 (void)EnableIRQ(s_spiIRQ[instance]);
1036 }
1037
1038 /*!
1039 * brief Performs a non-blocking SPI interrupt transfer.
1040 *
1041 * note The API immediately returns after transfer initialization is finished.
1042 * Call SPI_GetStatusIRQ() to get the transfer status.
1043 * note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
1044 *
1045 * param base SPI peripheral base address.
1046 * param handle pointer to spi_master_handle_t structure which stores the transfer state
1047 * param xfer pointer to spi_xfer_config_t structure
1048 * retval kStatus_Success Successfully start a transfer.
1049 * retval kStatus_InvalidArgument Input argument is invalid.
1050 * retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
1051 */
SPI_MasterTransferNonBlocking(SPI_Type * base,spi_master_handle_t * handle,spi_transfer_t * xfer)1052 status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
1053 {
1054 assert((handle != NULL) && (xfer != NULL));
1055 uint32_t mask = 0U;
1056
1057 /* Check if SPI is busy */
1058 if (handle->state == (uint32_t)kSPI_Busy)
1059 {
1060 return (status_t)kStatus_SPI_Busy;
1061 }
1062
1063 /* Check if the input arguments valid */
1064 if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
1065 {
1066 return (status_t)kStatus_InvalidArgument;
1067 }
1068
1069 /* Set the handle information */
1070 handle->txData = xfer->txData;
1071 handle->rxData = xfer->rxData;
1072 handle->transferSize = xfer->dataSize;
1073 handle->txRemainingBytes = xfer->dataSize;
1074 handle->rxRemainingBytes = xfer->dataSize;
1075
1076 /* Set the SPI state to busy */
1077 handle->state = (uint32_t)kSPI_Busy;
1078
1079 /* Enable Interrupt */
1080 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
1081
1082 handle->watermark = SPI_GetWatermark(base);
1083
1084 /* If the size of the transfer size less than watermark, set watermark to 1 */
1085 if (xfer->dataSize < (uint32_t)handle->watermark * 2U)
1086 {
1087 handle->watermark = 1U;
1088 }
1089
1090 /* According to watermark size, enable interrupts */
1091 if (handle->watermark > 1U)
1092 {
1093 /* Enable Rx near full interrupt */
1094 mask = (uint32_t)kSPI_RxFifoNearFullInterruptEnable;
1095 /* Enable Tx near full interrupt only if there are data to send */
1096 if (handle->txData != NULL)
1097 {
1098 mask |= (uint32_t)kSPI_TxFifoNearEmptyInterruptEnable;
1099 }
1100
1101 SPI_EnableFIFO(base, true);
1102 /* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
1103 while ((base->S & SPI_S_TNEAREF_MASK) != SPI_S_TNEAREF_MASK)
1104 {
1105 }
1106 SPI_SendInitialTransfer(base, handle);
1107 }
1108 else
1109 {
1110 /* Enable Rx full interrupt */
1111 mask = (uint32_t)kSPI_RxFullAndModfInterruptEnable;
1112 /* Enable Tx full interrupt only if there are data to send */
1113 if (handle->txData != NULL)
1114 {
1115 mask |= (uint32_t)kSPI_TxEmptyInterruptEnable;
1116 }
1117
1118 SPI_EnableFIFO(base, false);
1119 while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
1120 {
1121 }
1122 /* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
1123 SPI_SendInitialTransfer(base, handle);
1124 }
1125 #else
1126 /* Enable Rx full interrupt */
1127 mask = (uint32_t)kSPI_RxFullAndModfInterruptEnable;
1128 /* Enable Tx full interrupt only if there are data to send */
1129 if (handle->txData != NULL)
1130 {
1131 mask |= (uint32_t)kSPI_TxEmptyInterruptEnable;
1132 }
1133
1134 while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
1135 {
1136 }
1137 /* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
1138 SPI_SendInitialTransfer(base, handle);
1139 #endif
1140
1141 SPI_EnableInterrupts(base, mask);
1142 return kStatus_Success;
1143 }
1144
1145 /*!
1146 * brief Gets the bytes of the SPI interrupt transferred.
1147 *
1148 * param base SPI peripheral base address.
1149 * param handle Pointer to SPI transfer handle, this should be a static variable.
1150 * param count Transferred bytes of SPI master.
1151 * retval kStatus_SPI_Success Succeed get the transfer count.
1152 * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
1153 */
SPI_MasterTransferGetCount(SPI_Type * base,spi_master_handle_t * handle,size_t * count)1154 status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
1155 {
1156 assert(handle != NULL);
1157
1158 status_t status = kStatus_Success;
1159
1160 if (handle->state != (uint32_t)kSPI_Busy)
1161 {
1162 status = (status_t)kStatus_NoTransferInProgress;
1163 }
1164 else
1165 {
1166 /* Return remaing bytes in different cases */
1167 if (handle->rxData != NULL)
1168 {
1169 *count = handle->transferSize - handle->rxRemainingBytes;
1170 }
1171 else
1172 {
1173 *count = handle->transferSize - handle->txRemainingBytes;
1174 }
1175 }
1176
1177 return status;
1178 }
1179
1180 /*!
1181 * brief Aborts an SPI transfer using interrupt.
1182 *
1183 * param base SPI peripheral base address.
1184 * param handle Pointer to SPI transfer handle, this should be a static variable.
1185 */
SPI_MasterTransferAbort(SPI_Type * base,spi_master_handle_t * handle)1186 void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
1187 {
1188 assert(handle != NULL);
1189 uint32_t mask = (uint32_t)kSPI_TxEmptyInterruptEnable;
1190
1191 /* Stop interrupts */
1192 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
1193 if (handle->watermark > 1U)
1194 {
1195 mask |= (uint32_t)kSPI_RxFifoNearFullInterruptEnable | (uint32_t)kSPI_TxFifoNearEmptyInterruptEnable;
1196 }
1197 else
1198 {
1199 mask |= (uint32_t)kSPI_RxFullAndModfInterruptEnable | (uint32_t)kSPI_TxEmptyInterruptEnable;
1200 }
1201 #else
1202 mask |= (uint32_t)kSPI_RxFullAndModfInterruptEnable | (uint32_t)kSPI_TxEmptyInterruptEnable;
1203 #endif
1204
1205 SPI_DisableInterrupts(base, mask);
1206 /* Transfer finished, set the state to Done*/
1207 handle->state = (uint32_t)kSPI_Idle;
1208
1209 /* Clear the internal state */
1210 handle->rxRemainingBytes = 0;
1211 handle->txRemainingBytes = 0;
1212 }
1213
1214 /*!
1215 * brief Interrupts the handler for the SPI.
1216 *
1217 * param base SPI peripheral base address.
1218 * param handle pointer to spi_master_handle_t structure which stores the transfer state.
1219 */
SPI_MasterTransferHandleIRQ(SPI_Type * base,spi_master_handle_t * handle)1220 void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
1221 {
1222 assert(handle != NULL);
1223
1224 /* If needs to receive data, do a receive */
1225 if ((handle->rxRemainingBytes) != 0U)
1226 {
1227 SPI_ReceiveTransfer(base, handle);
1228 }
1229
1230 /* We always need to send a data to make the SPI run */
1231 /* To prevent rx overflow, calculate the difference between rxRemainingBytes
1232 and txRemainingBytes and make sure the difference is smaller than watermark.
1233 The watermark is set according to FIFO size, for instance that does not have
1234 FIFO, the watermark is 1. */
1235 if (((handle->txRemainingBytes) != 0U) &&
1236 ((handle->rxRemainingBytes - handle->txRemainingBytes) < handle->watermark))
1237 {
1238 SPI_SendTransfer(base, handle);
1239 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
1240 if (handle->txRemainingBytes == 0U)
1241 {
1242 SPI_DisableInterrupts(base, (uint32_t)kSPI_TxFifoNearEmptyInterruptEnable);
1243 SPI_EnableInterrupts(base, (uint32_t)kSPI_TxEmptyInterruptEnable);
1244 }
1245 #endif
1246 }
1247
1248 /* All the transfer finished */
1249 if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
1250 {
1251 if ((SPI_GetStatusFlags(base) & (uint32_t)kSPI_TxBufferEmptyFlag) != 0U)
1252 {
1253 /* Complete the transfer */
1254 SPI_MasterTransferAbort(base, handle);
1255
1256 if (handle->callback != NULL)
1257 {
1258 (handle->callback)(base, handle, kStatus_SPI_Idle, handle->userData);
1259 }
1260 }
1261 }
1262 }
1263 /*!
1264 * brief Initializes the SPI slave handle.
1265 *
1266 * This function initializes the SPI slave handle which can be used for other SPI slave transactional APIs. Usually,
1267 * for a specified SPI instance, call this API once to get the initialized handle.
1268 *
1269 * param base SPI peripheral base address.
1270 * param handle SPI handle pointer.
1271 * param callback Callback function.
1272 * param userData User data.
1273 */
SPI_SlaveTransferCreateHandle(SPI_Type * base,spi_slave_handle_t * handle,spi_slave_callback_t callback,void * userData)1274 void SPI_SlaveTransferCreateHandle(SPI_Type *base,
1275 spi_slave_handle_t *handle,
1276 spi_slave_callback_t callback,
1277 void *userData)
1278 {
1279 assert(handle != NULL);
1280
1281 /* Slave create handle share same logic with master create handle, the only difference
1282 is the Isr pointer. */
1283 SPI_MasterTransferCreateHandle(base, handle, callback, userData);
1284 s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
1285 }
1286
1287 /*!
1288 * brief Performs a non-blocking SPI slave interrupt transfer.
1289 *
1290 * note The API returns immediately after the transfer initialization is finished.
1291 * Call SPI_GetStatusIRQ() to get the transfer status.
1292 * note If SPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
1293 *
1294 * param base SPI peripheral base address.
1295 * param handle pointer to spi_slave_handle_t structure which stores the transfer state
1296 * param xfer pointer to spi_xfer_config_t structure
1297 * retval kStatus_Success Successfully start a transfer.
1298 * retval kStatus_InvalidArgument Input argument is invalid.
1299 * retval kStatus_SPI_Busy SPI is not idle, is running another transfer.
1300 */
SPI_SlaveTransferNonBlocking(SPI_Type * base,spi_slave_handle_t * handle,spi_transfer_t * xfer)1301 status_t SPI_SlaveTransferNonBlocking(SPI_Type *base, spi_slave_handle_t *handle, spi_transfer_t *xfer)
1302 {
1303 assert((handle != NULL) && (xfer != NULL));
1304 uint32_t mask = 0U;
1305
1306 /* Check if SPI is busy */
1307 if (handle->state == (uint32_t)kSPI_Busy)
1308 {
1309 return (status_t)kStatus_SPI_Busy;
1310 }
1311
1312 /* Check if the input arguments valid */
1313 if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
1314 {
1315 return (status_t)kStatus_InvalidArgument;
1316 }
1317
1318 /* Read out any possible data */
1319 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
1320 /* If instance has FIFO and FIFO is enabled. */
1321 if ((FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0) && ((base->C3 & SPI_C3_FIFOMODE_MASK) != 0U))
1322 {
1323 while ((SPI_GetStatusFlags(base) & (uint32_t)kSPI_RxFifoEmptyFlag) == 0U)
1324 {
1325 (void)SPI_ReadData(base);
1326 }
1327 }
1328 else
1329 {
1330 if ((SPI_GetStatusFlags(base) & (uint32_t)kSPI_RxBufferFullFlag) != 0U)
1331 {
1332 (void)SPI_ReadData(base);
1333 }
1334 }
1335 #else
1336 if ((SPI_GetStatusFlags(base) & (uint32_t)kSPI_RxBufferFullFlag) != 0U)
1337 {
1338 (void)SPI_ReadData(base);
1339 }
1340 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
1341
1342 /* Set the handle information */
1343 handle->txData = xfer->txData;
1344 handle->rxData = xfer->rxData;
1345 handle->transferSize = xfer->dataSize;
1346 handle->txRemainingBytes = (xfer->txData == NULL) ? 0U : xfer->dataSize;
1347 handle->rxRemainingBytes = (xfer->rxData == NULL) ? 0U : xfer->dataSize;
1348
1349 /* Set the SPI state to busy */
1350 handle->state = (uint32_t)kSPI_Busy;
1351
1352 /* Enable Interrupt */
1353 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
1354
1355 handle->watermark = SPI_GetWatermark(base);
1356
1357 /* If the size of the transfer size less than watermark, set watermark to 1 */
1358 if (xfer->dataSize < (uint32_t)handle->watermark * 2U)
1359 {
1360 handle->watermark = 1U;
1361 }
1362
1363 /* According to watermark size, enable interrupts */
1364 if (handle->watermark > 1U)
1365 {
1366 /* Enable Rx near full interrupt */
1367
1368 if (handle->rxData != NULL)
1369 {
1370 mask |= (uint32_t)kSPI_RxFifoNearFullInterruptEnable;
1371 }
1372 /* Enable Tx near full interrupt only if there are data to send */
1373 if (handle->txData != NULL)
1374 {
1375 mask |= (uint32_t)kSPI_TxFifoNearEmptyInterruptEnable;
1376 }
1377
1378 SPI_EnableFIFO(base, true);
1379 }
1380 else
1381 {
1382 /* Enable Rx full interrupt */
1383 if (handle->rxData != NULL)
1384 {
1385 mask |= (uint32_t)kSPI_RxFullAndModfInterruptEnable;
1386 }
1387 /* Enable Tx full interrupt only if there are data to send */
1388 if (handle->txData != NULL)
1389 {
1390 mask |= (uint32_t)kSPI_TxEmptyInterruptEnable;
1391 }
1392
1393 SPI_EnableFIFO(base, false);
1394 }
1395 #else
1396 /* Enable Rx full interrupt */
1397 if (handle->rxData != NULL)
1398 {
1399 mask |= (uint32_t)kSPI_RxFullAndModfInterruptEnable;
1400 }
1401 /* Enable Tx full interrupt only if there are data to send */
1402 if (handle->txData != NULL)
1403 {
1404 mask |= (uint32_t)kSPI_TxEmptyInterruptEnable;
1405 }
1406 #endif
1407
1408 SPI_EnableInterrupts(base, mask);
1409 return kStatus_Success;
1410 }
1411
1412 /*!
1413 * brief Interrupts a handler for the SPI slave.
1414 *
1415 * param base SPI peripheral base address.
1416 * param handle pointer to spi_slave_handle_t structure which stores the transfer state
1417 */
SPI_SlaveTransferHandleIRQ(SPI_Type * base,spi_slave_handle_t * handle)1418 void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
1419 {
1420 assert(handle != NULL);
1421
1422 /* If needs to receive data, do a receive */
1423 if ((handle->rxRemainingBytes) != 0U)
1424 {
1425 SPI_ReceiveTransfer(base, handle);
1426 }
1427
1428 if ((handle->txRemainingBytes) != 0U)
1429 {
1430 SPI_SendTransfer(base, handle);
1431 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
1432 if (handle->txRemainingBytes == 0U)
1433 {
1434 SPI_DisableInterrupts(base, (uint32_t)kSPI_TxFifoNearEmptyInterruptEnable);
1435 SPI_EnableInterrupts(base, (uint32_t)kSPI_TxEmptyInterruptEnable);
1436 }
1437 #endif
1438 }
1439
1440 /* All the transfer finished */
1441 if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
1442 {
1443 if ((SPI_GetStatusFlags(base) & (uint32_t)kSPI_TxBufferEmptyFlag) != 0U)
1444 {
1445 /* Complete the transfer */
1446 SPI_SlaveTransferAbort(base, handle);
1447
1448 if (handle->callback != NULL)
1449 {
1450 handle->callback(base, handle, kStatus_SPI_Idle, handle->userData);
1451 }
1452 }
1453 }
1454 }
1455
SPI_CommonIRQHandler(SPI_Type * base,uint32_t instance)1456 static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance)
1457 {
1458 if ((base->C1 & SPI_C1_MSTR_MASK) != 0U)
1459 {
1460 s_spiMasterIsr(base, s_spiHandle[instance]);
1461 }
1462 else
1463 {
1464 s_spiSlaveIsr(base, s_spiHandle[instance]);
1465 }
1466 SDK_ISR_EXIT_BARRIER;
1467 }
1468
1469 #if defined(FSL_FEATURE_SPI_HAS_SHARED_IRQ0_IRQ1_IRQ2) && FSL_FEATURE_SPI_HAS_SHARED_IRQ0_IRQ1_IRQ2
1470 void SPI0_SPI1_SPI2_DriverIRQHandler(void);
SPI0_SPI1_SPI2_DriverIRQHandler(void)1471 void SPI0_SPI1_SPI2_DriverIRQHandler(void)
1472 {
1473 for (uint32_t instance = 0U; instance < 3U; instance++)
1474 {
1475 if (s_spiHandle[instance] != NULL)
1476 {
1477 SPI_CommonIRQHandler(s_spiBases[instance], instance);
1478 }
1479 }
1480 }
1481 #elif defined(FSL_FEATURE_SPI_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_SPI_HAS_SHARED_IRQ0_IRQ1
1482 void SPI0_SPI1_DriverIRQHandler(void);
SPI0_SPI1_DriverIRQHandler(void)1483 void SPI0_SPI1_DriverIRQHandler(void)
1484 {
1485 for (uint32_t instance = 0U; instance < 2U; instance++)
1486 {
1487 if (s_spiHandle[instance] != NULL)
1488 {
1489 SPI_CommonIRQHandler(s_spiBases[instance], instance);
1490 }
1491 }
1492 }
1493 #else
1494 #if defined(SPI0)
1495 void SPI0_DriverIRQHandler(void);
SPI0_DriverIRQHandler(void)1496 void SPI0_DriverIRQHandler(void)
1497 {
1498 assert(s_spiHandle[0] != NULL);
1499 SPI_CommonIRQHandler(SPI0, 0);
1500 }
1501 #endif
1502
1503 #if defined(SPI1)
1504 void SPI1_DriverIRQHandler(void);
SPI1_DriverIRQHandler(void)1505 void SPI1_DriverIRQHandler(void)
1506 {
1507 assert(s_spiHandle[1] != NULL);
1508 SPI_CommonIRQHandler(SPI1, 1);
1509 }
1510 #endif
1511
1512 #if defined(SPI2)
1513 void SPI2_DriverIRQHandler(void);
SPI2_DriverIRQHandler(void)1514 void SPI2_DriverIRQHandler(void)
1515 {
1516 assert(s_spiHandle[2] != NULL);
1517 SPI_CommonIRQHandler(SPI2, 2);
1518 }
1519 #endif
1520 #endif
1521