1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_flexio_spi.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.flexio_spi"
18 #endif
19 
20 /*! @brief FLEXIO SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
21 enum _flexio_spi_transfer_states
22 {
23     kFLEXIO_SPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver's queue. */
24     kFLEXIO_SPI_Busy,        /*!< Transmiter/Receive's queue is not finished. */
25 };
26 
27 /*******************************************************************************
28  * Prototypes
29  ******************************************************************************/
30 
31 /*!
32  * @brief Send a piece of data for SPI.
33  *
34  * This function computes the number of data to be written into D register or Tx FIFO,
35  * and write the data into it. At the same time, this function updates the values in
36  * master handle structure.
37  *
38  * @param base pointer to FLEXIO_SPI_Type structure
39  * @param handle Pointer to SPI master handle structure.
40  */
41 static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
42 
43 /*!
44  * @brief Receive a piece of data for SPI master.
45  *
46  * This function computes the number of data to receive from D register or Rx FIFO,
47  * and write the data to destination address. At the same time, this function updates
48  * the values in master handle structure.
49  *
50  * @param base pointer to FLEXIO_SPI_Type structure
51  * @param handle Pointer to SPI master handle structure.
52  */
53 static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
54 
55 /*******************************************************************************
56  * Variables
57  ******************************************************************************/
58 
59 /*******************************************************************************
60  * Codes
61  ******************************************************************************/
62 
FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type * base)63 static uint32_t FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type *base)
64 {
65     return FLEXIO_GetInstance(base->flexioBase);
66 }
67 
FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)68 static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
69 {
70     uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
71 
72     if (handle->txData != NULL)
73     {
74         /* Transmit data and update tx size/buff. */
75         if (handle->bytePerFrame == 1U)
76         {
77             tmpData = *(handle->txData);
78             handle->txData++;
79         }
80         else
81         {
82             if (handle->direction == kFLEXIO_SPI_MsbFirst)
83             {
84                 tmpData = (uint16_t)(handle->txData[0]) << 8U;
85                 tmpData += handle->txData[1];
86             }
87             else
88             {
89                 tmpData = (uint16_t)(handle->txData[1]) << 8U;
90                 tmpData += handle->txData[0];
91             }
92             handle->txData += 2U;
93         }
94     }
95     else
96     {
97         tmpData = FLEXIO_SPI_DUMMYDATA;
98     }
99 
100     handle->txRemainingBytes -= handle->bytePerFrame;
101 
102     FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
103 
104     if (0U == handle->txRemainingBytes)
105     {
106         FLEXIO_SPI_DisableInterrupts(base, (uint32_t)kFLEXIO_SPI_TxEmptyInterruptEnable);
107     }
108 }
109 
FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)110 static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
111 {
112     uint16_t tmpData;
113 
114     tmpData = FLEXIO_SPI_ReadData(base, handle->direction);
115 
116     if (handle->rxData != NULL)
117     {
118         if (handle->bytePerFrame == 1U)
119         {
120             *handle->rxData = (uint8_t)tmpData;
121             handle->rxData++;
122         }
123         else
124         {
125             if (handle->direction == kFLEXIO_SPI_MsbFirst)
126             {
127                 *handle->rxData = (uint8_t)(tmpData >> 8);
128                 handle->rxData++;
129                 *handle->rxData = (uint8_t)tmpData;
130             }
131             else
132             {
133                 *handle->rxData = (uint8_t)tmpData;
134                 handle->rxData++;
135                 *handle->rxData = (uint8_t)(tmpData >> 8);
136             }
137             handle->rxData++;
138         }
139     }
140     handle->rxRemainingBytes -= handle->bytePerFrame;
141 }
142 
143 /*!
144  * brief Ungates the FlexIO clock, resets the FlexIO module, configures the FlexIO SPI master hardware,
145  * and configures the FlexIO SPI with FlexIO SPI master configuration. The
146  * configuration structure can be filled by the user, or be set with default values
147  * by the FLEXIO_SPI_MasterGetDefaultConfig().
148  *
149  * note 1.FlexIO SPI master only support CPOL = 0, which means clock inactive low.
150  *      2.For FlexIO SPI master, the input valid time is 1.5 clock cycles, for slave the output valid time
151  *        is 2.5 clock cycles. So if FlexIO SPI master communicates with other spi IPs, the maximum baud
152  *        rate is FlexIO clock frequency divided by 2*2=4. If FlexIO SPI master communicates with FlexIO
153  *        SPI slave, the maximum baud rate is FlexIO clock frequency divided by (1.5+2.5)*2=8.
154  *
155  * Example
156    code
157    FLEXIO_SPI_Type spiDev = {
158    .flexioBase = FLEXIO,
159    .SDOPinIndex = 0,
160    .SDIPinIndex = 1,
161    .SCKPinIndex = 2,
162    .CSnPinIndex = 3,
163    .shifterIndex = {0,1},
164    .timerIndex = {0,1}
165    };
166    flexio_spi_master_config_t config = {
167    .enableMaster = true,
168    .enableInDoze = false,
169    .enableInDebug = true,
170    .enableFastAccess = false,
171    .baudRate_Bps = 500000,
172    .phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
173    .direction = kFLEXIO_SPI_MsbFirst,
174    .dataMode = kFLEXIO_SPI_8BitMode
175    };
176    FLEXIO_SPI_MasterInit(&spiDev, &config, srcClock_Hz);
177    endcode
178  *
179  * param base Pointer to the FLEXIO_SPI_Type structure.
180  * param masterConfig Pointer to the flexio_spi_master_config_t structure.
181  * param srcClock_Hz FlexIO source clock in Hz.
182 */
FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type * base,flexio_spi_master_config_t * masterConfig,uint32_t srcClock_Hz)183 void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz)
184 {
185     assert(base != NULL);
186     assert(masterConfig != NULL);
187 
188     flexio_shifter_config_t shifterConfig;
189     flexio_timer_config_t timerConfig;
190     uint32_t ctrlReg  = 0;
191     uint16_t timerDiv = 0;
192     uint16_t timerCmp = 0;
193 
194     /* Clear the shifterConfig & timerConfig struct. */
195     (void)memset(&shifterConfig, 0, sizeof(shifterConfig));
196     (void)memset(&timerConfig, 0, sizeof(timerConfig));
197 
198 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
199     /* Ungate flexio clock. */
200     CLOCK_EnableClock(s_flexioClocks[FLEXIO_SPI_GetInstance(base)]);
201 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
202 
203     /* Configure FLEXIO SPI Master */
204     ctrlReg = base->flexioBase->CTRL;
205     ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
206     ctrlReg |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
207                 FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
208     if (!masterConfig->enableInDoze)
209     {
210         ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
211     }
212 
213     base->flexioBase->CTRL = ctrlReg;
214 
215     /* Do hardware configuration. */
216     /* 1. Configure the shifter 0 for tx. */
217     shifterConfig.timerSelect = base->timerIndex[0];
218     shifterConfig.pinConfig   = kFLEXIO_PinConfigOutput;
219     shifterConfig.pinSelect   = base->SDOPinIndex;
220     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
221     shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
222     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
223     if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
224     {
225         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
226         shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitDisable;
227         shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
228     }
229     else
230     {
231         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
232         shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitLow;
233         shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
234     }
235 
236     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
237 
238     /* 2. Configure the shifter 1 for rx. */
239     shifterConfig.timerSelect  = base->timerIndex[0];
240     shifterConfig.pinConfig    = kFLEXIO_PinConfigOutputDisabled;
241     shifterConfig.pinSelect    = base->SDIPinIndex;
242     shifterConfig.pinPolarity  = kFLEXIO_PinActiveHigh;
243     shifterConfig.shifterMode  = kFLEXIO_ShifterModeReceive;
244     shifterConfig.inputSource  = kFLEXIO_ShifterInputFromPin;
245     shifterConfig.shifterStop  = kFLEXIO_ShifterStopBitDisable;
246     shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
247     if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
248     {
249         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
250     }
251     else
252     {
253         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
254     }
255 
256     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
257 
258     /*3. Configure the timer 0 for SCK. */
259     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
260     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
261     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
262     timerConfig.pinConfig       = kFLEXIO_PinConfigOutput;
263     timerConfig.pinSelect       = base->SCKPinIndex;
264     timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
265     timerConfig.timerMode       = kFLEXIO_TimerModeDual8BitBaudBit;
266     timerConfig.timerOutput     = kFLEXIO_TimerOutputZeroNotAffectedByReset;
267     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
268     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
269     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompare;
270     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerHigh;
271     timerConfig.timerStop       = kFLEXIO_TimerStopBitEnableOnTimerDisable;
272     timerConfig.timerStart      = kFLEXIO_TimerStartBitEnabled;
273 
274     timerDiv = (uint16_t)(srcClock_Hz / masterConfig->baudRate_Bps);
275     timerDiv = timerDiv / 2U - 1U;
276 
277     timerCmp = ((uint16_t)masterConfig->dataMode * 2U - 1U) << 8U;
278     timerCmp |= timerDiv;
279 
280     timerConfig.timerCompare = timerCmp;
281 
282     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
283 
284     /* 4. Configure the timer 1 for CSn. */
285     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->timerIndex[0]);
286     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
287     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
288     timerConfig.pinConfig       = kFLEXIO_PinConfigOutput;
289     timerConfig.pinSelect       = base->CSnPinIndex;
290     timerConfig.pinPolarity     = kFLEXIO_PinActiveLow;
291     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
292     timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
293     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
294     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
295     timerConfig.timerDisable    = kFLEXIO_TimerDisableOnPreTimerDisable;
296     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnPrevTimerEnable;
297     timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
298     timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
299 
300     timerConfig.timerCompare = 0xFFFFU;
301 
302     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
303 }
304 
305 /*!
306  * brief Resets the FlexIO SPI timer and shifter config.
307  *
308  * param base Pointer to the FLEXIO_SPI_Type.
309  */
FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type * base)310 void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base)
311 {
312     base->flexioBase->SHIFTCFG[base->shifterIndex[0]] = 0;
313     base->flexioBase->SHIFTCTL[base->shifterIndex[0]] = 0;
314     base->flexioBase->SHIFTCFG[base->shifterIndex[1]] = 0;
315     base->flexioBase->SHIFTCTL[base->shifterIndex[1]] = 0;
316     base->flexioBase->TIMCFG[base->timerIndex[0]]     = 0;
317     base->flexioBase->TIMCMP[base->timerIndex[0]]     = 0;
318     base->flexioBase->TIMCTL[base->timerIndex[0]]     = 0;
319     base->flexioBase->TIMCFG[base->timerIndex[1]]     = 0;
320     base->flexioBase->TIMCMP[base->timerIndex[1]]     = 0;
321     base->flexioBase->TIMCTL[base->timerIndex[1]]     = 0;
322 }
323 
324 /*!
325  * brief Gets the default configuration to configure the FlexIO SPI master. The configuration
326  * can be used directly by calling the FLEXIO_SPI_MasterConfigure().
327  * Example:
328    code
329    flexio_spi_master_config_t masterConfig;
330    FLEXIO_SPI_MasterGetDefaultConfig(&masterConfig);
331    endcode
332  * param masterConfig Pointer to the flexio_spi_master_config_t structure.
333 */
FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t * masterConfig)334 void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig)
335 {
336     assert(masterConfig != NULL);
337 
338     /* Initializes the configure structure to zero. */
339     (void)memset(masterConfig, 0, sizeof(*masterConfig));
340 
341     masterConfig->enableMaster     = true;
342     masterConfig->enableInDoze     = false;
343     masterConfig->enableInDebug    = true;
344     masterConfig->enableFastAccess = false;
345     /* Default baud rate 500kbps. */
346     masterConfig->baudRate_Bps = 500000U;
347     /* Default CPHA = 0. */
348     masterConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
349     /* Default bit count at 8. */
350     masterConfig->dataMode = kFLEXIO_SPI_8BitMode;
351 }
352 
353 /*!
354  * brief Ungates the FlexIO clock, resets the FlexIO module, configures the FlexIO SPI slave hardware
355  * configuration, and configures the FlexIO SPI with FlexIO SPI slave configuration. The
356  * configuration structure can be filled by the user, or be set with default values
357  * by the FLEXIO_SPI_SlaveGetDefaultConfig().
358  *
359  * note 1.Only one timer is needed in the FlexIO SPI slave. As a result, the second timer index is ignored.
360  *      2.FlexIO SPI slave only support CPOL = 0, which means clock inactive low.
361  *      3.For FlexIO SPI master, the input valid time is 1.5 clock cycles, for slave the output valid time
362  *        is 2.5 clock cycles. So if FlexIO SPI slave communicates with other spi IPs, the maximum baud
363  *        rate is FlexIO clock frequency divided by 3*2=6. If FlexIO SPI slave communicates with FlexIO
364  *        SPI master, the maximum baud rate is FlexIO clock frequency divided by (1.5+2.5)*2=8.
365  * Example
366    code
367    FLEXIO_SPI_Type spiDev = {
368    .flexioBase = FLEXIO,
369    .SDOPinIndex = 0,
370    .SDIPinIndex = 1,
371    .SCKPinIndex = 2,
372    .CSnPinIndex = 3,
373    .shifterIndex = {0,1},
374    .timerIndex = {0}
375    };
376    flexio_spi_slave_config_t config = {
377    .enableSlave = true,
378    .enableInDoze = false,
379    .enableInDebug = true,
380    .enableFastAccess = false,
381    .phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
382    .direction = kFLEXIO_SPI_MsbFirst,
383    .dataMode = kFLEXIO_SPI_8BitMode
384    };
385    FLEXIO_SPI_SlaveInit(&spiDev, &config);
386    endcode
387  * param base Pointer to the FLEXIO_SPI_Type structure.
388  * param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
389 */
FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type * base,flexio_spi_slave_config_t * slaveConfig)390 void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig)
391 {
392     assert((base != NULL) && (slaveConfig != NULL));
393 
394     flexio_shifter_config_t shifterConfig;
395     flexio_timer_config_t timerConfig;
396     uint32_t ctrlReg = 0;
397 
398     /* Clear the shifterConfig & timerConfig struct. */
399     (void)memset(&shifterConfig, 0, sizeof(shifterConfig));
400     (void)memset(&timerConfig, 0, sizeof(timerConfig));
401 
402 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
403     /* Ungate flexio clock. */
404     CLOCK_EnableClock(s_flexioClocks[FLEXIO_SPI_GetInstance(base)]);
405 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
406 
407     /* Configure FLEXIO SPI Slave */
408     ctrlReg = base->flexioBase->CTRL;
409     ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
410     ctrlReg |= (FLEXIO_CTRL_DBGE(slaveConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(slaveConfig->enableFastAccess) |
411                 FLEXIO_CTRL_FLEXEN(slaveConfig->enableSlave));
412     if (!slaveConfig->enableInDoze)
413     {
414         ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
415     }
416 
417     base->flexioBase->CTRL = ctrlReg;
418 
419     /* Do hardware configuration. */
420     /* 1. Configure the shifter 0 for tx. */
421     shifterConfig.timerSelect = base->timerIndex[0];
422     shifterConfig.pinConfig   = kFLEXIO_PinConfigOutput;
423     shifterConfig.pinSelect   = base->SDOPinIndex;
424     shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
425     shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
426     shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
427     shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
428     if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
429     {
430         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
431         shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
432     }
433     else
434     {
435         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
436         shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
437     }
438 
439     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
440 
441     /* 2. Configure the shifter 1 for rx. */
442     shifterConfig.timerSelect  = base->timerIndex[0];
443     shifterConfig.pinConfig    = kFLEXIO_PinConfigOutputDisabled;
444     shifterConfig.pinSelect    = base->SDIPinIndex;
445     shifterConfig.pinPolarity  = kFLEXIO_PinActiveHigh;
446     shifterConfig.shifterMode  = kFLEXIO_ShifterModeReceive;
447     shifterConfig.inputSource  = kFLEXIO_ShifterInputFromPin;
448     shifterConfig.shifterStop  = kFLEXIO_ShifterStopBitDisable;
449     shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
450     if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
451     {
452         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
453     }
454     else
455     {
456         shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
457     }
458 
459     FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
460 
461     /*3. Configure the timer 0 for shift clock. */
462     timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->CSnPinIndex);
463     timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
464     timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
465     timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
466     timerConfig.pinSelect       = base->SCKPinIndex;
467     timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
468     timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
469     timerConfig.timerOutput     = kFLEXIO_TimerOutputZeroNotAffectedByReset;
470     timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
471     timerConfig.timerReset      = kFLEXIO_TimerResetNever;
472     timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerRisingEdge;
473     timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
474     if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
475     {
476         /* The configuration kFLEXIO_TimerDisableOnTimerCompare only support continuous
477         PCS access, change to kFLEXIO_TimerDisableNever to enable discontinuous PCS access. */
478         timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
479         timerConfig.timerStart   = kFLEXIO_TimerStartBitDisabled;
480     }
481     else
482     {
483         timerConfig.timerDisable = kFLEXIO_TimerDisableOnTriggerFallingEdge;
484         timerConfig.timerStart   = kFLEXIO_TimerStartBitEnabled;
485     }
486 
487     timerConfig.timerCompare = (uint32_t)slaveConfig->dataMode * 2U - 1U;
488 
489     FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
490 }
491 
492 /*!
493  * brief Gates the FlexIO clock.
494  *
495  * param base Pointer to the FLEXIO_SPI_Type.
496  */
FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type * base)497 void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base)
498 {
499     FLEXIO_SPI_MasterDeinit(base);
500 }
501 
502 /*!
503  * brief Gets the default configuration to configure the FlexIO SPI slave. The configuration
504  * can be used directly for calling the FLEXIO_SPI_SlaveConfigure().
505  * Example:
506    code
507    flexio_spi_slave_config_t slaveConfig;
508    FLEXIO_SPI_SlaveGetDefaultConfig(&slaveConfig);
509    endcode
510  * param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
511 */
FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t * slaveConfig)512 void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig)
513 {
514     assert(slaveConfig != NULL);
515 
516     /* Initializes the configure structure to zero. */
517     (void)memset(slaveConfig, 0, sizeof(*slaveConfig));
518 
519     slaveConfig->enableSlave      = true;
520     slaveConfig->enableInDoze     = false;
521     slaveConfig->enableInDebug    = true;
522     slaveConfig->enableFastAccess = false;
523     /* Default CPHA = 0. */
524     slaveConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
525     /* Default bit count at 8. */
526     slaveConfig->dataMode = kFLEXIO_SPI_8BitMode;
527 }
528 
529 /*!
530  * brief Enables the FlexIO SPI interrupt.
531  *
532  * This function enables the FlexIO SPI interrupt.
533  *
534  * param base Pointer to the FLEXIO_SPI_Type structure.
535  * param mask interrupt source. The parameter can be any combination of the following values:
536  *        arg kFLEXIO_SPI_RxFullInterruptEnable
537  *        arg kFLEXIO_SPI_TxEmptyInterruptEnable
538  */
FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type * base,uint32_t mask)539 void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
540 {
541     if ((mask & (uint32_t)kFLEXIO_SPI_TxEmptyInterruptEnable) != 0U)
542     {
543         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
544     }
545     if ((mask & (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable) != 0U)
546     {
547         FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
548     }
549 }
550 
551 /*!
552  * brief Disables the FlexIO SPI interrupt.
553  *
554  * This function disables the FlexIO SPI interrupt.
555  *
556  * param base Pointer to the FLEXIO_SPI_Type structure.
557  * param mask interrupt source The parameter can be any combination of the following values:
558  *        arg kFLEXIO_SPI_RxFullInterruptEnable
559  *        arg kFLEXIO_SPI_TxEmptyInterruptEnable
560  */
FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type * base,uint32_t mask)561 void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
562 {
563     if ((mask & (uint32_t)kFLEXIO_SPI_TxEmptyInterruptEnable) != 0U)
564     {
565         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[0]);
566     }
567     if ((mask & (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable) != 0U)
568     {
569         FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1UL << base->shifterIndex[1]);
570     }
571 }
572 
573 /*!
574  * brief Enables/disables the FlexIO SPI transmit DMA. This function enables/disables the FlexIO SPI Tx DMA,
575  * which means that asserting the kFLEXIO_SPI_TxEmptyFlag does/doesn't trigger the DMA request.
576  *
577  * param base Pointer to the FLEXIO_SPI_Type structure.
578  * param mask SPI DMA source.
579  * param enable True means enable DMA, false means disable DMA.
580  */
FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type * base,uint32_t mask,bool enable)581 void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable)
582 {
583     if ((mask & (uint32_t)kFLEXIO_SPI_TxDmaEnable) != 0U)
584     {
585         FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1UL << base->shifterIndex[0], enable);
586     }
587 
588     if ((mask & (uint32_t)kFLEXIO_SPI_RxDmaEnable) != 0U)
589     {
590         FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1UL << base->shifterIndex[1], enable);
591     }
592 }
593 
594 /*!
595  * brief Gets FlexIO SPI status flags.
596  *
597  * param base Pointer to the FLEXIO_SPI_Type structure.
598  * return status flag; Use the status flag to AND the following flag mask and get the status.
599  *          arg kFLEXIO_SPI_TxEmptyFlag
600  *          arg kFLEXIO_SPI_RxEmptyFlag
601  */
602 
FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type * base)603 uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base)
604 {
605     uint32_t shifterStatus = FLEXIO_GetShifterStatusFlags(base->flexioBase);
606     uint32_t status        = 0;
607 
608     status = ((shifterStatus & (1UL << base->shifterIndex[0])) >> base->shifterIndex[0]);
609     status |= (((shifterStatus & (1UL << base->shifterIndex[1])) >> (base->shifterIndex[1])) << 1U);
610 
611     return status;
612 }
613 
614 /*!
615  * brief Clears FlexIO SPI status flags.
616  *
617  * param base Pointer to the FLEXIO_SPI_Type structure.
618  * param mask status flag
619  *      The parameter can be any combination of the following values:
620  *          arg kFLEXIO_SPI_TxEmptyFlag
621  *          arg kFLEXIO_SPI_RxEmptyFlag
622  */
623 
FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type * base,uint32_t mask)624 void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask)
625 {
626     if ((mask & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag) != 0U)
627     {
628         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[0]);
629     }
630     if ((mask & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag) != 0U)
631     {
632         FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1UL << base->shifterIndex[1]);
633     }
634 }
635 
636 /*!
637  * brief Sets baud rate for the FlexIO SPI transfer, which is only used for the master.
638  *
639  * param base Pointer to the FLEXIO_SPI_Type structure.
640  * param baudRate_Bps Baud Rate needed in Hz.
641  * param srcClockHz SPI source clock frequency in Hz.
642  */
FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClockHz)643 void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz)
644 {
645     uint16_t timerDiv       = 0;
646     uint16_t timerCmp       = 0;
647     FLEXIO_Type *flexioBase = base->flexioBase;
648 
649     /* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/
650     timerDiv = (uint16_t)(srcClockHz / baudRate_Bps);
651     timerDiv = timerDiv / 2U - 1U;
652 
653     timerCmp = (uint16_t)(flexioBase->TIMCMP[base->timerIndex[0]]);
654     timerCmp &= 0xFF00U;
655     timerCmp |= timerDiv;
656 
657     flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
658 }
659 
660 /*!
661  * brief Sends a buffer of data bytes.
662  *
663  * note This function blocks using the polling method until all bytes have been sent.
664  *
665  * param base Pointer to the FLEXIO_SPI_Type structure.
666  * param direction Shift direction of MSB first or LSB first.
667  * param buffer The data bytes to send.
668  * param size The number of data bytes to send.
669  * retval kStatus_Success Successfully create the handle.
670  * retval kStatus_FLEXIO_SPI_Timeout The transfer timed out and was aborted.
671  */
FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type * base,flexio_spi_shift_direction_t direction,const uint8_t * buffer,size_t size)672 status_t FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
673                                   flexio_spi_shift_direction_t direction,
674                                   const uint8_t *buffer,
675                                   size_t size)
676 {
677     assert(buffer != NULL);
678     assert(size != 0U);
679 
680 #if SPI_RETRY_TIMES
681     uint32_t waitTimes;
682 #endif
683 
684     while (0U != size--)
685     {
686         /* Wait until data transfer complete. */
687 #if SPI_RETRY_TIMES
688         waitTimes = SPI_RETRY_TIMES;
689         while ((0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag)) &&
690                (0U != --waitTimes))
691 #else
692         while (0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag))
693 #endif
694         {
695         }
696 #if SPI_RETRY_TIMES
697         if (waitTimes == 0U)
698         {
699             return kStatus_FLEXIO_SPI_Timeout;
700         }
701 #endif
702         FLEXIO_SPI_WriteData(base, direction, *buffer++);
703     }
704 
705     return kStatus_Success;
706 }
707 
708 /*!
709  * brief Receives a buffer of bytes.
710  *
711  * note This function blocks using the polling method until all bytes have been received.
712  *
713  * param base Pointer to the FLEXIO_SPI_Type structure.
714  * param direction Shift direction of MSB first or LSB first.
715  * param buffer The buffer to store the received bytes.
716  * param size The number of data bytes to be received.
717  * param direction Shift direction of MSB first or LSB first.
718  * retval kStatus_Success Successfully create the handle.
719  * retval kStatus_FLEXIO_SPI_Timeout The transfer timed out and was aborted.
720  */
FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type * base,flexio_spi_shift_direction_t direction,uint8_t * buffer,size_t size)721 status_t FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
722                                  flexio_spi_shift_direction_t direction,
723                                  uint8_t *buffer,
724                                  size_t size)
725 {
726     assert(buffer != NULL);
727     assert(size != 0U);
728 
729 #if SPI_RETRY_TIMES
730     uint32_t waitTimes;
731 #endif
732 
733     while (0U != size--)
734     {
735         /* Wait until data transfer complete. */
736 #if SPI_RETRY_TIMES
737         waitTimes = SPI_RETRY_TIMES;
738         while ((0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag)) &&
739                (0U != --waitTimes))
740 #else
741         while (0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag))
742 #endif
743         {
744         }
745 #if SPI_RETRY_TIMES
746         if (waitTimes == 0U)
747         {
748             return kStatus_FLEXIO_SPI_Timeout;
749         }
750 #endif
751         *buffer++ = (uint8_t)FLEXIO_SPI_ReadData(base, direction);
752     }
753 
754     return kStatus_Success;
755 }
756 
757 /*!
758  * brief Receives a buffer of bytes.
759  *
760  * note This function blocks via polling until all bytes have been received.
761  *
762  * param base pointer to FLEXIO_SPI_Type structure
763  * param xfer FlexIO SPI transfer structure, see #flexio_spi_transfer_t.
764  * retval kStatus_Success Successfully create the handle.
765  * retval kStatus_FLEXIO_SPI_Timeout The transfer timed out and was aborted.
766  */
FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type * base,flexio_spi_transfer_t * xfer)767 status_t FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer)
768 {
769     flexio_spi_shift_direction_t direction;
770     uint8_t bytesPerFrame;
771     uint32_t dataMode = 0;
772     uint16_t timerCmp = (uint16_t)(base->flexioBase->TIMCMP[base->timerIndex[0]]);
773     uint16_t tmpData  = FLEXIO_SPI_DUMMYDATA;
774 #if SPI_RETRY_TIMES
775     uint32_t waitTimes;
776 #endif
777 
778     timerCmp &= 0x00FFU;
779     /* Configure the values in handle. */
780     switch (xfer->flags)
781     {
782         case (uint8_t)kFLEXIO_SPI_8bitMsb:
783             dataMode      = (8UL * 2UL - 1UL) << 8U;
784             bytesPerFrame = 1U;
785             direction     = kFLEXIO_SPI_MsbFirst;
786             break;
787 
788         case (uint8_t)kFLEXIO_SPI_8bitLsb:
789             dataMode      = (8UL * 2UL - 1UL) << 8U;
790             bytesPerFrame = 1U;
791             direction     = kFLEXIO_SPI_LsbFirst;
792             break;
793 
794         case (uint8_t)kFLEXIO_SPI_16bitMsb:
795             dataMode      = (16UL * 2UL - 1UL) << 8U;
796             bytesPerFrame = 2U;
797             direction     = kFLEXIO_SPI_MsbFirst;
798             break;
799 
800         case (uint8_t)kFLEXIO_SPI_16bitLsb:
801             dataMode      = (16UL * 2UL - 1UL) << 8U;
802             bytesPerFrame = 2U;
803             direction     = kFLEXIO_SPI_LsbFirst;
804             break;
805 
806         default:
807             dataMode      = (8UL * 2UL - 1UL) << 8U;
808             bytesPerFrame = 1U;
809             direction     = kFLEXIO_SPI_MsbFirst;
810             assert(true);
811             break;
812     }
813 
814     dataMode |= timerCmp;
815 
816     /* Configure transfer size. */
817     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
818 
819     while (xfer->dataSize != 0U)
820     {
821         /* Wait until data transfer complete. */
822 #if SPI_RETRY_TIMES
823         waitTimes = SPI_RETRY_TIMES;
824         while ((0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag)) &&
825                (0U != --waitTimes))
826 #else
827         while (0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag))
828 #endif
829         {
830         }
831 #if SPI_RETRY_TIMES
832         if (waitTimes == 0U)
833         {
834             return kStatus_FLEXIO_SPI_Timeout;
835         }
836 #endif
837         if (xfer->txData != NULL)
838         {
839             /* Transmit data and update tx size/buff. */
840             if (bytesPerFrame == 1U)
841             {
842                 tmpData = *(xfer->txData);
843                 xfer->txData++;
844             }
845             else
846             {
847                 if (direction == kFLEXIO_SPI_MsbFirst)
848                 {
849                     tmpData = (uint16_t)(xfer->txData[0]) << 8U;
850                     tmpData += xfer->txData[1];
851                 }
852                 else
853                 {
854                     tmpData = (uint16_t)(xfer->txData[1]) << 8U;
855                     tmpData += xfer->txData[0];
856                 }
857                 xfer->txData += 2U;
858             }
859         }
860         else
861         {
862             tmpData = FLEXIO_SPI_DUMMYDATA;
863         }
864 
865         xfer->dataSize -= bytesPerFrame;
866 
867         FLEXIO_SPI_WriteData(base, direction, tmpData);
868 
869 #if SPI_RETRY_TIMES
870         waitTimes = SPI_RETRY_TIMES;
871         while ((0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag)) &&
872                (0U != --waitTimes))
873 #else
874         while (0U == (FLEXIO_SPI_GetStatusFlags(base) & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag))
875 #endif
876         {
877         }
878 #if SPI_RETRY_TIMES
879         if (waitTimes == 0U)
880         {
881             return kStatus_FLEXIO_SPI_Timeout;
882         }
883 #endif
884         tmpData = FLEXIO_SPI_ReadData(base, direction);
885 
886         if (xfer->rxData != NULL)
887         {
888             if (bytesPerFrame == 1U)
889             {
890                 *xfer->rxData = (uint8_t)tmpData;
891                 xfer->rxData++;
892             }
893             else
894             {
895                 if (direction == kFLEXIO_SPI_MsbFirst)
896                 {
897                     *xfer->rxData = (uint8_t)(tmpData >> 8);
898                     xfer->rxData++;
899                     *xfer->rxData = (uint8_t)tmpData;
900                 }
901                 else
902                 {
903                     *xfer->rxData = (uint8_t)tmpData;
904                     xfer->rxData++;
905                     *xfer->rxData = (uint8_t)(tmpData >> 8);
906                 }
907                 xfer->rxData++;
908             }
909         }
910     }
911 
912     return kStatus_Success;
913 }
914 
915 /*!
916  * brief Initializes the FlexIO SPI Master handle, which is used in transactional functions.
917  *
918  * param base Pointer to the FLEXIO_SPI_Type structure.
919  * param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
920  * param callback The callback function.
921  * param userData The parameter of the callback function.
922  * retval kStatus_Success Successfully create the handle.
923  * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
924  */
FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,flexio_spi_master_transfer_callback_t callback,void * userData)925 status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
926                                                flexio_spi_master_handle_t *handle,
927                                                flexio_spi_master_transfer_callback_t callback,
928                                                void *userData)
929 {
930     assert(handle != NULL);
931 
932     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
933 
934     /* Zero the handle. */
935     (void)memset(handle, 0, sizeof(*handle));
936 
937     /* Register callback and userData. */
938     handle->callback = callback;
939     handle->userData = userData;
940 
941     /* Clear pending NVIC IRQ before enable NVIC IRQ. */
942     NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
943     /* Enable interrupt in NVIC. */
944     (void)EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
945 
946     /* Save the context in global variables to support the double weak mechanism. */
947     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_MasterTransferHandleIRQ);
948 }
949 
950 /*!
951  * brief Master transfer data using IRQ.
952  *
953  * This function sends data using IRQ. This is a non-blocking function, which returns
954  * right away. When all data is sent out/received, the callback function is called.
955  *
956  * param base Pointer to the FLEXIO_SPI_Type structure.
957  * param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
958  * param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
959  * retval kStatus_Success Successfully start a transfer.
960  * retval kStatus_InvalidArgument Input argument is invalid.
961  * retval kStatus_FLEXIO_SPI_Busy SPI is not idle, is running another transfer.
962  */
FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,flexio_spi_transfer_t * xfer)963 status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
964                                               flexio_spi_master_handle_t *handle,
965                                               flexio_spi_transfer_t *xfer)
966 {
967     assert(handle != NULL);
968     assert(xfer != NULL);
969 
970     uint32_t dataMode = 0;
971     uint16_t timerCmp = (uint16_t)base->flexioBase->TIMCMP[base->timerIndex[0]];
972     uint16_t tmpData  = FLEXIO_SPI_DUMMYDATA;
973 
974     timerCmp &= 0x00FFU;
975 
976     /* Check if SPI is busy. */
977     if (handle->state == (uint32_t)kFLEXIO_SPI_Busy)
978     {
979         return kStatus_FLEXIO_SPI_Busy;
980     }
981 
982     /* Check if the argument is legal. */
983     if ((xfer->txData == NULL) && (xfer->rxData == NULL))
984     {
985         return kStatus_InvalidArgument;
986     }
987 
988     /* Configure the values in handle */
989     switch (xfer->flags)
990     {
991         case (uint8_t)kFLEXIO_SPI_8bitMsb:
992             dataMode             = (8UL * 2UL - 1UL) << 8U;
993             handle->bytePerFrame = 1U;
994             handle->direction    = kFLEXIO_SPI_MsbFirst;
995             break;
996         case (uint8_t)kFLEXIO_SPI_8bitLsb:
997             dataMode             = (8UL * 2UL - 1UL) << 8U;
998             handle->bytePerFrame = 1U;
999             handle->direction    = kFLEXIO_SPI_LsbFirst;
1000             break;
1001         case (uint8_t)kFLEXIO_SPI_16bitMsb:
1002             dataMode             = (16UL * 2UL - 1UL) << 8U;
1003             handle->bytePerFrame = 2U;
1004             handle->direction    = kFLEXIO_SPI_MsbFirst;
1005             break;
1006         case (uint8_t)kFLEXIO_SPI_16bitLsb:
1007             dataMode             = (16UL * 2UL - 1UL) << 8U;
1008             handle->bytePerFrame = 2U;
1009             handle->direction    = kFLEXIO_SPI_LsbFirst;
1010             break;
1011         default:
1012             dataMode             = (8UL * 2UL - 1UL) << 8U;
1013             handle->bytePerFrame = 1U;
1014             handle->direction    = kFLEXIO_SPI_MsbFirst;
1015             assert(true);
1016             break;
1017     }
1018 
1019     dataMode |= timerCmp;
1020 
1021     /* Configure transfer size. */
1022     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
1023 
1024     handle->state            = (uint32_t)kFLEXIO_SPI_Busy;
1025     handle->txData           = xfer->txData;
1026     handle->rxData           = xfer->rxData;
1027     handle->rxRemainingBytes = xfer->dataSize;
1028 
1029     /* Save total transfer size. */
1030     handle->transferSize = xfer->dataSize;
1031 
1032     /* Send first byte of data to trigger the rx interrupt. */
1033     if (handle->txData != NULL)
1034     {
1035         /* Transmit data and update tx size/buff. */
1036         if (handle->bytePerFrame == 1U)
1037         {
1038             tmpData = *(handle->txData);
1039             handle->txData++;
1040         }
1041         else
1042         {
1043             if (handle->direction == kFLEXIO_SPI_MsbFirst)
1044             {
1045                 tmpData = (uint16_t)(handle->txData[0]) << 8U;
1046                 tmpData += handle->txData[1];
1047             }
1048             else
1049             {
1050                 tmpData = (uint16_t)(handle->txData[1]) << 8U;
1051                 tmpData += handle->txData[0];
1052             }
1053             handle->txData += 2U;
1054         }
1055     }
1056     else
1057     {
1058         tmpData = FLEXIO_SPI_DUMMYDATA;
1059     }
1060 
1061     handle->txRemainingBytes = xfer->dataSize - handle->bytePerFrame;
1062 
1063     FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
1064 
1065     /* Enable transmit and receive interrupt to handle rx. */
1066     FLEXIO_SPI_EnableInterrupts(base, (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable);
1067 
1068     return kStatus_Success;
1069 }
1070 
1071 /*!
1072  * brief Gets the data transfer status which used IRQ.
1073  *
1074  * param base Pointer to the FLEXIO_SPI_Type structure.
1075  * param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
1076  * param count Number of bytes transferred so far by the non-blocking transaction.
1077  * retval kStatus_InvalidArgument count is Invalid.
1078  * retval kStatus_Success Successfully return the count.
1079  */
FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,size_t * count)1080 status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count)
1081 {
1082     assert(handle != NULL);
1083 
1084     if (NULL == count)
1085     {
1086         return kStatus_InvalidArgument;
1087     }
1088 
1089     /* Return remaing bytes in different cases. */
1090     if (handle->rxData != NULL)
1091     {
1092         *count = handle->transferSize - handle->rxRemainingBytes;
1093     }
1094     else
1095     {
1096         *count = handle->transferSize - handle->txRemainingBytes;
1097     }
1098 
1099     return kStatus_Success;
1100 }
1101 
1102 /*!
1103  * brief Aborts the master data transfer, which used IRQ.
1104  *
1105  * param base Pointer to the FLEXIO_SPI_Type structure.
1106  * param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
1107  */
FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)1108 void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
1109 {
1110     assert(handle != NULL);
1111 
1112     FLEXIO_SPI_DisableInterrupts(base, (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable);
1113     FLEXIO_SPI_DisableInterrupts(base, (uint32_t)kFLEXIO_SPI_TxEmptyInterruptEnable);
1114 
1115     /* Transfer finished, set the state to idle. */
1116     handle->state = (uint32_t)kFLEXIO_SPI_Idle;
1117 
1118     /* Clear the internal state. */
1119     handle->rxRemainingBytes = 0;
1120     handle->txRemainingBytes = 0;
1121 }
1122 
1123 /*!
1124  * brief FlexIO SPI master IRQ handler function.
1125  *
1126  * param spiType Pointer to the FLEXIO_SPI_Type structure.
1127  * param spiHandle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
1128  */
FLEXIO_SPI_MasterTransferHandleIRQ(void * spiType,void * spiHandle)1129 void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle)
1130 {
1131     assert(spiHandle != NULL);
1132 
1133     flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
1134     FLEXIO_SPI_Type *base;
1135     uint32_t status;
1136 
1137     if (handle->state == (uint32_t)kFLEXIO_SPI_Idle)
1138     {
1139         return;
1140     }
1141 
1142     base   = (FLEXIO_SPI_Type *)spiType;
1143     status = FLEXIO_SPI_GetStatusFlags(base);
1144 
1145     /* Handle rx. */
1146     if (((status & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag) != 0U) && (handle->rxRemainingBytes != 0U))
1147     {
1148         FLEXIO_SPI_TransferReceiveTransaction(base, handle);
1149     }
1150 
1151     /* Handle tx. */
1152     if (((status & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag) != 0U) && (handle->txRemainingBytes != 0U))
1153     {
1154         FLEXIO_SPI_TransferSendTransaction(base, handle);
1155     }
1156 
1157     /* All the transfer finished. */
1158     if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
1159     {
1160         FLEXIO_SPI_MasterTransferAbort(base, handle);
1161         if (handle->callback != NULL)
1162         {
1163             (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
1164         }
1165     }
1166 }
1167 
1168 /*!
1169  * brief Initializes the FlexIO SPI Slave handle, which is used in transactional functions.
1170  *
1171  * param base Pointer to the FLEXIO_SPI_Type structure.
1172  * param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
1173  * param callback The callback function.
1174  * param userData The parameter of the callback function.
1175  * retval kStatus_Success Successfully create the handle.
1176  * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
1177  */
FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_slave_transfer_callback_t callback,void * userData)1178 status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
1179                                               flexio_spi_slave_handle_t *handle,
1180                                               flexio_spi_slave_transfer_callback_t callback,
1181                                               void *userData)
1182 {
1183     assert(handle != NULL);
1184 
1185     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
1186 
1187     /* Zero the handle. */
1188     (void)memset(handle, 0, sizeof(*handle));
1189 
1190     /* Register callback and userData. */
1191     handle->callback = callback;
1192     handle->userData = userData;
1193 
1194     /* Clear pending NVIC IRQ before enable NVIC IRQ. */
1195     NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
1196     /* Enable interrupt in NVIC. */
1197     (void)EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
1198 
1199     /* Save the context in global variables to support the double weak mechanism. */
1200     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_SlaveTransferHandleIRQ);
1201 }
1202 
1203 /*!
1204  * brief Slave transfer data using IRQ.
1205  *
1206  * This function sends data using IRQ. This is a non-blocking function, which returns
1207  * right away. When all data is sent out/received, the callback function is called.
1208  * param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
1209  *
1210  * param base Pointer to the FLEXIO_SPI_Type structure.
1211  * param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
1212  * retval kStatus_Success Successfully start a transfer.
1213  * retval kStatus_InvalidArgument Input argument is invalid.
1214  * retval kStatus_FLEXIO_SPI_Busy SPI is not idle; it is running another transfer.
1215  */
FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_transfer_t * xfer)1216 status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
1217                                              flexio_spi_slave_handle_t *handle,
1218                                              flexio_spi_transfer_t *xfer)
1219 {
1220     assert(handle != NULL);
1221     assert(xfer != NULL);
1222 
1223     uint32_t dataMode = 0;
1224 
1225     /* Check if SPI is busy. */
1226     if (handle->state == (uint32_t)kFLEXIO_SPI_Busy)
1227     {
1228         return kStatus_FLEXIO_SPI_Busy;
1229     }
1230 
1231     /* Check if the argument is legal. */
1232     if ((xfer->txData == NULL) && (xfer->rxData == NULL))
1233     {
1234         return kStatus_InvalidArgument;
1235     }
1236 
1237     /* Configure the values in handle */
1238     switch (xfer->flags)
1239     {
1240         case (uint8_t)kFLEXIO_SPI_8bitMsb:
1241             dataMode             = 8U * 2U - 1U;
1242             handle->bytePerFrame = 1U;
1243             handle->direction    = kFLEXIO_SPI_MsbFirst;
1244             break;
1245         case (uint8_t)kFLEXIO_SPI_8bitLsb:
1246             dataMode             = 8U * 2U - 1U;
1247             handle->bytePerFrame = 1U;
1248             handle->direction    = kFLEXIO_SPI_LsbFirst;
1249             break;
1250         case (uint8_t)kFLEXIO_SPI_16bitMsb:
1251             dataMode             = 16U * 2U - 1U;
1252             handle->bytePerFrame = 2U;
1253             handle->direction    = kFLEXIO_SPI_MsbFirst;
1254             break;
1255         case (uint8_t)kFLEXIO_SPI_16bitLsb:
1256             dataMode             = 16U * 2U - 1U;
1257             handle->bytePerFrame = 2U;
1258             handle->direction    = kFLEXIO_SPI_LsbFirst;
1259             break;
1260         default:
1261             dataMode             = 8U * 2U - 1U;
1262             handle->bytePerFrame = 1U;
1263             handle->direction    = kFLEXIO_SPI_MsbFirst;
1264             assert(true);
1265             break;
1266     }
1267 
1268     /* Configure transfer size. */
1269     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
1270 
1271     handle->state            = (uint32_t)kFLEXIO_SPI_Busy;
1272     handle->txData           = xfer->txData;
1273     handle->rxData           = xfer->rxData;
1274     handle->txRemainingBytes = xfer->dataSize;
1275     handle->rxRemainingBytes = xfer->dataSize;
1276 
1277     /* Save total transfer size. */
1278     handle->transferSize = xfer->dataSize;
1279 
1280     /* Enable transmit and receive interrupt to handle tx and rx. */
1281     FLEXIO_SPI_EnableInterrupts(base, (uint32_t)kFLEXIO_SPI_TxEmptyInterruptEnable);
1282     FLEXIO_SPI_EnableInterrupts(base, (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable);
1283 
1284     return kStatus_Success;
1285 }
1286 
1287 /*!
1288  * brief FlexIO SPI slave IRQ handler function.
1289  *
1290  * param spiType Pointer to the FLEXIO_SPI_Type structure.
1291  * param spiHandle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
1292  */
FLEXIO_SPI_SlaveTransferHandleIRQ(void * spiType,void * spiHandle)1293 void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle)
1294 {
1295     assert(spiHandle != NULL);
1296 
1297     flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
1298     FLEXIO_SPI_Type *base;
1299     uint32_t status;
1300 
1301     if (handle->state == (uint32_t)kFLEXIO_SPI_Idle)
1302     {
1303         return;
1304     }
1305 
1306     base   = (FLEXIO_SPI_Type *)spiType;
1307     status = FLEXIO_SPI_GetStatusFlags(base);
1308 
1309     /* Handle tx. */
1310     if (((status & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag) != 0U) && (handle->txRemainingBytes != 0U))
1311     {
1312         FLEXIO_SPI_TransferSendTransaction(base, handle);
1313     }
1314 
1315     /* Handle rx. */
1316     if (((status & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag) != 0U) && (handle->rxRemainingBytes != 0U))
1317     {
1318         FLEXIO_SPI_TransferReceiveTransaction(base, handle);
1319     }
1320 
1321     /* All the transfer finished. */
1322     if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
1323     {
1324         FLEXIO_SPI_SlaveTransferAbort(base, handle);
1325         if (handle->callback != NULL)
1326         {
1327             (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
1328         }
1329     }
1330 }
1331