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