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