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