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     /* Enable interrupt in NVIC. */
942     (void)EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
943 
944     /* Save the context in global variables to support the double weak mechanism. */
945     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_MasterTransferHandleIRQ);
946 }
947 
948 /*!
949  * brief Master transfer data using IRQ.
950  *
951  * This function sends data using IRQ. This is a non-blocking function, which returns
952  * right away. When all data is sent out/received, the callback function is called.
953  *
954  * param base Pointer to the FLEXIO_SPI_Type structure.
955  * param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
956  * param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
957  * retval kStatus_Success Successfully start a transfer.
958  * retval kStatus_InvalidArgument Input argument is invalid.
959  * retval kStatus_FLEXIO_SPI_Busy SPI is not idle, is running another transfer.
960  */
FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,flexio_spi_transfer_t * xfer)961 status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
962                                               flexio_spi_master_handle_t *handle,
963                                               flexio_spi_transfer_t *xfer)
964 {
965     assert(handle != NULL);
966     assert(xfer != NULL);
967 
968     uint32_t dataMode = 0;
969     uint16_t timerCmp = (uint16_t)base->flexioBase->TIMCMP[base->timerIndex[0]];
970     uint16_t tmpData  = FLEXIO_SPI_DUMMYDATA;
971 
972     timerCmp &= 0x00FFU;
973 
974     /* Check if SPI is busy. */
975     if (handle->state == (uint32_t)kFLEXIO_SPI_Busy)
976     {
977         return kStatus_FLEXIO_SPI_Busy;
978     }
979 
980     /* Check if the argument is legal. */
981     if ((xfer->txData == NULL) && (xfer->rxData == NULL))
982     {
983         return kStatus_InvalidArgument;
984     }
985 
986     /* Configure the values in handle */
987     switch (xfer->flags)
988     {
989         case (uint8_t)kFLEXIO_SPI_8bitMsb:
990             dataMode             = (8UL * 2UL - 1UL) << 8U;
991             handle->bytePerFrame = 1U;
992             handle->direction    = kFLEXIO_SPI_MsbFirst;
993             break;
994         case (uint8_t)kFLEXIO_SPI_8bitLsb:
995             dataMode             = (8UL * 2UL - 1UL) << 8U;
996             handle->bytePerFrame = 1U;
997             handle->direction    = kFLEXIO_SPI_LsbFirst;
998             break;
999         case (uint8_t)kFLEXIO_SPI_16bitMsb:
1000             dataMode             = (16UL * 2UL - 1UL) << 8U;
1001             handle->bytePerFrame = 2U;
1002             handle->direction    = kFLEXIO_SPI_MsbFirst;
1003             break;
1004         case (uint8_t)kFLEXIO_SPI_16bitLsb:
1005             dataMode             = (16UL * 2UL - 1UL) << 8U;
1006             handle->bytePerFrame = 2U;
1007             handle->direction    = kFLEXIO_SPI_LsbFirst;
1008             break;
1009         default:
1010             dataMode             = (8UL * 2UL - 1UL) << 8U;
1011             handle->bytePerFrame = 1U;
1012             handle->direction    = kFLEXIO_SPI_MsbFirst;
1013             assert(true);
1014             break;
1015     }
1016 
1017     dataMode |= timerCmp;
1018 
1019     /* Configure transfer size. */
1020     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
1021 
1022     handle->state            = (uint32_t)kFLEXIO_SPI_Busy;
1023     handle->txData           = xfer->txData;
1024     handle->rxData           = xfer->rxData;
1025     handle->rxRemainingBytes = xfer->dataSize;
1026 
1027     /* Save total transfer size. */
1028     handle->transferSize = xfer->dataSize;
1029 
1030     /* Send first byte of data to trigger the rx interrupt. */
1031     if (handle->txData != NULL)
1032     {
1033         /* Transmit data and update tx size/buff. */
1034         if (handle->bytePerFrame == 1U)
1035         {
1036             tmpData = *(handle->txData);
1037             handle->txData++;
1038         }
1039         else
1040         {
1041             if (handle->direction == kFLEXIO_SPI_MsbFirst)
1042             {
1043                 tmpData = (uint16_t)(handle->txData[0]) << 8U;
1044                 tmpData += handle->txData[1];
1045             }
1046             else
1047             {
1048                 tmpData = (uint16_t)(handle->txData[1]) << 8U;
1049                 tmpData += handle->txData[0];
1050             }
1051             handle->txData += 2U;
1052         }
1053     }
1054     else
1055     {
1056         tmpData = FLEXIO_SPI_DUMMYDATA;
1057     }
1058 
1059     handle->txRemainingBytes = xfer->dataSize - handle->bytePerFrame;
1060 
1061     FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
1062 
1063     /* Enable transmit and receive interrupt to handle rx. */
1064     FLEXIO_SPI_EnableInterrupts(base, (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable);
1065 
1066     return kStatus_Success;
1067 }
1068 
1069 /*!
1070  * brief Gets the data transfer status which used IRQ.
1071  *
1072  * param base Pointer to the FLEXIO_SPI_Type structure.
1073  * param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
1074  * param count Number of bytes transferred so far by the non-blocking transaction.
1075  * retval kStatus_InvalidArgument count is Invalid.
1076  * retval kStatus_Success Successfully return the count.
1077  */
FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,size_t * count)1078 status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count)
1079 {
1080     assert(handle != NULL);
1081 
1082     if (NULL == count)
1083     {
1084         return kStatus_InvalidArgument;
1085     }
1086 
1087     /* Return remaing bytes in different cases. */
1088     if (handle->rxData != NULL)
1089     {
1090         *count = handle->transferSize - handle->rxRemainingBytes;
1091     }
1092     else
1093     {
1094         *count = handle->transferSize - handle->txRemainingBytes;
1095     }
1096 
1097     return kStatus_Success;
1098 }
1099 
1100 /*!
1101  * brief Aborts the master data transfer, which used IRQ.
1102  *
1103  * param base Pointer to the FLEXIO_SPI_Type structure.
1104  * param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
1105  */
FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)1106 void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
1107 {
1108     assert(handle != NULL);
1109 
1110     FLEXIO_SPI_DisableInterrupts(base, (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable);
1111     FLEXIO_SPI_DisableInterrupts(base, (uint32_t)kFLEXIO_SPI_TxEmptyInterruptEnable);
1112 
1113     /* Transfer finished, set the state to idle. */
1114     handle->state = (uint32_t)kFLEXIO_SPI_Idle;
1115 
1116     /* Clear the internal state. */
1117     handle->rxRemainingBytes = 0;
1118     handle->txRemainingBytes = 0;
1119 }
1120 
1121 /*!
1122  * brief FlexIO SPI master IRQ handler function.
1123  *
1124  * param spiType Pointer to the FLEXIO_SPI_Type structure.
1125  * param spiHandle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
1126  */
FLEXIO_SPI_MasterTransferHandleIRQ(void * spiType,void * spiHandle)1127 void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle)
1128 {
1129     assert(spiHandle != NULL);
1130 
1131     flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
1132     FLEXIO_SPI_Type *base;
1133     uint32_t status;
1134 
1135     if (handle->state == (uint32_t)kFLEXIO_SPI_Idle)
1136     {
1137         return;
1138     }
1139 
1140     base   = (FLEXIO_SPI_Type *)spiType;
1141     status = FLEXIO_SPI_GetStatusFlags(base);
1142 
1143     /* Handle rx. */
1144     if (((status & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag) != 0U) && (handle->rxRemainingBytes != 0U))
1145     {
1146         FLEXIO_SPI_TransferReceiveTransaction(base, handle);
1147     }
1148 
1149     /* Handle tx. */
1150     if (((status & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag) != 0U) && (handle->txRemainingBytes != 0U))
1151     {
1152         FLEXIO_SPI_TransferSendTransaction(base, handle);
1153     }
1154 
1155     /* All the transfer finished. */
1156     if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
1157     {
1158         FLEXIO_SPI_MasterTransferAbort(base, handle);
1159         if (handle->callback != NULL)
1160         {
1161             (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
1162         }
1163     }
1164 }
1165 
1166 /*!
1167  * brief Initializes the FlexIO SPI Slave handle, which is used in transactional functions.
1168  *
1169  * param base Pointer to the FLEXIO_SPI_Type structure.
1170  * param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
1171  * param callback The callback function.
1172  * param userData The parameter of the callback function.
1173  * retval kStatus_Success Successfully create the handle.
1174  * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
1175  */
FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_slave_transfer_callback_t callback,void * userData)1176 status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
1177                                               flexio_spi_slave_handle_t *handle,
1178                                               flexio_spi_slave_transfer_callback_t callback,
1179                                               void *userData)
1180 {
1181     assert(handle != NULL);
1182 
1183     IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
1184 
1185     /* Zero the handle. */
1186     (void)memset(handle, 0, sizeof(*handle));
1187 
1188     /* Register callback and userData. */
1189     handle->callback = callback;
1190     handle->userData = userData;
1191 
1192     /* Enable interrupt in NVIC. */
1193     (void)EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
1194 
1195     /* Save the context in global variables to support the double weak mechanism. */
1196     return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_SlaveTransferHandleIRQ);
1197 }
1198 
1199 /*!
1200  * brief Slave transfer data using IRQ.
1201  *
1202  * This function sends data using IRQ. This is a non-blocking function, which returns
1203  * right away. When all data is sent out/received, the callback function is called.
1204  * param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
1205  *
1206  * param base Pointer to the FLEXIO_SPI_Type structure.
1207  * param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
1208  * retval kStatus_Success Successfully start a transfer.
1209  * retval kStatus_InvalidArgument Input argument is invalid.
1210  * retval kStatus_FLEXIO_SPI_Busy SPI is not idle; it is running another transfer.
1211  */
FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_transfer_t * xfer)1212 status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
1213                                              flexio_spi_slave_handle_t *handle,
1214                                              flexio_spi_transfer_t *xfer)
1215 {
1216     assert(handle != NULL);
1217     assert(xfer != NULL);
1218 
1219     uint32_t dataMode = 0;
1220 
1221     /* Check if SPI is busy. */
1222     if (handle->state == (uint32_t)kFLEXIO_SPI_Busy)
1223     {
1224         return kStatus_FLEXIO_SPI_Busy;
1225     }
1226 
1227     /* Check if the argument is legal. */
1228     if ((xfer->txData == NULL) && (xfer->rxData == NULL))
1229     {
1230         return kStatus_InvalidArgument;
1231     }
1232 
1233     /* Configure the values in handle */
1234     switch (xfer->flags)
1235     {
1236         case (uint8_t)kFLEXIO_SPI_8bitMsb:
1237             dataMode             = 8U * 2U - 1U;
1238             handle->bytePerFrame = 1U;
1239             handle->direction    = kFLEXIO_SPI_MsbFirst;
1240             break;
1241         case (uint8_t)kFLEXIO_SPI_8bitLsb:
1242             dataMode             = 8U * 2U - 1U;
1243             handle->bytePerFrame = 1U;
1244             handle->direction    = kFLEXIO_SPI_LsbFirst;
1245             break;
1246         case (uint8_t)kFLEXIO_SPI_16bitMsb:
1247             dataMode             = 16U * 2U - 1U;
1248             handle->bytePerFrame = 2U;
1249             handle->direction    = kFLEXIO_SPI_MsbFirst;
1250             break;
1251         case (uint8_t)kFLEXIO_SPI_16bitLsb:
1252             dataMode             = 16U * 2U - 1U;
1253             handle->bytePerFrame = 2U;
1254             handle->direction    = kFLEXIO_SPI_LsbFirst;
1255             break;
1256         default:
1257             dataMode             = 8U * 2U - 1U;
1258             handle->bytePerFrame = 1U;
1259             handle->direction    = kFLEXIO_SPI_MsbFirst;
1260             assert(true);
1261             break;
1262     }
1263 
1264     /* Configure transfer size. */
1265     base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
1266 
1267     handle->state            = (uint32_t)kFLEXIO_SPI_Busy;
1268     handle->txData           = xfer->txData;
1269     handle->rxData           = xfer->rxData;
1270     handle->txRemainingBytes = xfer->dataSize;
1271     handle->rxRemainingBytes = xfer->dataSize;
1272 
1273     /* Save total transfer size. */
1274     handle->transferSize = xfer->dataSize;
1275 
1276     /* Enable transmit and receive interrupt to handle tx and rx. */
1277     FLEXIO_SPI_EnableInterrupts(base, (uint32_t)kFLEXIO_SPI_TxEmptyInterruptEnable);
1278     FLEXIO_SPI_EnableInterrupts(base, (uint32_t)kFLEXIO_SPI_RxFullInterruptEnable);
1279 
1280     return kStatus_Success;
1281 }
1282 
1283 /*!
1284  * brief FlexIO SPI slave IRQ handler function.
1285  *
1286  * param spiType Pointer to the FLEXIO_SPI_Type structure.
1287  * param spiHandle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
1288  */
FLEXIO_SPI_SlaveTransferHandleIRQ(void * spiType,void * spiHandle)1289 void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle)
1290 {
1291     assert(spiHandle != NULL);
1292 
1293     flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
1294     FLEXIO_SPI_Type *base;
1295     uint32_t status;
1296 
1297     if (handle->state == (uint32_t)kFLEXIO_SPI_Idle)
1298     {
1299         return;
1300     }
1301 
1302     base   = (FLEXIO_SPI_Type *)spiType;
1303     status = FLEXIO_SPI_GetStatusFlags(base);
1304 
1305     /* Handle tx. */
1306     if (((status & (uint32_t)kFLEXIO_SPI_TxBufferEmptyFlag) != 0U) && (handle->txRemainingBytes != 0U))
1307     {
1308         FLEXIO_SPI_TransferSendTransaction(base, handle);
1309     }
1310 
1311     /* Handle rx. */
1312     if (((status & (uint32_t)kFLEXIO_SPI_RxBufferFullFlag) != 0U) && (handle->rxRemainingBytes != 0U))
1313     {
1314         FLEXIO_SPI_TransferReceiveTransaction(base, handle);
1315     }
1316 
1317     /* All the transfer finished. */
1318     if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
1319     {
1320         FLEXIO_SPI_SlaveTransferAbort(base, handle);
1321         if (handle->callback != NULL)
1322         {
1323             (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
1324         }
1325     }
1326 }
1327