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