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