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