1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2023 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 != NULL);
175 assert(handle != NULL);
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 != NULL);
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->polarity = kECSPI_PolarityActiveHigh; /*!< Clock polarity */
221 config->phase = kECSPI_ClockPhaseFirstEdge; /*!< clock phase */
222 }
223
224 /*!
225 * brief Sets the ECSPI configuration structure to default values.
226 *
227 * The purpose of this API is to get the configuration structure initialized for use in ECSPI_MasterInit().
228 * User may use the initialized structure unchanged in ECSPI_MasterInit, or modify
229 * some fields of the structure before calling ECSPI_MasterInit. After calling this API,
230 * the master is ready to transfer.
231 * Example:
232 code
233 ecspi_master_config_t config;
234 ECSPI_MasterGetDefaultConfig(&config);
235 endcode
236 *
237 * param config pointer to config structure
238 */
ECSPI_MasterGetDefaultConfig(ecspi_master_config_t * config)239 void ECSPI_MasterGetDefaultConfig(ecspi_master_config_t *config)
240 {
241 /* Initializes the configure structure to zero. */
242 (void)memset(config, 0, sizeof(*config));
243
244 config->channel = kECSPI_Channel0;
245 config->burstLength = 8;
246 config->samplePeriodClock = kECSPI_spiClock;
247 config->baudRate_Bps = 500000;
248 config->chipSelectDelay = 0;
249 config->samplePeriod = 0;
250 config->txFifoThreshold = 1;
251 config->rxFifoThreshold = 0;
252 /* Default configuration of channel */
253 ECSPI_GetDefaultChannelConfig(&config->channelConfig);
254 /*!< ECSPI peripheral operates in slave mode.*/
255 config->channelConfig.channelMode = kECSPI_Master;
256 config->enableLoopback = false;
257 }
258
259 /*!
260 * brief Initializes the ECSPI with configuration.
261 *
262 * The configuration structure can be filled by user from scratch, or be set with default
263 * values by ECSPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer.
264 * Example
265 code
266 ecspi_master_config_t config = {
267 .baudRate_Bps = 400000,
268 ...
269 };
270 ECSPI_MasterInit(ECSPI0, &config);
271 endcode
272 *
273 * param base ECSPI base pointer
274 * param config pointer to master configuration structure
275 * param srcClock_Hz Source clock frequency.
276 */
ECSPI_MasterInit(ECSPI_Type * base,const ecspi_master_config_t * config,uint32_t srcClock_Hz)277 void ECSPI_MasterInit(ECSPI_Type *base, const ecspi_master_config_t *config, uint32_t srcClock_Hz)
278 {
279 assert((config != NULL) && (srcClock_Hz != 0U));
280 assert(config->burstLength <= 4096U);
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 != NULL) && (config != NULL));
357 assert(config->burstLength <= 4096U);
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 != NULL);
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 |= (ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) |
470 ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) |
471 ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) |
472 ECSPI_CONFIGREG_SCLK_POL(config->polarity) | ECSPI_CONFIGREG_SCLK_PHA(config->phase));
473 break;
474
475 case kECSPI_Channel1:
476 base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 1U;
477 base->CONFIGREG |=
478 ((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 1U) |
479 (ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 1U) |
480 (ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 1U) |
481 (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 1U) | (ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 1U));
482 break;
483
484 case kECSPI_Channel2:
485 base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 2;
486 base->CONFIGREG |=
487 ((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 2) |
488 (ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 2) |
489 (ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 2) |
490 (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 2) | (ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 2));
491 break;
492
493 case kECSPI_Channel3:
494 base->CONREG |= ECSPI_CONREG_CHANNEL_MODE(config->channelMode) << 3;
495 base->CONFIGREG |=
496 ((ECSPI_CONFIGREG_SCLK_CTL(config->clockInactiveState) << 3) |
497 (ECSPI_CONFIGREG_DATA_CTL(config->dataLineInactiveState) << 3) |
498 (ECSPI_CONFIGREG_SS_POL(config->chipSlectActiveState) << 3) |
499 (ECSPI_CONFIGREG_SCLK_POL(config->polarity) << 3) | (ECSPI_CONFIGREG_SCLK_PHA(config->phase) << 3));
500 break;
501
502 default:
503 assert(false);
504 break;
505 }
506 }
507
508 /*!
509 * brief Sends a buffer of data bytes using a blocking method.
510 *
511 * note This function blocks via polling until all bytes have been sent.
512 *
513 * param base ECSPI base pointer
514 * param buffer The data bytes to send
515 * param size The number of data bytes to send
516 * retval kStatus_Success Successfully start a transfer.
517 * retval kStatus_ECSPI_Timeout The transfer timed out and was aborted.
518 */
ECSPI_WriteBlocking(ECSPI_Type * base,uint32_t * buffer,size_t size)519 status_t ECSPI_WriteBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
520 {
521 size_t i = 0U;
522 #if SPI_RETRY_TIMES
523 uint32_t waitTimes;
524 #endif
525
526 while (i < size)
527 {
528 /* Wait for TX fifo buffer empty */
529 #if SPI_RETRY_TIMES
530 waitTimes = SPI_RETRY_TIMES;
531 while (((base->STATREG & ECSPI_STATREG_TE_MASK) == 0UL) && (--waitTimes != 0U))
532 #else
533 while ((base->STATREG & ECSPI_STATREG_TE_MASK) == 0UL)
534 #endif
535 {
536 }
537
538 #if SPI_RETRY_TIMES
539 if (waitTimes == 0U)
540 {
541 return kStatus_ECSPI_Timeout;
542 }
543 #endif
544
545 /* Write data to tx register */
546 if (NULL != buffer)
547 {
548 ECSPI_WriteData(base, *buffer++);
549 }
550 else
551 {
552 ECSPI_WriteData(base, ECSPI_DUMMYDATA);
553 }
554 i++;
555 }
556 return kStatus_Success;
557 }
558
ECSPI_ReadBlocking(ECSPI_Type * base,uint32_t * buffer,size_t size)559 static status_t ECSPI_ReadBlocking(ECSPI_Type *base, uint32_t *buffer, size_t size)
560 {
561 assert(base != NULL);
562
563 uint32_t state = 0U;
564 size_t i = 0U;
565 #if SPI_RETRY_TIMES
566 uint32_t waitTimes;
567 #endif
568
569 while (i < size)
570 {
571 /* Wait for RX FIFO buffer ready */
572 #if SPI_RETRY_TIMES
573 waitTimes = SPI_RETRY_TIMES;
574 while (((base->STATREG & ECSPI_STATREG_RR_MASK) == 0UL) && (--waitTimes != 0U))
575 #else
576 while ((base->STATREG & ECSPI_STATREG_RR_MASK) == 0UL)
577 #endif
578 {
579 /* Get status flags of ECSPI */
580 state = ECSPI_GetStatusFlags(base);
581 /* If hardware overflow happen */
582 if ((ECSPI_STATREG_RO_MASK & state) != 0UL)
583 {
584 /* Clear overflow flag for next transfer */
585 ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
586 return kStatus_ECSPI_HardwareOverFlow;
587 }
588 }
589
590 #if SPI_RETRY_TIMES
591 if (waitTimes == 0U)
592 {
593 return kStatus_ECSPI_Timeout;
594 }
595 #endif
596
597 /* Read data from rx register */
598 if (NULL != buffer)
599 {
600 *buffer++ = ECSPI_ReadData(base);
601 }
602 else
603 {
604 (void)ECSPI_ReadData(base);
605 }
606 i++;
607 }
608 return kStatus_Success;
609 }
610
611 /*!
612 * brief Initializes the ECSPI master handle.
613 *
614 * This function initializes the ECSPI master handle which can be used for other ECSPI master transactional APIs.
615 * Usually,
616 * for a specified ECSPI instance, call this API once to get the initialized handle.
617 *
618 * param base ECSPI peripheral base address.
619 * param handle ECSPI handle pointer.
620 * param callback Callback function.
621 * param userData User data.
622 */
ECSPI_MasterTransferCreateHandle(ECSPI_Type * base,ecspi_master_handle_t * handle,ecspi_master_callback_t callback,void * userData)623 void ECSPI_MasterTransferCreateHandle(ECSPI_Type *base,
624 ecspi_master_handle_t *handle,
625 ecspi_master_callback_t callback,
626 void *userData)
627 {
628 assert(base != NULL);
629 assert(handle != NULL);
630
631 uint32_t instance = ECSPI_GetInstance(base);
632
633 /* Initialize the handle */
634 s_ecspiHandle[instance] = handle;
635 handle->callback = callback;
636 handle->userData = userData;
637 s_ecspiMasterIsr = ECSPI_MasterTransferHandleIRQ;
638
639 /* Enable ECSPI NVIC */
640 (void)EnableIRQ(s_ecspiIRQ[instance]);
641 }
642
643 /*!
644 * brief Transfers a block of data using a polling method.
645 *
646 * param base SPI base pointer
647 * param xfer pointer to spi_xfer_config_t structure
648 * retval kStatus_Success Successfully start a transfer.
649 * retval kStatus_InvalidArgument Input argument is invalid.
650 * retval kStatus_ECSPI_Timeout The transfer timed out and was aborted.
651 */
ECSPI_MasterTransferBlocking(ECSPI_Type * base,ecspi_transfer_t * xfer)652 status_t ECSPI_MasterTransferBlocking(ECSPI_Type *base, ecspi_transfer_t *xfer)
653 {
654 assert((base != NULL) && (xfer != NULL));
655
656 status_t state;
657 uint32_t burstLength = 0U;
658 uint32_t dataCounts = 0U;
659 /* Check if the argument is legal */
660 if ((xfer->txData == NULL) && (xfer->rxData == NULL))
661 {
662 return kStatus_InvalidArgument;
663 }
664 /* Select ECSPI channel to current channel
665 * Note:
666 * xfer.channel must be configured before transfer, because every channel has
667 * it's own configuration,if don't configure this parameter, transfer channel
668 * will use the default channel0.
669 */
670 ECSPI_SetChannelSelect(base, xfer->channel);
671 /* Caculate the data size need to be send for one burst */
672 burstLength = ((base->CONREG & ECSPI_CONREG_BURST_LENGTH_MASK) >> ECSPI_CONREG_BURST_LENGTH_SHIFT) + 1UL;
673 dataCounts = ((burstLength % 32UL) != 0UL) ? (burstLength / 32UL + 1UL) : (burstLength / 32UL);
674
675 while (xfer->dataSize > 0UL)
676 {
677 /* ECSPI will transmit and receive at the same time, if txData is NULL,
678 * instance will transmit dummy data, the dummy data can be set by user.
679 * if rxData is NULL, data will be read from RX FIFO buffer, but the
680 * data will be ignored by driver.
681 * Note that, txData and rxData can not be both NULL.
682 */
683 state = ECSPI_WriteBlocking(base, xfer->txData, dataCounts);
684 if (kStatus_Success != state)
685 {
686 return state;
687 }
688 if (NULL != xfer->txData)
689 {
690 xfer->txData += dataCounts;
691 }
692 state = ECSPI_ReadBlocking(base, xfer->rxData, dataCounts);
693 if (kStatus_Success != state)
694 {
695 return state;
696 }
697 if (NULL != xfer->rxData)
698 {
699 xfer->rxData += dataCounts;
700 }
701
702 xfer->dataSize -= dataCounts;
703 }
704
705 return kStatus_Success;
706 }
707
708 /*!
709 * brief Performs a non-blocking ECSPI interrupt transfer.
710 *
711 * note The API immediately returns after transfer initialization is finished.
712 * note If ECSPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
713 *
714 * param base ECSPI peripheral base address.
715 * param handle pointer to ecspi_master_handle_t structure which stores the transfer state
716 * param xfer pointer to ecspi_transfer_t structure
717 * retval kStatus_Success Successfully start a transfer.
718 * retval kStatus_InvalidArgument Input argument is invalid.
719 * retval kStatus_ECSPI_Busy ECSPI is not idle, is running another transfer.
720 */
ECSPI_MasterTransferNonBlocking(ECSPI_Type * base,ecspi_master_handle_t * handle,ecspi_transfer_t * xfer)721 status_t ECSPI_MasterTransferNonBlocking(ECSPI_Type *base, ecspi_master_handle_t *handle, ecspi_transfer_t *xfer)
722 {
723 assert((base != NULL) && (handle != NULL) && (xfer != NULL));
724
725 /* Check if ECSPI is busy */
726 if (handle->state == (uint32_t)kECSPI_Busy)
727 {
728 return kStatus_ECSPI_Busy;
729 }
730
731 /* Check if the input arguments valid */
732 if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
733 {
734 return kStatus_InvalidArgument;
735 }
736
737 /* Set the handle information */
738 handle->channel = xfer->channel;
739 handle->txData = xfer->txData;
740 handle->rxData = xfer->rxData;
741 handle->transferSize = xfer->dataSize;
742 handle->txRemainingBytes = xfer->dataSize;
743 handle->rxRemainingBytes = xfer->dataSize;
744
745 /* Set the ECSPI state to busy */
746 handle->state = kECSPI_Busy;
747
748 /* Select ECSPI channel to current channel
749 * Note:
750 * xfer.channel must be configured before transferfer, because every channel has
751 * it's own configuration, if don't configure this parameter, transfer channel
752 * will use the default channel0.
753 */
754 ECSPI_SetChannelSelect(base, xfer->channel);
755
756 /* First send data to Tx FIFO to start a ECSPI transfer */
757 ECSPI_SendTransfer(base, handle);
758
759 if (NULL != xfer->rxData)
760 {
761 /* Enable Rx data request interrupt and receive overflow interrupt, when data in RX FIFO buffer is greater
762 * than the RX_THRESHOLD, then a interrupt occurred. Only enable Rx interrupt,
763 * use rx interrupt to driver ECSPI transfer.
764 */
765 ECSPI_EnableInterrupts(
766 base, (uint32_t)kECSPI_RxFifoReadyInterruptEnable | (uint32_t)kECSPI_RxFifoOverFlowInterruptEnable);
767 }
768 else
769 {
770 /* Enable Tx data request interrupt, when data in TX FIFO buffer is greater
771 * than the TX_THRESHOLD, then a interrupt occurred.
772 */
773 ECSPI_EnableInterrupts(base, kECSPI_TxFifoDataRequstInterruptEnable);
774 }
775
776 return kStatus_Success;
777 }
778
779 /*!
780 * brief Gets the bytes of the ECSPI interrupt transferred.
781 *
782 * param base ECSPI peripheral base address.
783 * param handle Pointer to ECSPI transfer handle, this should be a static variable.
784 * param count Transferred bytes of ECSPI master.
785 * retval kStatus_ECSPI_Success Succeed get the transfer count.
786 * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
787 */
ECSPI_MasterTransferGetCount(ECSPI_Type * base,ecspi_master_handle_t * handle,size_t * count)788 status_t ECSPI_MasterTransferGetCount(ECSPI_Type *base, ecspi_master_handle_t *handle, size_t *count)
789 {
790 assert(handle != NULL);
791
792 status_t status = kStatus_Success;
793
794 if (handle->state != (uint32_t)kStatus_ECSPI_Busy)
795 {
796 status = kStatus_NoTransferInProgress;
797 }
798 else
799 {
800 /* Return remaing bytes in different cases */
801 if (handle->rxData != NULL)
802 {
803 *count = handle->transferSize - handle->rxRemainingBytes;
804 }
805 else
806 {
807 *count = handle->transferSize - handle->txRemainingBytes;
808 }
809 }
810
811 return status;
812 }
813
814 /*!
815 * brief Aborts an ECSPI transfer using interrupt.
816 *
817 * param base ECSPI peripheral base address.
818 * param handle Pointer to ECSPI transfer handle, this should be a static variable.
819 */
ECSPI_MasterTransferAbort(ECSPI_Type * base,ecspi_master_handle_t * handle)820 void ECSPI_MasterTransferAbort(ECSPI_Type *base, ecspi_master_handle_t *handle)
821 {
822 assert(handle != NULL);
823
824 /* Stop interrupts */
825 if (NULL != handle->rxData)
826 {
827 ECSPI_DisableInterrupts(
828 base, (uint32_t)kECSPI_RxFifoReadyInterruptEnable | (uint32_t)kECSPI_RxFifoOverFlowInterruptEnable);
829 }
830 else
831 {
832 ECSPI_DisableInterrupts(base, kECSPI_TxFifoDataRequstInterruptEnable);
833 }
834 /* Transfer finished, set the state to Done*/
835 handle->state = kECSPI_Idle;
836
837 /* Clear the internal state */
838 handle->rxRemainingBytes = 0;
839 handle->txRemainingBytes = 0;
840 }
841
842 /*!
843 * brief Interrupts the handler for the ECSPI.
844 *
845 * param base ECSPI peripheral base address.
846 * param handle pointer to ecspi_master_handle_t structure which stores the transfer state.
847 */
ECSPI_MasterTransferHandleIRQ(ECSPI_Type * base,ecspi_master_handle_t * handle)848 void ECSPI_MasterTransferHandleIRQ(ECSPI_Type *base, ecspi_master_handle_t *handle)
849 {
850 assert(handle != NULL);
851
852 /* If hardware overflow happens */
853 if ((base->STATREG & ECSPI_STATREG_RO_MASK) != 0UL)
854 {
855 /* Clear overflow flag for next transfer */
856 ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
857 if ((handle->callback) != NULL)
858 {
859 (handle->callback)(base, handle, kStatus_ECSPI_HardwareOverFlow, handle->userData);
860 }
861 }
862 /* If need to receive data, do a receive */
863 if ((handle->rxRemainingBytes) != 0UL)
864 {
865 ECSPI_ReceiveTransfer(base, handle);
866 }
867
868 /* We always need to send a data to make the ECSPI run */
869 if ((handle->txRemainingBytes) != 0UL)
870 {
871 ECSPI_SendTransfer(base, handle);
872 }
873
874 /* All the transfer finished */
875 if ((handle->txRemainingBytes == 0UL) && (handle->rxRemainingBytes == 0UL))
876 {
877 /* Complete the transfer */
878 ECSPI_MasterTransferAbort(base, handle);
879
880 if ((handle->callback) != NULL)
881 {
882 (handle->callback)(base, handle, kStatus_Success, handle->userData);
883 }
884 }
885 }
886
887 /*!
888 * brief Initializes the ECSPI slave handle.
889 *
890 * This function initializes the ECSPI slave handle which can be used for other ECSPI slave transactional APIs. Usually,
891 * for a specified ECSPI instance, call this API once to get the initialized handle.
892 *
893 * param base ECSPI peripheral base address.
894 * param handle ECSPI handle pointer.
895 * param callback Callback function.
896 * param userData User data.
897 */
ECSPI_SlaveTransferCreateHandle(ECSPI_Type * base,ecspi_slave_handle_t * handle,ecspi_slave_callback_t callback,void * userData)898 void ECSPI_SlaveTransferCreateHandle(ECSPI_Type *base,
899 ecspi_slave_handle_t *handle,
900 ecspi_slave_callback_t callback,
901 void *userData)
902 {
903 assert(handle != NULL);
904
905 /* Slave create handle share same logic with master create handle, the only difference
906 is the Isr pointer. */
907 ECSPI_MasterTransferCreateHandle(base, handle, callback, userData);
908 s_ecspiSlaveIsr = ECSPI_SlaveTransferHandleIRQ;
909 }
910
911 /*!
912 * brief Interrupts a handler for the ECSPI slave.
913 *
914 * param base ECSPI peripheral base address.
915 * param handle pointer to ecspi_slave_handle_t structure which stores the transfer state
916 */
ECSPI_SlaveTransferHandleIRQ(ECSPI_Type * base,ecspi_slave_handle_t * handle)917 void ECSPI_SlaveTransferHandleIRQ(ECSPI_Type *base, ecspi_slave_handle_t *handle)
918 {
919 assert(handle != NULL);
920 /* If hardware overflow happens */
921 if ((base->STATREG & ECSPI_STATREG_RO_MASK) != 0UL)
922 {
923 /* Clear overflow flag for next transfer */
924 ECSPI_ClearStatusFlags(base, kECSPI_RxFifoOverFlowFlag);
925 if ((handle->callback) != NULL)
926 {
927 (handle->callback)(base, handle, kStatus_ECSPI_HardwareOverFlow, handle->userData);
928 }
929 }
930 /* If needs to receive data, do a receive */
931 if ((handle->rxRemainingBytes) != 0UL)
932 {
933 ECSPI_ReceiveTransfer(base, handle);
934 }
935
936 /* We always need to send a data to make the ECSPI run */
937 if ((handle->txRemainingBytes) != 0UL)
938 {
939 ECSPI_SendTransfer(base, handle);
940 }
941
942 /* All the transfer finished */
943 if ((handle->txRemainingBytes == 0UL) && (handle->rxRemainingBytes == 0UL))
944 {
945 /* Complete the transfer */
946 ECSPI_SlaveTransferAbort(base, handle);
947
948 if ((handle->callback) != NULL)
949 {
950 (handle->callback)(base, handle, kStatus_Success, handle->userData);
951 }
952 }
953 }
954
ECSPI_CommonIRQHandler(ECSPI_Type * base,ecspi_master_handle_t * handle)955 static void ECSPI_CommonIRQHandler(ECSPI_Type *base, ecspi_master_handle_t *handle)
956 {
957 if (ECSPI_IsMaster(base, handle->channel))
958 {
959 s_ecspiMasterIsr(base, handle);
960 }
961 else
962 {
963 s_ecspiSlaveIsr(base, handle);
964 }
965 SDK_ISR_EXIT_BARRIER;
966 }
967
968 #if defined(ECSPI1)
969 void ECSPI1_DriverIRQHandler(void);
ECSPI1_DriverIRQHandler(void)970 void ECSPI1_DriverIRQHandler(void)
971 {
972 assert(s_ecspiHandle[1] != NULL);
973 ECSPI_CommonIRQHandler(ECSPI1, s_ecspiHandle[1]);
974 }
975 #endif /* ECSPI1 */
976
977 #if defined(ECSPI2)
978 void ECSPI2_DriverIRQHandler(void);
ECSPI2_DriverIRQHandler(void)979 void ECSPI2_DriverIRQHandler(void)
980 {
981 assert(s_ecspiHandle[2] != NULL);
982 ECSPI_CommonIRQHandler(ECSPI2, s_ecspiHandle[2]);
983 }
984 #endif /* ECSPI2 */
985
986 #if defined(ECSPI3)
987 void ECSPI3_DriverIRQHandler(void);
ECSPI3_DriverIRQHandler(void)988 void ECSPI3_DriverIRQHandler(void)
989 {
990 assert(s_ecspiHandle[3] != NULL);
991 ECSPI_CommonIRQHandler(ECSPI3, s_ecspiHandle[3]);
992 }
993 #endif /* ECSPI3 */
994
995 #if defined(ECSPI4)
996 void ECSPI4_DriverIRQHandler(void);
ECSPI4_DriverIRQHandler(void)997 void ECSPI4_DriverIRQHandler(void)
998 {
999 assert(s_ecspiHandle[4] != NULL);
1000 ECSPI_CommonIRQHandler(ECSPI4, s_ecspiHandle[4]);
1001 }
1002 #endif /* ECSPI4 */
1003