1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of the copyright holder nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "fsl_spi.h"
32 
33 /*******************************************************************************
34  * Definitons
35  ******************************************************************************/
36 /*! @brief SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
37 enum _spi_transfer_states_t
38 {
39     kSPI_Idle = 0x0, /*!< SPI is idle state */
40     kSPI_Busy        /*!< SPI is busy tranferring data. */
41 };
42 
43 /*! @brief Typedef for spi master interrupt handler. spi master and slave handle is the same. */
44 typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle);
45 
46 /*******************************************************************************
47  * Prototypes
48  ******************************************************************************/
49 /*!
50  * @brief Get the instance for SPI module.
51  *
52  * @param base SPI base address
53  */
54 uint32_t SPI_GetInstance(SPI_Type *base);
55 
56 /*!
57  * @brief Sends a buffer of data bytes in non-blocking way.
58  *
59  * @param base SPI base pointer
60  * @param buffer The data bytes to send
61  * @param size The number of data bytes to send
62  */
63 static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
64 
65 /*!
66  * @brief Receive a buffer of data bytes in non-blocking way.
67  *
68  * @param base SPI base pointer
69  * @param buffer The data bytes to send
70  * @param size The number of data bytes to send
71  */
72 static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size);
73 
74 /*!
75  * @brief Get the waterrmark value for this SPI instance.
76  *
77  * @param base SPI base pointer
78  * @return Watermark value for the SPI instance.
79  */
80 static uint8_t SPI_GetWatermark(SPI_Type *base);
81 
82 /*!
83  * @brief Send a piece of data for SPI.
84  *
85  * This function computes the number of data to be written into D register or Tx FIFO,
86  * and write the data into it. At the same time, this function updates the values in
87  * master handle structure.
88  *
89  * @param base SPI base pointer
90  * @param handle Pointer to SPI master handle structure.
91  */
92 static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle);
93 
94 /*!
95  * @brief Receive a piece of data for SPI master.
96  *
97  * This function computes the number of data to receive from D register or Rx FIFO,
98  * and write the data to destination address. At the same time, this function updates
99  * the values in master handle structure.
100  *
101  * @param base SPI base pointer
102  * @param handle Pointer to SPI master handle structure.
103  */
104 static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle);
105 
106 /*!
107  * @brief Common IRQ handler for SPI.
108  *
109  * @param base SPI base pointer.
110  * @param instance SPI instance number.
111  */
112 static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance);
113 /*******************************************************************************
114  * Variables
115  ******************************************************************************/
116 /*! @brief SPI internal handle pointer array */
117 static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT];
118 /*! @brief Base pointer array */
119 static SPI_Type *const s_spiBases[] = SPI_BASE_PTRS;
120 /*! @brief IRQ name array */
121 static const IRQn_Type s_spiIRQ[] = SPI_IRQS;
122 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
123 /*! @brief Clock array name */
124 static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS;
125 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
126 
127 /*! @brief Pointer to master IRQ handler for each instance. */
128 static spi_isr_t s_spiMasterIsr;
129 static spi_isr_t s_spiSlaveIsr;
130 
131 /*******************************************************************************
132  * Code
133  ******************************************************************************/
SPI_GetInstance(SPI_Type * base)134 uint32_t SPI_GetInstance(SPI_Type *base)
135 {
136     uint32_t instance;
137 
138     /* Find the instance index from base address mappings. */
139     for (instance = 0; instance < ARRAY_SIZE(s_spiBases); instance++)
140     {
141         if (s_spiBases[instance] == base)
142         {
143             break;
144         }
145     }
146 
147     assert(instance < ARRAY_SIZE(s_spiBases));
148 
149     return instance;
150 }
151 
SPI_WriteNonBlocking(SPI_Type * base,uint8_t * buffer,size_t size)152 static void SPI_WriteNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
153 {
154     uint32_t i = 0;
155     uint8_t bytesPerFrame = 1U;
156 
157 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
158     /* Check if 16 bits or 8 bits */
159     bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
160 #endif
161 
162     while (i < size)
163     {
164         if (buffer != NULL)
165         {
166 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
167             /*16 bit mode*/
168             if (base->C2 & SPI_C2_SPIMODE_MASK)
169             {
170                 base->DL = *buffer++;
171                 base->DH = *buffer++;
172             }
173             /* 8 bit mode */
174             else
175             {
176                 base->DL = *buffer++;
177             }
178 #else
179             base->D = *buffer++;
180 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
181         }
182         /* Send dummy data */
183         else
184         {
185             SPI_WriteData(base, SPI_DUMMYDATA);
186         }
187         i += bytesPerFrame;
188     }
189 }
190 
SPI_ReadNonBlocking(SPI_Type * base,uint8_t * buffer,size_t size)191 static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
192 {
193     uint32_t i = 0;
194     uint8_t bytesPerFrame = 1U;
195 
196 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
197     /* Check if 16 bits or 8 bits */
198     bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
199 #endif
200 
201     while (i < size)
202     {
203         if (buffer != NULL)
204         {
205 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
206             /*16 bit mode*/
207             if (base->C2 & SPI_C2_SPIMODE_MASK)
208             {
209                 *buffer++ = base->DL;
210                 *buffer++ = base->DH;
211             }
212             /* 8 bit mode */
213             else
214             {
215                 *buffer++ = base->DL;
216             }
217 #else
218             *buffer++ = base->D;
219 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
220         }
221         else
222         {
223             SPI_ReadData(base);
224         }
225         i += bytesPerFrame;
226     }
227 }
228 
SPI_GetWatermark(SPI_Type * base)229 static uint8_t SPI_GetWatermark(SPI_Type *base)
230 {
231     uint8_t ret = 0;
232 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
233     uint8_t rxSize = 0U;
234     /* Get the number to be sent if there is FIFO */
235     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
236     {
237         rxSize = (base->C3 & SPI_C3_RNFULLF_MARK_MASK) >> SPI_C3_RNFULLF_MARK_SHIFT;
238         if (rxSize == 0U)
239         {
240             ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) * 3U / 4U;
241         }
242         else
243         {
244             ret = FSL_FEATURE_SPI_FIFO_SIZEn(base) / 2U;
245         }
246     }
247     /* If no FIFO, just set the watermark to 1 */
248     else
249     {
250         ret = 1U;
251     }
252 #else
253     ret = 1U;
254 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
255     return ret;
256 }
257 
SPI_SendInitialTransfer(SPI_Type * base,spi_master_handle_t * handle)258 static void SPI_SendInitialTransfer(SPI_Type *base, spi_master_handle_t *handle)
259 {
260     uint8_t bytestoTransfer = handle->bytePerFrame;
261 
262 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
263     if (handle->watermark > 1)
264     {
265         bytestoTransfer = 2 * handle->watermark;
266     }
267 #endif
268 
269     SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
270 
271     /* Update handle information */
272     if (handle->txData)
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)
288         {
289             /* As a master, only write once */
290             if (base->S & SPI_S_SPTEF_MASK)
291             {
292                 SPI_WriteNonBlocking(base, handle->txData, bytes);
293                 /* Update handle information */
294                 if (handle->txData)
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) && (handle->txRemainingBytes >= bytes))
305             {
306                 SPI_WriteNonBlocking(base, handle->txData, bytes);
307 
308                 /* Update handle information */
309                 if (handle->txData)
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         uint8_t bytestoTransfer = handle->watermark * 2;
323 
324         if (handle->txRemainingBytes < 8U)
325         {
326             bytestoTransfer = handle->txRemainingBytes;
327         }
328 
329         SPI_WriteNonBlocking(base, handle->txData, bytestoTransfer);
330 
331         /* Update handle information */
332         if (handle->txData)
333         {
334             handle->txData += bytestoTransfer;
335         }
336         handle->txRemainingBytes -= bytestoTransfer;
337     }
338 #endif
339 }
340 
SPI_ReceiveTransfer(SPI_Type * base,spi_master_handle_t * handle)341 static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle)
342 {
343     uint8_t bytes = handle->bytePerFrame;
344 
345     /* Read S register and ensure SPRF is 1, otherwise the write would be ignored. */
346     if (handle->watermark == 1U)
347     {
348         if (base->S & SPI_S_SPRF_MASK)
349         {
350             SPI_ReadNonBlocking(base, handle->rxData, bytes);
351 
352             /* Update information in handle */
353             if (handle->rxData)
354             {
355                 handle->rxData += bytes;
356             }
357             handle->rxRemainingBytes -= bytes;
358         }
359     }
360 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO)
361     /* If use FIFO */
362     else
363     {
364         /* While rx fifo not empty and remaining data can also trigger the last interrupt */
365         while ((base->S & SPI_S_RFIFOEF_MASK) == 0U)
366         {
367             SPI_ReadNonBlocking(base, handle->rxData, bytes);
368 
369             /* Update information in handle */
370             if (handle->rxData)
371             {
372                 handle->rxData += bytes;
373             }
374             handle->rxRemainingBytes -= bytes;
375 
376             /* If the reamining data equals to watermark, leave to last interrupt */
377             if (handle->rxRemainingBytes == (handle->watermark * 2U))
378             {
379                 break;
380             }
381         }
382     }
383 #endif
384 }
385 
SPI_MasterGetDefaultConfig(spi_master_config_t * config)386 void SPI_MasterGetDefaultConfig(spi_master_config_t *config)
387 {
388     config->enableMaster = true;
389     config->enableStopInWaitMode = false;
390     config->polarity = kSPI_ClockPolarityActiveHigh;
391     config->phase = kSPI_ClockPhaseFirstEdge;
392     config->direction = kSPI_MsbFirst;
393 
394 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
395     config->dataMode = kSPI_8BitMode;
396 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
397 
398 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
399     config->txWatermark = kSPI_TxFifoOneHalfEmpty;
400     config->rxWatermark = kSPI_RxFifoOneHalfFull;
401 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
402 
403     config->pinMode = kSPI_PinModeNormal;
404     config->outputMode = kSPI_SlaveSelectAutomaticOutput;
405     config->baudRate_Bps = 500000U;
406 }
407 
SPI_MasterInit(SPI_Type * base,const spi_master_config_t * config,uint32_t srcClock_Hz)408 void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz)
409 {
410     assert(config && srcClock_Hz);
411 
412 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
413     /* Open clock gate for SPI and open interrupt */
414     CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
415 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
416 
417     /* Disable SPI before configuration */
418     base->C1 &= ~SPI_C1_SPE_MASK;
419 
420     /* Configure clock polarity and phase, set SPI to master */
421     base->C1 = SPI_C1_MSTR(1U) | SPI_C1_CPOL(config->polarity) | SPI_C1_CPHA(config->phase) |
422                SPI_C1_SSOE(config->outputMode & 1U) | SPI_C1_LSBFE(config->direction);
423 
424 /* Set data mode, and also pin mode and mode fault settings */
425 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
426     base->C2 = SPI_C2_MODFEN(config->outputMode >> 1U) | SPI_C2_BIDIROE(config->pinMode >> 1U) |
427                SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_SPC0(config->pinMode & 1U) |
428                SPI_C2_SPIMODE(config->dataMode);
429 #else
430     base->C2 = SPI_C2_MODFEN(config->outputMode >> 1U) | SPI_C2_BIDIROE(config->pinMode >> 1U) |
431                SPI_C2_SPISWAI(config->enableStopInWaitMode) | SPI_C2_SPC0(config->pinMode & 1U);
432 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
433 
434 /* Set watermark, FIFO is enabled */
435 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
436     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
437     {
438         base->C3 = SPI_C3_TNEAREF_MARK(config->txWatermark) | SPI_C3_RNFULLF_MARK(config->rxWatermark) |
439                    SPI_C3_INTCLR(0U) | SPI_C3_FIFOMODE(1U);
440     }
441 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
442 
443     /* Set baud rate */
444     SPI_MasterSetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
445 
446     /* Enable SPI */
447     if (config->enableMaster)
448     {
449         base->C1 |= SPI_C1_SPE_MASK;
450     }
451 }
452 
SPI_SlaveGetDefaultConfig(spi_slave_config_t * config)453 void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config)
454 {
455     config->enableSlave = true;
456     config->polarity = kSPI_ClockPolarityActiveHigh;
457     config->phase = kSPI_ClockPhaseFirstEdge;
458     config->direction = kSPI_MsbFirst;
459     config->enableStopInWaitMode = false;
460 
461 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
462     config->dataMode = kSPI_8BitMode;
463 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
464 
465 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
466     config->txWatermark = kSPI_TxFifoOneHalfEmpty;
467     config->rxWatermark = kSPI_RxFifoOneHalfFull;
468 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
469 }
470 
SPI_SlaveInit(SPI_Type * base,const spi_slave_config_t * config)471 void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config)
472 {
473     assert(config);
474 
475 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
476     /* Open clock gate for SPI and open interrupt */
477     CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]);
478 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
479 
480     /* Disable SPI before configuration */
481     base->C1 &= ~SPI_C1_SPE_MASK;
482 
483     /* Configure master and clock polarity and phase */
484     base->C1 =
485         SPI_C1_MSTR(0U) | SPI_C1_CPOL(config->polarity) | SPI_C1_CPHA(config->phase) | SPI_C1_LSBFE(config->direction);
486 
487 /* Configure data mode if needed */
488 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
489     base->C2 = SPI_C2_SPIMODE(config->dataMode) | SPI_C2_SPISWAI(config->enableStopInWaitMode);
490 #else
491     base->C2 = SPI_C2_SPISWAI(config->enableStopInWaitMode);
492 #endif /* FSL_FEATURE_SPI_16BIT_TRANSFERS */
493 
494 /* Set watermark */
495 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
496     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0U)
497     {
498         base->C3 = SPI_C3_TNEAREF_MARK(config->txWatermark) | SPI_C3_RNFULLF_MARK(config->rxWatermark) |
499                    SPI_C3_INTCLR(0U) | SPI_C3_FIFOMODE(1U);
500     }
501 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
502 
503     /* Enable SPI */
504     if (config->enableSlave)
505     {
506         base->C1 |= SPI_C1_SPE_MASK;
507     }
508 }
509 
SPI_Deinit(SPI_Type * base)510 void SPI_Deinit(SPI_Type *base)
511 {
512     /* Disable SPI module before shutting down */
513     base->C1 &= ~SPI_C1_SPE_MASK;
514 
515 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
516     /* Gate the clock */
517     CLOCK_DisableClock(s_spiClock[SPI_GetInstance(base)]);
518 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
519 }
520 
SPI_GetStatusFlags(SPI_Type * base)521 uint32_t SPI_GetStatusFlags(SPI_Type *base)
522 {
523 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
524     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
525     {
526         return ((base->S) | (((uint32_t)base->CI) << 8U));
527     }
528     else
529     {
530         return (base->S);
531     }
532 #else
533     return (base->S);
534 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
535 }
536 
SPI_EnableInterrupts(SPI_Type * base,uint32_t mask)537 void SPI_EnableInterrupts(SPI_Type *base, uint32_t mask)
538 {
539     /* Rx full interrupt */
540     if (mask & kSPI_RxFullAndModfInterruptEnable)
541     {
542         base->C1 |= SPI_C1_SPIE_MASK;
543     }
544 
545     /* Tx empty interrupt */
546     if (mask & kSPI_TxEmptyInterruptEnable)
547     {
548         base->C1 |= SPI_C1_SPTIE_MASK;
549     }
550 
551     /* Data match interrupt */
552     if (mask & kSPI_MatchInterruptEnable)
553     {
554         base->C2 |= SPI_C2_SPMIE_MASK;
555     }
556 
557 /* FIFO related interrupts */
558 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
559     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
560     {
561         /* Rx FIFO near full interrupt */
562         if (mask & kSPI_RxFifoNearFullInterruptEnable)
563         {
564             base->C3 |= SPI_C3_RNFULLIEN_MASK;
565         }
566 
567         /* Tx FIFO near empty interrupt */
568         if (mask & kSPI_TxFifoNearEmptyInterruptEnable)
569         {
570             base->C3 |= SPI_C3_TNEARIEN_MASK;
571         }
572     }
573 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
574 }
575 
SPI_DisableInterrupts(SPI_Type * base,uint32_t mask)576 void SPI_DisableInterrupts(SPI_Type *base, uint32_t mask)
577 {
578     /* Rx full interrupt */
579     if (mask & kSPI_RxFullAndModfInterruptEnable)
580     {
581         base->C1 &= (~SPI_C1_SPIE_MASK);
582     }
583 
584     /* Tx empty interrupt */
585     if (mask & kSPI_TxEmptyInterruptEnable)
586     {
587         base->C1 &= (~SPI_C1_SPTIE_MASK);
588     }
589 
590     /* Data match interrupt */
591     if (mask & kSPI_MatchInterruptEnable)
592     {
593         base->C2 &= (~SPI_C2_SPMIE_MASK);
594     }
595 
596 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
597     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
598     {
599         /* Rx FIFO near full interrupt */
600         if (mask & kSPI_RxFifoNearFullInterruptEnable)
601         {
602             base->C3 &= ~SPI_C3_RNFULLIEN_MASK;
603         }
604 
605         /* Tx FIFO near empty interrupt */
606         if (mask & kSPI_TxFifoNearEmptyInterruptEnable)
607         {
608             base->C3 &= ~SPI_C3_TNEARIEN_MASK;
609         }
610     }
611 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
612 }
613 
SPI_MasterSetBaudRate(SPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)614 void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
615 {
616     uint32_t prescaler;
617     uint32_t bestPrescaler;
618     uint32_t rateDivisor;
619     uint32_t bestDivisor;
620     uint32_t rateDivisorValue;
621     uint32_t realBaudrate;
622     uint32_t diff;
623     uint32_t min_diff;
624     uint32_t freq = baudRate_Bps;
625 
626     /* Find combination of prescaler and scaler resulting in baudrate closest to the requested value */
627     min_diff = 0xFFFFFFFFU;
628 
629     /* Set the maximum divisor bit settings for each of the following divisors */
630     bestPrescaler = 7U;
631     bestDivisor = 8U;
632 
633     /* In all for loops, if min_diff = 0, the exit for loop*/
634     for (prescaler = 0; (prescaler <= 7) && min_diff; prescaler++)
635     {
636         /* Initialize to div-by-2 */
637         rateDivisorValue = 2U;
638 
639         for (rateDivisor = 0; (rateDivisor <= 8U) && min_diff; rateDivisor++)
640         {
641             /* Calculate actual baud rate, note need to add 1 to prescaler */
642             realBaudrate = ((srcClock_Hz) / ((prescaler + 1) * rateDivisorValue));
643 
644             /* Calculate the baud rate difference based on the conditional statement ,that states that the
645             calculated baud rate must not exceed the desired baud rate */
646             if (freq >= realBaudrate)
647             {
648                 diff = freq - realBaudrate;
649                 if (min_diff > diff)
650                 {
651                     /* A better match found */
652                     min_diff = diff;
653                     bestPrescaler = prescaler;
654                     bestDivisor = rateDivisor;
655                 }
656             }
657 
658             /* Multiply by 2 for each iteration, possible divisor values: 2, 4, 8, 16, ... 512 */
659             rateDivisorValue *= 2U;
660         }
661     }
662 
663     /* Write the best prescalar and baud rate scalar */
664     base->BR = SPI_BR_SPR(bestDivisor) | SPI_BR_SPPR(bestPrescaler);
665 }
666 
SPI_WriteBlocking(SPI_Type * base,uint8_t * buffer,size_t size)667 void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size)
668 {
669     uint32_t i = 0;
670     uint8_t bytesPerFrame = 1U;
671 
672 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
673     /* Check if 16 bits or 8 bits */
674     bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
675 #endif
676 
677     while (i < size)
678     {
679         while ((base->S & SPI_S_SPTEF_MASK) == 0)
680         {
681         }
682 
683         /* Send a frame of data */
684         SPI_WriteNonBlocking(base, buffer, bytesPerFrame);
685 
686         i += bytesPerFrame;
687         buffer += bytesPerFrame;
688     }
689 }
690 
691 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
SPI_EnableFIFO(SPI_Type * base,bool enable)692 void SPI_EnableFIFO(SPI_Type *base, bool enable)
693 {
694     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0U)
695     {
696         if (enable)
697         {
698             base->C3 |= SPI_C3_FIFOMODE_MASK;
699         }
700         else
701         {
702             base->C3 &= ~SPI_C3_FIFOMODE_MASK;
703         }
704     }
705 }
706 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
707 
SPI_WriteData(SPI_Type * base,uint16_t data)708 void SPI_WriteData(SPI_Type *base, uint16_t data)
709 {
710 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
711     base->DL = data & 0xFFU;
712     base->DH = (data >> 8U) & 0xFFU;
713 #else
714     base->D = data & 0xFFU;
715 #endif
716 }
717 
SPI_ReadData(SPI_Type * base)718 uint16_t SPI_ReadData(SPI_Type *base)
719 {
720     uint16_t val = 0;
721 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
722     val = base->DL;
723     val |= (uint16_t)((uint16_t)(base->DH) << 8U);
724 #else
725     val = base->D;
726 #endif
727     return val;
728 }
729 
SPI_MasterTransferBlocking(SPI_Type * base,spi_transfer_t * xfer)730 status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer)
731 {
732     assert(xfer);
733 
734     uint8_t bytesPerFrame = 1U;
735 
736     /* Check if the argument is legal */
737     if ((xfer->txData == NULL) && (xfer->rxData == NULL))
738     {
739         return kStatus_InvalidArgument;
740     }
741 
742 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS
743     /* Check if 16 bits or 8 bits */
744     bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
745 #endif
746 
747     /* Disable SPI and then enable it, this is used to clear S register */
748     base->C1 &= ~SPI_C1_SPE_MASK;
749     base->C1 |= SPI_C1_SPE_MASK;
750 
751 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
752 
753     /* Disable FIFO, as the FIFO may cause data loss if the data size is not integer
754        times of 2bytes. As SPI cannot set watermark to 0, only can set to 1/2 FIFO size or 3/4 FIFO
755        size. */
756     if (FSL_FEATURE_SPI_FIFO_SIZEn(base) != 0)
757     {
758         base->C3 &= ~SPI_C3_FIFOMODE_MASK;
759     }
760 
761 #endif /* FSL_FEATURE_SPI_HAS_FIFO */
762 
763     /* Begin the polling transfer until all data sent */
764     while (xfer->dataSize > 0)
765     {
766         /* Data send */
767         while ((base->S & SPI_S_SPTEF_MASK) == 0U)
768         {
769         }
770         SPI_WriteNonBlocking(base, xfer->txData, bytesPerFrame);
771         if (xfer->txData)
772         {
773             xfer->txData += bytesPerFrame;
774         }
775 
776         while ((base->S & SPI_S_SPRF_MASK) == 0U)
777         {
778         }
779         SPI_ReadNonBlocking(base, xfer->rxData, bytesPerFrame);
780         if (xfer->rxData)
781         {
782             xfer->rxData += bytesPerFrame;
783         }
784 
785         /* Decrease the number */
786         xfer->dataSize -= bytesPerFrame;
787     }
788 
789     return kStatus_Success;
790 }
791 
SPI_MasterTransferCreateHandle(SPI_Type * base,spi_master_handle_t * handle,spi_master_callback_t callback,void * userData)792 void SPI_MasterTransferCreateHandle(SPI_Type *base,
793                                     spi_master_handle_t *handle,
794                                     spi_master_callback_t callback,
795                                     void *userData)
796 {
797     assert(handle);
798 
799     uint8_t instance = SPI_GetInstance(base);
800 
801     /* Zero the handle */
802     memset(handle, 0, sizeof(*handle));
803 
804     /* Initialize the handle */
805     s_spiHandle[instance] = handle;
806     handle->callback = callback;
807     handle->userData = userData;
808     s_spiMasterIsr = SPI_MasterTransferHandleIRQ;
809     handle->watermark = SPI_GetWatermark(base);
810 
811 /* Get the bytes per frame */
812 #if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && (FSL_FEATURE_SPI_16BIT_TRANSFERS)
813     handle->bytePerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U;
814 #else
815     handle->bytePerFrame = 1U;
816 #endif
817 
818     /* Enable SPI NVIC */
819     EnableIRQ(s_spiIRQ[instance]);
820 }
821 
SPI_MasterTransferNonBlocking(SPI_Type * base,spi_master_handle_t * handle,spi_transfer_t * xfer)822 status_t SPI_MasterTransferNonBlocking(SPI_Type *base, spi_master_handle_t *handle, spi_transfer_t *xfer)
823 {
824     assert(handle && xfer);
825 
826     /* Check if SPI is busy */
827     if (handle->state == kSPI_Busy)
828     {
829         return kStatus_SPI_Busy;
830     }
831 
832     /* Check if the input arguments valid */
833     if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
834     {
835         return kStatus_InvalidArgument;
836     }
837 
838     /* Set the handle information */
839     handle->txData = xfer->txData;
840     handle->rxData = xfer->rxData;
841     handle->transferSize = xfer->dataSize;
842     handle->txRemainingBytes = xfer->dataSize;
843     handle->rxRemainingBytes = xfer->dataSize;
844 
845     /* Set the SPI state to busy */
846     handle->state = kSPI_Busy;
847 
848     /* Disable SPI and then enable it, this is used to clear S register*/
849     base->C1 &= ~SPI_C1_SPE_MASK;
850     base->C1 |= SPI_C1_SPE_MASK;
851 
852 /* Enable Interrupt, only enable Rx interrupt, use rx interrupt to driver SPI transfer */
853 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
854 
855     handle->watermark = SPI_GetWatermark(base);
856 
857     /* If the size of the transfer size less than watermark, set watermark to 1 */
858     if (xfer->dataSize < handle->watermark * 2U)
859     {
860         handle->watermark = 1U;
861     }
862 
863     /* According to watermark size, enable interrupts */
864     if (handle->watermark > 1U)
865     {
866         SPI_EnableFIFO(base, true);
867         /* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
868         while ((base->S & SPI_S_TNEAREF_MASK) != SPI_S_TNEAREF_MASK)
869             ;
870         SPI_SendInitialTransfer(base, handle);
871         /* Enable Rx near full interrupt */
872         SPI_EnableInterrupts(base, kSPI_RxFifoNearFullInterruptEnable);
873     }
874     else
875     {
876         SPI_EnableFIFO(base, false);
877         while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
878             ;
879         /* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
880         SPI_SendInitialTransfer(base, handle);
881         SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
882     }
883 #else
884     while ((base->S & SPI_S_SPTEF_MASK) != SPI_S_SPTEF_MASK)
885         ;
886     /* First send a piece of data to Tx Data or FIFO to start a SPI transfer */
887     SPI_SendInitialTransfer(base, handle);
888     SPI_EnableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
889 #endif
890 
891     return kStatus_Success;
892 }
893 
SPI_MasterTransferGetCount(SPI_Type * base,spi_master_handle_t * handle,size_t * count)894 status_t SPI_MasterTransferGetCount(SPI_Type *base, spi_master_handle_t *handle, size_t *count)
895 {
896     assert(handle);
897 
898     status_t status = kStatus_Success;
899 
900     if (handle->state != kStatus_SPI_Busy)
901     {
902         status = kStatus_NoTransferInProgress;
903     }
904     else
905     {
906         /* Return remaing bytes in different cases */
907         if (handle->rxData)
908         {
909             *count = handle->transferSize - handle->rxRemainingBytes;
910         }
911         else
912         {
913             *count = handle->transferSize - handle->txRemainingBytes;
914         }
915     }
916 
917     return status;
918 }
919 
SPI_MasterTransferAbort(SPI_Type * base,spi_master_handle_t * handle)920 void SPI_MasterTransferAbort(SPI_Type *base, spi_master_handle_t *handle)
921 {
922     assert(handle);
923 
924 /* Stop interrupts */
925 #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO
926     if (handle->watermark > 1U)
927     {
928         SPI_DisableInterrupts(base, kSPI_RxFifoNearFullInterruptEnable | kSPI_RxFullAndModfInterruptEnable);
929     }
930     else
931     {
932         SPI_DisableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
933     }
934 #else
935     SPI_DisableInterrupts(base, kSPI_RxFullAndModfInterruptEnable);
936 #endif
937 
938     /* Transfer finished, set the state to Done*/
939     handle->state = kSPI_Idle;
940 
941     /* Clear the internal state */
942     handle->rxRemainingBytes = 0;
943     handle->txRemainingBytes = 0;
944 }
945 
SPI_MasterTransferHandleIRQ(SPI_Type * base,spi_master_handle_t * handle)946 void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle)
947 {
948     assert(handle);
949 
950     /* If needs to receive data, do a receive */
951     if (handle->rxRemainingBytes)
952     {
953         SPI_ReceiveTransfer(base, handle);
954     }
955 
956     /* We always need to send a data to make the SPI run */
957     if (handle->txRemainingBytes)
958     {
959         SPI_SendTransfer(base, handle);
960     }
961 
962     /* All the transfer finished */
963     if ((handle->txRemainingBytes == 0) && (handle->rxRemainingBytes == 0))
964     {
965         /* Complete the transfer */
966         SPI_MasterTransferAbort(base, handle);
967 
968         if (handle->callback)
969         {
970             (handle->callback)(base, handle, kStatus_SPI_Idle, handle->userData);
971         }
972     }
973 }
974 
SPI_SlaveTransferCreateHandle(SPI_Type * base,spi_slave_handle_t * handle,spi_slave_callback_t callback,void * userData)975 void SPI_SlaveTransferCreateHandle(SPI_Type *base,
976                                    spi_slave_handle_t *handle,
977                                    spi_slave_callback_t callback,
978                                    void *userData)
979 {
980     assert(handle);
981 
982     /* Slave create handle share same logic with master create handle, the only difference
983     is the Isr pointer. */
984     SPI_MasterTransferCreateHandle(base, handle, callback, userData);
985     s_spiSlaveIsr = SPI_SlaveTransferHandleIRQ;
986 }
987 
SPI_SlaveTransferHandleIRQ(SPI_Type * base,spi_slave_handle_t * handle)988 void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle)
989 {
990     assert(handle);
991 
992     /* Do data send first in case of data missing. */
993     if (handle->txRemainingBytes)
994     {
995         SPI_SendTransfer(base, handle);
996     }
997 
998     /* If needs to receive data, do a receive */
999     if (handle->rxRemainingBytes)
1000     {
1001         SPI_ReceiveTransfer(base, handle);
1002     }
1003 
1004     /* All the transfer finished */
1005     if ((handle->txRemainingBytes == 0) && (handle->rxRemainingBytes == 0))
1006     {
1007         /* Complete the transfer */
1008         SPI_SlaveTransferAbort(base, handle);
1009 
1010         if (handle->callback)
1011         {
1012             (handle->callback)(base, handle, kStatus_SPI_Idle, handle->userData);
1013         }
1014     }
1015 }
1016 
SPI_CommonIRQHandler(SPI_Type * base,uint32_t instance)1017 static void SPI_CommonIRQHandler(SPI_Type *base, uint32_t instance)
1018 {
1019     if (base->C1 & SPI_C1_MSTR_MASK)
1020     {
1021         s_spiMasterIsr(base, s_spiHandle[instance]);
1022     }
1023     else
1024     {
1025         s_spiSlaveIsr(base, s_spiHandle[instance]);
1026     }
1027 }
1028 
1029 #if defined(SPI0)
SPI0_DriverIRQHandler(void)1030 void SPI0_DriverIRQHandler(void)
1031 {
1032     assert(s_spiHandle[0]);
1033     SPI_CommonIRQHandler(SPI0, 0);
1034 }
1035 #endif
1036 
1037 #if defined(SPI1)
SPI1_DriverIRQHandler(void)1038 void SPI1_DriverIRQHandler(void)
1039 {
1040     assert(s_spiHandle[1]);
1041     SPI_CommonIRQHandler(SPI1, 1);
1042 }
1043 #endif
1044 
1045 #if defined(SPI2)
SPI2_DriverIRQHandler(void)1046 void SPI2_DriverIRQHandler(void)
1047 {
1048     assert(s_spiHandle[2]);
1049     SPI_CommonIRQHandler(SPI2, 2);
1050 }
1051 #endif
1052