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