1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_ecspi.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.ecspi"
18 #endif
19
20 /*! @brief ECSPI transfer state, which is used for ECSPI transactiaonl APIs' internal state. */
21 enum
22 {
23 kECSPI_Idle = 0x0, /*!< ECSPI is idle state */
24 kECSPI_Busy /*!< ECSPI is busy tranferring data. */
25 };
26
27 /*! @brief Typedef for ecspi master interrupt handler. ecspi master and slave handle is the same. */
28 typedef void (*ecspi_isr_t)(ECSPI_Type *base, ecspi_master_handle_t *ecspiHandle);
29
30 /*******************************************************************************
31 * Prototypes
32 ******************************************************************************/
33 /*!
34 * @brief Sends a buffer of data bytes in non-blocking way.
35 *
36 * @param base ECSPI base pointer
37 * @param buffer The data bytes to send
38 * @param size The number of data bytes to send
39 */
40 static void ECSPI_WriteNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size);
41
42 /*!
43 * @brief Receive a buffer of data bytes in non-blocking way.
44 *
45 * @param base ECSPI base pointer
46 * @param buffer The data bytes to send
47 * @param size The number of data bytes to send
48 */
49 static void ECSPI_ReadNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size);
50
51 /*!
52 * @brief Send a piece of data for ECSPI.
53 *
54 * This function computes the number of data to be written into D register or Tx FIFO,
55 * and write the data into it. At the same time, this function updates the values in
56 * master handle structure.
57 *
58 * @param base ECSPI base pointer
59 * @param handle Pointer to ECSPI master handle structure.
60 */
61 static void ECSPI_SendTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle);
62
63 /*!
64 * @brief Receive a piece of data for ECSPI master.
65 *
66 * This function computes the number of data to receive from D register or Rx FIFO,
67 * and write the data to destination address. At the same time, this function updates
68 * the values in master handle structure.
69 *
70 * @param base ECSPI base pointer
71 * @param handle Pointer to ECSPI master handle structure.
72 */
73 static void ECSPI_ReceiveTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle);
74
75 /*!
76 * @brief Sets the ECSPI channel configuration structure to default values.
77 *
78 * This function is to get the channel configuration structure initialized for use in ECSPI_SetChannelConfig().
79 * User may use the initialized structure unchanged in ECSPI_SetChannelConfig(), or modify
80 * some fields of the structure before calling ECSPI_SetChannelConfig().
81 *
82 * @param config pointer to config structure
83 */
84 static void ECSPI_GetDefaultChannelConfig(ecspi_channel_config_t *config);
85
86 /*!
87 * @brief Common IRQ handler for SPI.
88 *
89 * @param base SPI base pointer.
90 * @param instance SPI instance number.
91 */
92 static void ECSPI_CommonIRQHandler(ECSPI_Type *base, ecspi_master_handle_t *handle);
93
94 /*******************************************************************************
95 * Variables
96 ******************************************************************************/
97 /*! @brief Base pointer array */
98 static ECSPI_Type *const s_ecspiBases[] = ECSPI_BASE_PTRS;
99 /*! @brief ECSPI internal handle pointer array */
100 static ecspi_master_handle_t *s_ecspiHandle[ARRAY_SIZE(s_ecspiBases)];
101 /*! @brief IRQ name array */
102 static const IRQn_Type s_ecspiIRQ[] = ECSPI_IRQS;
103 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
104 /*! @brief Clock array name */
105 static const clock_ip_name_t s_ecspiClock[] = ECSPI_CLOCKS;
106 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
107
108 /*! @brief Pointer to master IRQ handler for each instance. */
109 static ecspi_isr_t s_ecspiMasterIsr;
110 /*! @brief Pointer to slave IRQ handler for each instance. */
111 static ecspi_isr_t s_ecspiSlaveIsr;
112
113 /*******************************************************************************
114 * Code
115 ******************************************************************************/
116 /*!
117 * brief Get the instance for ECSPI module.
118 *
119 * param base ECSPI base address
120 */
ECSPI_GetInstance(ECSPI_Type * base)121 uint32_t ECSPI_GetInstance(ECSPI_Type *base)
122 {
123 uint32_t instance;
124
125 /* Find the instance index from base address mappings. */
126 for (instance = 0; instance < ARRAY_SIZE(s_ecspiBases); instance++)
127 {
128 if (s_ecspiBases[instance] == base)
129 {
130 break;
131 }
132 }
133 assert(instance <= ARRAY_SIZE(s_ecspiBases));
134 return instance;
135 }
136
ECSPI_WriteNonBlocking(ECSPI_Type * base,uint32_t * buffer,size_t size)137 static void ECSPI_WriteNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
138 {
139 size_t i = 0U;
140
141 for (i = 0U; i < size; i++)
142 {
143 if (buffer != NULL)
144 {
145 base->TXDATA = *buffer++;
146 }
147 else
148 {
149 ECSPI_WriteData(base, ECSPI_DUMMYDATA);
150 }
151 }
152 }
153
ECSPI_ReadNonBlocking(ECSPI_Type * base,uint32_t * buffer,size_t size)154 static void ECSPI_ReadNonBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
155 {
156 if (NULL != buffer)
157 {
158 while ((size--) != 0UL)
159 {
160 *buffer++ = ECSPI_ReadData(base);
161 }
162 }
163 else
164 {
165 while ((size--) != 0UL)
166 {
167 (void)ECSPI_ReadData(base);
168 }
169 }
170 }
171
ECSPI_SendTransfer(ECSPI_Type * base,ecspi_master_handle_t * handle)172 static void ECSPI_SendTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle)
173 {
174 assert(base);
175 assert(handle);
176
177 uint32_t dataCounts = 0U;
178 uint32_t txRemainingBytes = (uint32_t)(handle->txRemainingBytes);
179 /* Caculate the data size to send */
180 dataCounts =
181 ((uint32_t)FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(base) - (uint32_t)ECSPI_GetTxFifoCount(base)) < txRemainingBytes ?
182 ((uint32_t)FSL_FEATURE_ECSPI_TX_FIFO_SIZEn(base) - (uint32_t)ECSPI_GetTxFifoCount(base)) :
183 txRemainingBytes;
184 while ((dataCounts--) != 0UL)
185 {
186 ECSPI_WriteNonBlocking(base, handle->txData, 1);
187 if (NULL != handle->txData)
188 {
189 handle->txData += 1U;
190 }
191 handle->txRemainingBytes -= 1U;
192 }
193 }
194
ECSPI_ReceiveTransfer(ECSPI_Type * base,ecspi_master_handle_t * handle)195 static void ECSPI_ReceiveTransfer(ECSPI_Type *base, ecspi_master_handle_t *handle)
196 {
197 assert(base);
198
199 uint32_t dataCounts = 0U;
200 /* Caculate the data size need to receive */
201 dataCounts =
202 (ECSPI_GetRxFifoCount(base) < handle->rxRemainingBytes) ? ECSPI_GetRxFifoCount(base) : handle->rxRemainingBytes;
203
204 ECSPI_ReadNonBlocking(base, handle->rxData, dataCounts);
205 if (NULL != handle->rxData)
206 {
207 handle->rxData += dataCounts;
208 }
209 handle->rxRemainingBytes -= dataCounts;
210 }
ECSPI_GetDefaultChannelConfig(ecspi_channel_config_t * config)211 static void ECSPI_GetDefaultChannelConfig(ecspi_channel_config_t *config)
212 {
213 /* Initializes the configure structure to zero. */
214 (void)memset(config, 0, sizeof(*config));
215
216 config->channelMode = kECSPI_Slave; /*!< ECSPI peripheral operates in slave mode.*/
217 config->clockInactiveState = kECSPI_ClockInactiveStateLow; /*!< Clock line (SCLK) inactive state */
218 config->dataLineInactiveState = kECSPI_DataLineInactiveStateLow; /*!< Data line (MOSI&MISO) inactive state */
219 config->chipSlectActiveState = kECSPI_ChipSelectActiveStateLow; /*!< Chip select(SS) line active state */
220 config->waveForm = kECSPI_WaveFormSingle; /*!< ECSPI SS wave form */
221 config->polarity = kECSPI_PolarityActiveHigh; /*!< Clock polarity */
222 config->phase = kECSPI_ClockPhaseFirstEdge; /*!< clock phase */
223 }
224
225 /*!
226 * brief Sets the ECSPI configuration structure to default values.
227 *
228 * The purpose of this API is to get the configuration structure initialized for use in ECSPI_MasterInit().
229 * User may use the initialized structure unchanged in ECSPI_MasterInit, or modify
230 * some fields of the structure before calling ECSPI_MasterInit. After calling this API,
231 * the master is ready to transfer.
232 * Example:
233 code
234 ecspi_master_config_t config;
235 ECSPI_MasterGetDefaultConfig(&config);
236 endcode
237 *
238 * param config pointer to config structure
239 */
ECSPI_MasterGetDefaultConfig(ecspi_master_config_t * config)240 void ECSPI_MasterGetDefaultConfig(ecspi_master_config_t *config)
241 {
242 /* Initializes the configure structure to zero. */
243 (void)memset(config, 0, sizeof(*config));
244
245 config->channel = kECSPI_Channel0;
246 config->burstLength = 8;
247 config->samplePeriodClock = kECSPI_spiClock;
248 config->baudRate_Bps = 500000;
249 config->chipSelectDelay = 0;
250 config->samplePeriod = 0;
251 config->txFifoThreshold = 1;
252 config->rxFifoThreshold = 0;
253 /* Default configuration of channel */
254 ECSPI_GetDefaultChannelConfig(&config->channelConfig);
255 /*!< ECSPI peripheral operates in slave mode.*/
256 config->channelConfig.channelMode = kECSPI_Master;
257 config->enableLoopback = false;
258 }
259
260 /*!
261 * brief Initializes the ECSPI with configuration.
262 *
263 * The configuration structure can be filled by user from scratch, or be set with default
264 * values by ECSPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
265 * Example
266 code
267 ecspi_master_config_t config = {
268 .baudRate_Bps = 400000,
269 ...
270 };
271 ECSPI_MasterInit(ECSPI0, &config);
272 endcode
273 *
274 * param base ECSPI base pointer
275 * param config pointer to master configuration structure
276 * param srcClock_Hz Source clock frequency.
277 */
ECSPI_MasterInit(ECSPI_Type * base,const ecspi_master_config_t * config,uint32_t srcClock_Hz)278 void ECSPI_MasterInit(ECSPI_Type *base, const ecspi_master_config_t *config, uint32_t srcClock_Hz)
279 {
280 assert(config && srcClock_Hz);
281 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
282 /* Open clock gate for SPI and open interrupt */
283 CLOCK_EnableClock(s_ecspiClock[ECSPI_GetInstance(base)]);
284 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
285 /* Reset control register to default value */
286 ECSPI_SoftwareReset(base);
287 /* Config CONREG register */
288 base->CONREG =
289 ECSPI_CONREG_BURST_LENGTH((uint32_t)config->burstLength - 1UL) | ECSPI_CONREG_SMC(1U) | ECSPI_CONREG_EN(1U);
290 /* Config CONFIGREG register */
291 ECSPI_SetChannelConfig(base, config->channel, &config->channelConfig);
292 /* Config DMAREG register */
293 base->DMAREG |=
294 ECSPI_DMAREG_TX_THRESHOLD(config->txFifoThreshold) | ECSPI_DMAREG_RX_THRESHOLD(config->rxFifoThreshold);
295 /* Config PERIODREG register */
296 base->PERIODREG |= ECSPI_PERIODREG_CSRC(config->samplePeriodClock) |
297 ECSPI_PERIODREG_SAMPLE_PERIOD(config->samplePeriod) |
298 ECSPI_PERIODREG_CSD_CTL(config->chipSelectDelay);
299 /* Config TESTING register if enable the loopback function. */
300 base->TESTREG |= ECSPI_TESTREG_LBC(config->enableLoopback);
301 /* Set baud rate */
302 ECSPI_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz);
303 }
304
305 /*!
306 * brief Sets the ECSPI configuration structure to default values.
307 *
308 * The purpose of this API is to get the configuration structure initialized for use in ECSPI_SlaveInit().
309 * User may use the initialized structure unchanged in ECSPI_SlaveInit(), or modify
310 * some fields of the structure before calling ECSPI_SlaveInit(). After calling this API,
311 * the master is ready to transfer.
312 * Example:
313 code
314 ecspi_Slaveconfig_t config;
315 ECSPI_SlaveGetDefaultConfig(&config);
316 endcode
317 *
318 * param config pointer to config structure
319 */
ECSPI_SlaveGetDefaultConfig(ecspi_slave_config_t * config)320 void ECSPI_SlaveGetDefaultConfig(ecspi_slave_config_t *config)
321 {
322 /* Default configuration of channel nember */
323
324 /* Initializes the configure structure to zero. */
325 (void)memset(config, 0, sizeof(*config));
326 config->channel = kECSPI_Channel0;
327
328 config->burstLength = 8;
329 config->txFifoThreshold = 1;
330 config->rxFifoThreshold = 0;
331 /* Set default channel configuration */
332 ECSPI_GetDefaultChannelConfig(&config->channelConfig);
333 /* ECSPI peripheral operates in slave mode.*/
334 config->channelConfig.channelMode = kECSPI_Slave;
335 }
336
337 /*!
338 * brief Initializes the ECSPI with configuration.
339 *
340 * The configuration structure can be filled by user from scratch, or be set with default
341 * values by ECSPI_SlaveGetDefaultConfig(). After calling this API, the slave is ready to transfer.
342 * Example
343 code
344 ecspi_Salveconfig_t config = {
345 .baudRate_Bps = 400000,
346 ...
347 };
348 ECSPI_SlaveInit(ECSPI1, &config);
349 endcode
350 *
351 * param base ECSPI base pointer
352 * param config pointer to master configuration structure
353 */
ECSPI_SlaveInit(ECSPI_Type * base,const ecspi_slave_config_t * config)354 void ECSPI_SlaveInit(ECSPI_Type *base, const ecspi_slave_config_t *config)
355 {
356 assert(base && config);
357
358 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
359 /* Open clock gate for SPI and open interrupt */
360 CLOCK_EnableClock(s_ecspiClock[ECSPI_GetInstance(base)]);
361 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
362
363 /* Reset control register to default value */
364 ECSPI_SoftwareReset(base);
365 /* Config CONREG register */
366 base->CONREG = ECSPI_CONREG_BURST_LENGTH(config->burstLength - 1UL) | ECSPI_CONREG_EN(1UL);
367 /* Config DMAREG register */
368 base->DMAREG |=
369 ECSPI_DMAREG_TX_THRESHOLD(config->txFifoThreshold) | ECSPI_DMAREG_RX_THRESHOLD(config->rxFifoThreshold);
370 /* Setup channel configuration */
371 ECSPI_SetChannelConfig(base, config->channel, &config->channelConfig);
372 }
373
374 /*!
375 * brief De-initializes the ECSPI.
376 *
377 * Calling this API resets the ECSPI module, gates the ECSPI clock.
378 * The ECSPI module can't work unless calling the ECSPI_MasterInit/ECSPI_SlaveInit to initialize module.
379 *
380 * param base ECSPI base pointer
381 */
ECSPI_Deinit(ECSPI_Type * base)382 void ECSPI_Deinit(ECSPI_Type *base)
383 {
384 /* Disable ECSPI module before shutting down */
385 base->CONREG &= ~ECSPI_CONREG_EN_MASK;
386
387 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
388 /* Gate the clock */
389 CLOCK_DisableClock(s_ecspiClock[ECSPI_GetInstance(base)]);
390 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
391 }
392
393 /*!
394 * brief Sets the baud rate for ECSPI transfer. This is only used in master.
395 *
396 * param base ECSPI base pointer
397 * param baudRate_Bps baud rate needed in Hz.
398 * param srcClock_Hz ECSPI source clock frequency in Hz.
399 */
ECSPI_SetBaudRate(ECSPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)400 void ECSPI_SetBaudRate(ECSPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
401 {
402 assert(base);
403
404 uint8_t bestPreDividerValue = 0U, preDividerValue = 0U;
405 uint8_t bestPostDividerValue = 0U, postDividerValue = 0U;
406 uint32_t realBaudrate = 0U;
407 uint32_t diff = 0xFFFFFFFFU;
408 uint32_t min_diff = 0xFFFFFFFFU;
409
410 for (preDividerValue = 0U; preDividerValue < 16U; preDividerValue++)
411 {
412 if (diff == 0U)
413 {
414 break;
415 }
416
417 for (postDividerValue = 0U; postDividerValue < 16U; postDividerValue++)
418 {
419 if (diff == 0U)
420 {
421 break;
422 }
423
424 realBaudrate = (srcClock_Hz / (preDividerValue + 1UL)) >> postDividerValue;
425 if (realBaudrate > baudRate_Bps)
426 {
427 diff = realBaudrate - baudRate_Bps;
428 if (diff < min_diff)
429 {
430 min_diff = diff;
431 bestPreDividerValue = preDividerValue;
432 bestPostDividerValue = postDividerValue;
433 }
434 }
435 else
436 {
437 diff = baudRate_Bps - realBaudrate;
438 if (diff < min_diff)
439 {
440 min_diff = diff;
441 bestPreDividerValue = preDividerValue;
442 bestPostDividerValue = postDividerValue;
443 }
444 }
445 }
446 }
447
448 base->CONREG |= ECSPI_CONREG_PRE_DIVIDER(bestPreDividerValue) | ECSPI_CONREG_POST_DIVIDER(bestPostDividerValue);
449 }
450
451 /*!
452 * brief Set channel select configuration for transfer.
453 *
454 * The purpose of this API is to set the channel will be use to transfer.
455 * User may use this API after instance has been initialized or before transfer start.
456 * The configuration structure #_ecspi_channel_config_ can be filled by user from scratch.
457 * After calling this API, user can select this channel as transfer channel.
458 *
459 * param base ECSPI base pointer
460 * param channel Channel source.
461 * param config Configuration struct of channel
462 */
ECSPI_SetChannelConfig(ECSPI_Type * base,ecspi_channel_source_t channel,const ecspi_channel_config_t * config)463 void ECSPI_SetChannelConfig(ECSPI_Type *base, ecspi_channel_source_t channel, const ecspi_channel_config_t *config)
464 {
465 switch (channel)
466 {
467 case kECSPI_Channel0:
468 base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode);
469 base->CONFIGREG |=
470 (ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) |
471 ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) |
472 ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) | ECSPI_CONFIGREG_SS_CTL(config->waveForm) |
473 ECSPI_CONFIGREG_SCLK_POL(config->polarity) | ECSPI_CONFIGREG_SCLK_PHA(config->phase));
474 break;
475
476 case kECSPI_Channel1:
477 base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 1U;
478 base->CONFIGREG |=
479 ((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 1U) |
480 (ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 1U) |
481 (ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 1U) |
482 (ECSPI_CONFIGREG_SS_CTL(config->waveForm) << 1U) | (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 1U) |
483 (ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 1U));
484 break;
485
486 case kECSPI_Channel2:
487 base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 2;
488 base->CONFIGREG |=
489 ((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 2) |
490 (ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 2) |
491 (ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 2) |
492 (ECSPI_CONFIGREG_SS_CTL(config->waveForm) << 2) | (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 2) |
493 (ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 2));
494 break;
495
496 case kECSPI_Channel3:
497 base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 3;
498 base->CONFIGREG |=
499 ((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 3) |
500 (ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 3) |
501 (ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 3) |
502 (ECSPI_CONFIGREG_SS_CTL(config->waveForm) << 3) | (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 3) |
503 (ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 3));
504 break;
505
506 default:
507 assert(false);
508 break;
509 }
510 }
511
512 /*!
513 * brief Sends a buffer of data bytes using a blocking method.
514 *
515 * note This function blocks via polling until all bytes have been sent.
516 *
517 * param base ECSPI base pointer
518 * param buffer The data bytes to send
519 * param size The number of data bytes to send
520 * retval kStatus_Success Successfully start a transfer.
521 * retval kStatus_ECSPI_Timeout The transfer timed out and was aborted.
522 */
ECSPI_WriteBlocking(ECSPI_Type * base,uint32_t * buffer,size_t size)523 status_t ECSPI_WriteBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
524 {
525 size_t i = 0U;
526 #if SPI_RETRY_TIMES
527 uint32_t waitTimes;
528 #endif
529
530 while (i < size)
531 {
532 /* Wait for TX fifo buffer empty */
533 #if SPI_RETRY_TIMES
534 waitTimes = SPI_RETRY_TIMES;
535 while (((base->STATREG & ECSPI_STATREG_TE_MASK) == 0UL) && (--waitTimes != 0U))
536 #else
537 while ((base->STATREG & ECSPI_STATREG_TE_MASK) == 0UL)
538 #endif
539 {
540 }
541
542 #if SPI_RETRY_TIMES
543 if (waitTimes == 0U)
544 {
545 return kStatus_ECSPI_Timeout;
546 }
547 #endif
548
549 /* Write data to tx register */
550 if (NULL != buffer)
551 {
552 ECSPI_WriteData(base, *buffer++);
553 }
554 else
555 {
556 ECSPI_WriteData(base, ECSPI_DUMMYDATA);
557 }
558 i++;
559 }
560 return kStatus_Success;
561 }
562
ECSPI_ReadBlocking(ECSPI_Type * base,uint32_t * buffer,size_t size)563 static status_t ECSPI_ReadBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
564 {
565 assert(base);
566
567 uint32_t state = 0U;
568 size_t i = 0U;
569 #if SPI_RETRY_TIMES
570 uint32_t waitTimes;
571 #endif
572
573 while (i < size)
574 {
575 /* Wait for RX FIFO buffer ready */
576 #if SPI_RETRY_TIMES
577 waitTimes = SPI_RETRY_TIMES;
578 while (((base->STATREG & ECSPI_STATREG_RR_MASK) == 0UL) && (--waitTimes != 0U))
579 #else
580 while ((base->STATREG & ECSPI_STATREG_RR_MASK) == 0UL)
581 #endif
582 {
583 /* Get status flags of ECSPI */
584 state = ECSPI_GetStatusFlags(base);
585 /* If hardware overflow happen */
586 if ((ECSPI_STATREG_RO_MASK & state) != 0UL)
587 {
588 /* Clear overflow flag for next transfer */
589 ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
590 return kStatus_ECSPI_HardwareOverFlow;
591 }
592 }
593
594 #if SPI_RETRY_TIMES
595 if (waitTimes == 0U)
596 {
597 return kStatus_ECSPI_Timeout;
598 }
599 #endif
600
601 /* Read data from rx register */
602 if (NULL != buffer)
603 {
604 *buffer++ = ECSPI_ReadData(base);
605 }
606 else
607 {
608 (void)ECSPI_ReadData(base);
609 }
610 i++;
611 }
612 return kStatus_Success;
613 }
614
615 /*!
616 * brief Initializes the ECSPI master handle.
617 *
618 * This function initializes the ECSPI master handle which can be used for other ECSPI master transactional APIs.
619 * Usually,
620 * for a specified ECSPI instance, call this API once to get the initialized handle.
621 *
622 * param base ECSPI peripheral base address.
623 * param handle ECSPI handle pointer.
624 * param callback Callback function.
625 * param userData User data.
626 */
ECSPI_MasterTransferCreateHandle(ECSPI_Type * base,ecspi_master_handle_t * handle,ecspi_master_callback_t callback,void * userData)627 void ECSPI_MasterTransferCreateHandle(ECSPI_Type *base,
628 ecspi_master_handle_t *handle,
629 ecspi_master_callback_t callback,
630 void *userData)
631 {
632 assert(base);
633 assert(handle);
634
635 uint32_t instance = ECSPI_GetInstance(base);
636
637 /* Initialize the handle */
638 s_ecspiHandle[instance] = handle;
639 handle->callback = callback;
640 handle->userData = userData;
641 s_ecspiMasterIsr = ECSPI_MasterTransferHandleIRQ;
642
643 /* Enable ECSPI NVIC */
644 (void)EnableIRQ(s_ecspiIRQ[instance]);
645 }
646
647 /*!
648 * brief Transfers a block of data using a polling method.
649 *
650 * param base SPI base pointer
651 * param xfer pointer to spi_xfer_config_t structure
652 * retval kStatus_Success Successfully start a transfer.
653 * retval kStatus_InvalidArgument Input argument is invalid.
654 * retval kStatus_ECSPI_Timeout The transfer timed out and was aborted.
655 */
ECSPI_MasterTransferBlocking(ECSPI_Type * base,ecspi_transfer_t * xfer)656 status_t ECSPI_MasterTransferBlocking(ECSPI_Type *base, ecspi_transfer_t *xfer)
657 {
658 assert(base && xfer);
659
660 status_t state;
661 uint32_t burstLength = 0U;
662 uint32_t dataCounts = 0U;
663 /* Check if the argument is legal */
664 if ((xfer->txData == NULL) && (xfer->rxData == NULL))
665 {
666 return kStatus_InvalidArgument;
667 }
668 /* Select ECSPI channel to current channel
669 * Note:
670 * xfer.channel must be configured before transfer, because every channel has
671 * it's own configuration,if don't configure this parameter, transfer channel
672 * will use the default channel0.
673 */
674 ECSPI_SetChannelSelect(base, xfer->channel);
675 /* Caculate the data size need to be send for one burst */
676 burstLength = ((base->CONREG & ECSPI_CONREG_BURST_LENGTH_MASK) >> ECSPI_CONREG_BURST_LENGTH_SHIFT) + 1UL;
677 dataCounts = ((burstLength % 32UL) != 0UL) ? (burstLength / 32UL + 1UL) : (burstLength / 32UL);
678
679 while (xfer->dataSize > 0UL)
680 {
681 /* ECSPI will transmit and receive at the same time, if txData is NULL,
682 * instance will transmit dummy data, the dummy data can be set by user.
683 * if rxData is NULL, data will be read from RX FIFO buffer, but the
684 * data will be ignored by driver.
685 * Note that, txData and rxData can not be both NULL.
686 */
687 state = ECSPI_WriteBlocking(base, xfer->txData, dataCounts);
688 if (kStatus_Success != state)
689 {
690 return state;
691 }
692 if (NULL != xfer->txData)
693 {
694 xfer->txData += dataCounts;
695 }
696 state = ECSPI_ReadBlocking(base, xfer->rxData, dataCounts);
697 if (kStatus_Success != state)
698 {
699 return state;
700 }
701 if (NULL != xfer->rxData)
702 {
703 xfer->rxData += dataCounts;
704 }
705
706 xfer->dataSize -= dataCounts;
707 }
708
709 return kStatus_Success;
710 }
711
712 /*!
713 * brief Performs a non-blocking ECSPI interrupt transfer.
714 *
715 * note The API immediately returns after transfer initialization is finished.
716 * note If ECSPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
717 *
718 * param base ECSPI peripheral base address.
719 * param handle pointer to ecspi_master_handle_t structure which stores the transfer state
720 * param xfer pointer to ecspi_transfer_t structure
721 * retval kStatus_Success Successfully start a transfer.
722 * retval kStatus_InvalidArgument Input argument is invalid.
723 * retval kStatus_ECSPI_Busy ECSPI is not idle, is running another transfer.
724 */
ECSPI_MasterTransferNonBlocking(ECSPI_Type * base,ecspi_master_handle_t * handle,ecspi_transfer_t * xfer)725 status_t ECSPI_MasterTransferNonBlocking(ECSPI_Type *base, ecspi_master_handle_t *handle, ecspi_transfer_t *xfer)
726 {
727 assert(base && handle && xfer);
728
729 /* Check if ECSPI is busy */
730 if (handle->state == (uint32_t)kECSPI_Busy)
731 {
732 return kStatus_ECSPI_Busy;
733 }
734
735 /* Check if the input arguments valid */
736 if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
737 {
738 return kStatus_InvalidArgument;
739 }
740
741 /* Set the handle information */
742 handle->channel = xfer->channel;
743 handle->txData = xfer->txData;
744 handle->rxData = xfer->rxData;
745 handle->transferSize = xfer->dataSize;
746 handle->txRemainingBytes = xfer->dataSize;
747 handle->rxRemainingBytes = xfer->dataSize;
748
749 /* Set the ECSPI state to busy */
750 handle->state = kECSPI_Busy;
751
752 /* Select ECSPI channel to current channel
753 * Note:
754 * xfer.channel must be configured before transferfer, because every channel has
755 * it's own configuration, if don't configure this parameter, transfer channel
756 * will use the default channel0.
757 */
758 ECSPI_SetChannelSelect(base, xfer->channel);
759
760 /* First send data to Tx FIFO to start a ECSPI transfer */
761 ECSPI_SendTransfer(base, handle);
762
763 if (NULL != xfer->rxData)
764 {
765 /* Enable Rx data request interrupt and receive overflow interrupt, when data in RX FIFO buffer is greater
766 * than the RX_THRESHOLD, then a interrupt occurred. Only enable Rx interrupt,
767 * use rx interrupt to driver ECSPI transfer.
768 */
769 ECSPI_EnableInterrupts(
770 base, (uint32_t)kECSPI_RxFifoReadyInterruptEnable | (uint32_t)kECSPI_RxFifoOverFlowInterruptEnable);
771 }
772 else
773 {
774 /* Enable Tx data request interrupt, when data in TX FIFO buffer is greater
775 * than the TX_THRESHOLD, then a interrupt occurred.
776 */
777 ECSPI_EnableInterrupts(base, kECSPI_TxFifoDataRequstInterruptEnable);
778 }
779
780 return kStatus_Success;
781 }
782
783 /*!
784 * brief Gets the bytes of the ECSPI interrupt transferred.
785 *
786 * param base ECSPI peripheral base address.
787 * param handle Pointer to ECSPI transfer handle, this should be a static variable.
788 * param count Transferred bytes of ECSPI master.
789 * retval kStatus_ECSPI_Success Succeed get the transfer count.
790 * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
791 */
ECSPI_MasterTransferGetCount(ECSPI_Type * base,ecspi_master_handle_t * handle,size_t * count)792 status_t ECSPI_MasterTransferGetCount(ECSPI_Type *base, ecspi_master_handle_t *handle, size_t *count)
793 {
794 assert(handle);
795
796 status_t status = kStatus_Success;
797
798 if (handle->state != (uint32_t)kStatus_ECSPI_Busy)
799 {
800 status = kStatus_NoTransferInProgress;
801 }
802 else
803 {
804 /* Return remaing bytes in different cases */
805 if (handle->rxData != NULL)
806 {
807 *count = handle->transferSize - handle->rxRemainingBytes;
808 }
809 else
810 {
811 *count = handle->transferSize - handle->txRemainingBytes;
812 }
813 }
814
815 return status;
816 }
817
818 /*!
819 * brief Aborts an ECSPI transfer using interrupt.
820 *
821 * param base ECSPI peripheral base address.
822 * param handle Pointer to ECSPI transfer handle, this should be a static variable.
823 */
ECSPI_MasterTransferAbort(ECSPI_Type * base,ecspi_master_handle_t * handle)824 void ECSPI_MasterTransferAbort(ECSPI_Type *base, ecspi_master_handle_t *handle)
825 {
826 assert(handle);
827
828 /* Stop interrupts */
829 if (NULL != handle->rxData)
830 {
831 ECSPI_DisableInterrupts(
832 base, (uint32_t)kECSPI_RxFifoReadyInterruptEnable | (uint32_t)kECSPI_RxFifoOverFlowInterruptEnable);
833 }
834 else
835 {
836 ECSPI_DisableInterrupts(base, kECSPI_TxFifoDataRequstInterruptEnable);
837 }
838 /* Transfer finished, set the state to Done*/
839 handle->state = kECSPI_Idle;
840
841 /* Clear the internal state */
842 handle->rxRemainingBytes = 0;
843 handle->txRemainingBytes = 0;
844 }
845
846 /*!
847 * brief Interrupts the handler for the ECSPI.
848 *
849 * param base ECSPI peripheral base address.
850 * param handle pointer to ecspi_master_handle_t structure which stores the transfer state.
851 */
ECSPI_MasterTransferHandleIRQ(ECSPI_Type * base,ecspi_master_handle_t * handle)852 void ECSPI_MasterTransferHandleIRQ(ECSPI_Type *base, ecspi_master_handle_t *handle)
853 {
854 assert(handle);
855
856 /* If hardware overflow happens */
857 if ((base->STATREG & ECSPI_STATREG_RO_MASK) != 0UL)
858 {
859 /* Clear overflow flag for next transfer */
860 ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
861 if ((handle->callback) != NULL)
862 {
863 (handle->callback)(base, handle, kStatus_ECSPI_HardwareOverFlow, handle->userData);
864 }
865 }
866 /* If need to receive data, do a receive */
867 if ((handle->rxRemainingBytes) != 0UL)
868 {
869 ECSPI_ReceiveTransfer(base, handle);
870 }
871
872 /* We always need to send a data to make the ECSPI run */
873 if ((handle->txRemainingBytes) != 0UL)
874 {
875 ECSPI_SendTransfer(base, handle);
876 }
877
878 /* All the transfer finished */
879 if ((handle->txRemainingBytes == 0UL) && (handle->rxRemainingBytes == 0UL))
880 {
881 /* Complete the transfer */
882 ECSPI_MasterTransferAbort(base, handle);
883
884 if ((handle->callback) != NULL)
885 {
886 (handle->callback)(base, handle, kStatus_Success, handle->userData);
887 }
888 }
889 }
890
891 /*!
892 * brief Initializes the ECSPI slave handle.
893 *
894 * This function initializes the ECSPI slave handle which can be used for other ECSPI slave transactional APIs. Usually,
895 * for a specified ECSPI instance, call this API once to get the initialized handle.
896 *
897 * param base ECSPI peripheral base address.
898 * param handle ECSPI handle pointer.
899 * param callback Callback function.
900 * param userData User data.
901 */
ECSPI_SlaveTransferCreateHandle(ECSPI_Type * base,ecspi_slave_handle_t * handle,ecspi_slave_callback_t callback,void * userData)902 void ECSPI_SlaveTransferCreateHandle(ECSPI_Type *base,
903 ecspi_slave_handle_t *handle,
904 ecspi_slave_callback_t callback,
905 void *userData)
906 {
907 assert(handle);
908
909 /* Slave create handle share same logic with master create handle, the only difference
910 is the Isr pointer. */
911 ECSPI_MasterTransferCreateHandle(base, handle, callback, userData);
912 s_ecspiSlaveIsr = ECSPI_SlaveTransferHandleIRQ;
913 }
914
915 /*!
916 * brief Interrupts a handler for the ECSPI slave.
917 *
918 * param base ECSPI peripheral base address.
919 * param handle pointer to ecspi_slave_handle_t structure which stores the transfer state
920 */
ECSPI_SlaveTransferHandleIRQ(ECSPI_Type * base,ecspi_slave_handle_t * handle)921 void ECSPI_SlaveTransferHandleIRQ(ECSPI_Type *base, ecspi_slave_handle_t *handle)
922 {
923 assert(handle);
924 /* If hardware overflow happens */
925 if ((base->STATREG & ECSPI_STATREG_RO_MASK) != 0UL)
926 {
927 /* Clear overflow flag for next transfer */
928 ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
929 if ((handle->callback) != NULL)
930 {
931 (handle->callback)(base, handle, kStatus_ECSPI_HardwareOverFlow, handle->userData);
932 }
933 }
934 /* If needs to receive data, do a receive */
935 if ((handle->rxRemainingBytes) != 0UL)
936 {
937 ECSPI_ReceiveTransfer(base, handle);
938 }
939
940 /* We always need to send a data to make the ECSPI run */
941 if ((handle->txRemainingBytes) != 0UL)
942 {
943 ECSPI_SendTransfer(base, handle);
944 }
945
946 /* All the transfer finished */
947 if ((handle->txRemainingBytes == 0UL) && (handle->rxRemainingBytes == 0UL))
948 {
949 /* Complete the transfer */
950 ECSPI_SlaveTransferAbort(base, handle);
951
952 if ((handle->callback) != NULL)
953 {
954 (handle->callback)(base, handle, kStatus_Success, handle->userData);
955 }
956 }
957 }
958
ECSPI_CommonIRQHandler(ECSPI_Type * base,ecspi_master_handle_t * handle)959 static void ECSPI_CommonIRQHandler(ECSPI_Type *base, ecspi_master_handle_t *handle)
960 {
961 if (ECSPI_IsMaster(base, handle->channel))
962 {
963 s_ecspiMasterIsr(base, handle);
964 }
965 else
966 {
967 s_ecspiSlaveIsr(base, handle);
968 }
969 SDK_ISR_EXIT_BARRIER;
970 }
971
972 #if defined(ECSPI1)
ECSPI1_DriverIRQHandler(void)973 void ECSPI1_DriverIRQHandler(void)
974 {
975 assert(s_ecspiHandle[1]);
976 ECSPI_CommonIRQHandler(ECSPI1, s_ecspiHandle[1]);
977 }
978 #endif /* ECSPI1 */
979
980 #if defined(ECSPI2)
ECSPI2_DriverIRQHandler(void)981 void ECSPI2_DriverIRQHandler(void)
982 {
983 assert(s_ecspiHandle[2]);
984 ECSPI_CommonIRQHandler(ECSPI2, s_ecspiHandle[2]);
985 }
986 #endif /* ECSPI2 */
987
988 #if defined(ECSPI3)
ECSPI3_DriverIRQHandler(void)989 void ECSPI3_DriverIRQHandler(void)
990 {
991 assert(s_ecspiHandle[3]);
992 ECSPI_CommonIRQHandler(ECSPI3, s_ecspiHandle[3]);
993 }
994 #endif /* ECSPI3 */
995
996 #if defined(ECSPI4)
ECSPI4_DriverIRQHandler(void)997 void ECSPI4_DriverIRQHandler(void)
998 {
999 assert(s_ecspiHandle[4]);
1000 ECSPI_CommonIRQHandler(ECSPI4, s_ecspiHandle[4]);
1001 }
1002 #endif /* ECSPI4 */
1003