1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 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 /*! @brief FLEXIO SPI transfer state, which is used for SPI transactiaonl APIs' internal state. */
16 enum _flexio_spi_transfer_states
17 {
18 kFLEXIO_SPI_Idle = 0x0U, /*!< Nothing in the transmitter/receiver's queue. */
19 kFLEXIO_SPI_Busy, /*!< Transmiter/Receive's queue is not finished. */
20 };
21
22 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
23 extern const clock_ip_name_t s_flexioClocks[];
24 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
25
26 extern FLEXIO_Type *const s_flexioBases[];
27
28 /*******************************************************************************
29 * Prototypes
30 ******************************************************************************/
31
32 extern uint32_t FLEXIO_GetInstance(FLEXIO_Type *base);
33
34 /*!
35 * @brief Send a piece of data for SPI.
36 *
37 * This function computes the number of data to be written into D register or Tx FIFO,
38 * and write the data into it. At the same time, this function updates the values in
39 * master handle structure.
40 *
41 * @param base pointer to FLEXIO_SPI_Type structure
42 * @param handle Pointer to SPI master handle structure.
43 */
44 static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
45
46 /*!
47 * @brief Receive a piece of data for SPI master.
48 *
49 * This function computes the number of data to receive from D register or Rx FIFO,
50 * and write the data to destination address. At the same time, this function updates
51 * the values in master handle structure.
52 *
53 * @param base pointer to FLEXIO_SPI_Type structure
54 * @param handle Pointer to SPI master handle structure.
55 */
56 static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
57
58 /*******************************************************************************
59 * Variables
60 ******************************************************************************/
61
62 /*******************************************************************************
63 * Codes
64 ******************************************************************************/
65
FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type * base)66 uint32_t FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type *base)
67 {
68 return FLEXIO_GetInstance(base->flexioBase);
69 }
70
FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)71 static void FLEXIO_SPI_TransferSendTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
72 {
73 uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
74
75 if (handle->txData != NULL)
76 {
77 /* Transmit data and update tx size/buff. */
78 if (handle->bytePerFrame == 1U)
79 {
80 tmpData = *(handle->txData);
81 handle->txData++;
82 }
83 else
84 {
85 if (handle->direction == kFLEXIO_SPI_MsbFirst)
86 {
87 tmpData = (uint32_t)(handle->txData[0]) << 8U;
88 tmpData += handle->txData[1];
89 }
90 else
91 {
92 tmpData = (uint32_t)(handle->txData[1]) << 8U;
93 tmpData += handle->txData[0];
94 }
95 handle->txData += 2U;
96 }
97 }
98 else
99 {
100 tmpData = FLEXIO_SPI_DUMMYDATA;
101 }
102
103 handle->txRemainingBytes -= handle->bytePerFrame;
104
105 FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
106
107 if (!handle->txRemainingBytes)
108 {
109 FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
110 }
111 }
112
FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)113 static void FLEXIO_SPI_TransferReceiveTransaction(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
114 {
115 uint16_t tmpData;
116
117 tmpData = FLEXIO_SPI_ReadData(base, handle->direction);
118
119 if (handle->rxData != NULL)
120 {
121 if (handle->bytePerFrame == 1U)
122 {
123 *handle->rxData = tmpData;
124 handle->rxData++;
125 }
126 else
127 {
128 if (handle->direction == kFLEXIO_SPI_MsbFirst)
129 {
130 *((uint16_t *)(handle->rxData)) = tmpData;
131 }
132 else
133 {
134 *((uint16_t *)(handle->rxData)) = (((tmpData << 8) & 0xff00U) | ((tmpData >> 8) & 0x00ffU));
135 }
136 handle->rxData += 2U;
137 }
138 }
139 handle->rxRemainingBytes -= handle->bytePerFrame;
140 }
141
FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type * base,flexio_spi_master_config_t * masterConfig,uint32_t srcClock_Hz)142 void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz)
143 {
144 assert(base);
145 assert(masterConfig);
146
147 flexio_shifter_config_t shifterConfig;
148 flexio_timer_config_t timerConfig;
149 uint32_t ctrlReg = 0;
150 uint16_t timerDiv = 0;
151 uint16_t timerCmp = 0;
152
153 /* Clear the shifterConfig & timerConfig struct. */
154 memset(&shifterConfig, 0, sizeof(shifterConfig));
155 memset(&timerConfig, 0, sizeof(timerConfig));
156
157 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
158 /* Ungate flexio clock. */
159 CLOCK_EnableClock(s_flexioClocks[FLEXIO_SPI_GetInstance(base)]);
160 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
161
162 /* Configure FLEXIO SPI Master */
163 ctrlReg = base->flexioBase->CTRL;
164 ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
165 ctrlReg |= (FLEXIO_CTRL_DBGE(masterConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(masterConfig->enableFastAccess) |
166 FLEXIO_CTRL_FLEXEN(masterConfig->enableMaster));
167 if (!masterConfig->enableInDoze)
168 {
169 ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
170 }
171
172 base->flexioBase->CTRL = ctrlReg;
173
174 /* Do hardware configuration. */
175 /* 1. Configure the shifter 0 for tx. */
176 shifterConfig.timerSelect = base->timerIndex[0];
177 shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
178 shifterConfig.pinSelect = base->SDOPinIndex;
179 shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
180 shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
181 shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
182 if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
183 {
184 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
185 shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
186 shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
187 }
188 else
189 {
190 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
191 shifterConfig.shifterStop = kFLEXIO_ShifterStopBitLow;
192 shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
193 }
194
195 FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
196
197 /* 2. Configure the shifter 1 for rx. */
198 shifterConfig.timerSelect = base->timerIndex[0];
199 shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
200 shifterConfig.pinSelect = base->SDIPinIndex;
201 shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
202 shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
203 shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
204 shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
205 shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
206 if (masterConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
207 {
208 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
209 }
210 else
211 {
212 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
213 }
214
215 FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
216
217 /*3. Configure the timer 0 for SCK. */
218 timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->shifterIndex[0]);
219 timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
220 timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
221 timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
222 timerConfig.pinSelect = base->SCKPinIndex;
223 timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
224 timerConfig.timerMode = kFLEXIO_TimerModeDual8BitBaudBit;
225 timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
226 timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
227 timerConfig.timerReset = kFLEXIO_TimerResetNever;
228 timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
229 timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh;
230 timerConfig.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable;
231 timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
232
233 timerDiv = srcClock_Hz / masterConfig->baudRate_Bps;
234 timerDiv = timerDiv / 2 - 1;
235
236 timerCmp = ((uint32_t)(masterConfig->dataMode * 2 - 1U)) << 8U;
237 timerCmp |= timerDiv;
238
239 timerConfig.timerCompare = timerCmp;
240
241 FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
242
243 /* 4. Configure the timer 1 for CSn. */
244 timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(base->timerIndex[0]);
245 timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
246 timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
247 timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
248 timerConfig.pinSelect = base->CSnPinIndex;
249 timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
250 timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
251 timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
252 timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
253 timerConfig.timerReset = kFLEXIO_TimerResetNever;
254 timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
255 timerConfig.timerEnable = kFLEXIO_TimerEnableOnPrevTimerEnable;
256 timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
257 timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
258
259 timerConfig.timerCompare = 0xFFFFU;
260
261 FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[1], &timerConfig);
262 }
263
FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type * base)264 void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base)
265 {
266 /* Disable FLEXIO SPI module. */
267 FLEXIO_SPI_Enable(base, false);
268
269 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
270 /* Gate flexio clock. */
271 CLOCK_DisableClock(kCLOCK_Flexio0);
272 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
273 }
274
FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t * masterConfig)275 void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig)
276 {
277 assert(masterConfig);
278
279 masterConfig->enableMaster = true;
280 masterConfig->enableInDoze = false;
281 masterConfig->enableInDebug = true;
282 masterConfig->enableFastAccess = false;
283 /* Default baud rate 500kbps. */
284 masterConfig->baudRate_Bps = 500000U;
285 /* Default CPHA = 0. */
286 masterConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
287 /* Default bit count at 8. */
288 masterConfig->dataMode = kFLEXIO_SPI_8BitMode;
289 }
290
FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type * base,flexio_spi_slave_config_t * slaveConfig)291 void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig)
292 {
293 assert(base && slaveConfig);
294
295 flexio_shifter_config_t shifterConfig;
296 flexio_timer_config_t timerConfig;
297 uint32_t ctrlReg = 0;
298
299 /* Clear the shifterConfig & timerConfig struct. */
300 memset(&shifterConfig, 0, sizeof(shifterConfig));
301 memset(&timerConfig, 0, sizeof(timerConfig));
302
303 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
304 /* Ungate flexio clock. */
305 CLOCK_EnableClock(kCLOCK_Flexio0);
306 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
307
308 /* Configure FLEXIO SPI Slave */
309 ctrlReg = base->flexioBase->CTRL;
310 ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
311 ctrlReg |= (FLEXIO_CTRL_DBGE(slaveConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(slaveConfig->enableFastAccess) |
312 FLEXIO_CTRL_FLEXEN(slaveConfig->enableSlave));
313 if (!slaveConfig->enableInDoze)
314 {
315 ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
316 }
317
318 base->flexioBase->CTRL = ctrlReg;
319
320 /* Do hardware configuration. */
321 /* 1. Configure the shifter 0 for tx. */
322 shifterConfig.timerSelect = base->timerIndex[0];
323 shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
324 shifterConfig.pinSelect = base->SDOPinIndex;
325 shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
326 shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
327 shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
328 shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
329 if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
330 {
331 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
332 shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
333 }
334 else
335 {
336 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
337 shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
338 }
339
340 FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[0], &shifterConfig);
341
342 /* 2. Configure the shifter 1 for rx. */
343 shifterConfig.timerSelect = base->timerIndex[0];
344 shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
345 shifterConfig.pinSelect = base->SDIPinIndex;
346 shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
347 shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
348 shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
349 shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
350 shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
351 if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
352 {
353 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
354 }
355 else
356 {
357 shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
358 }
359
360 FLEXIO_SetShifterConfig(base->flexioBase, base->shifterIndex[1], &shifterConfig);
361
362 /*3. Configure the timer 0 for shift clock. */
363 timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->CSnPinIndex);
364 timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
365 timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
366 timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
367 timerConfig.pinSelect = base->SCKPinIndex;
368 timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
369 timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
370 timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
371 timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
372 timerConfig.timerReset = kFLEXIO_TimerResetNever;
373 timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerRisingEdge;
374 timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
375 if (slaveConfig->phase == kFLEXIO_SPI_ClockPhaseFirstEdge)
376 {
377 /* The configuration kFLEXIO_TimerDisableOnTimerCompare only support continuous
378 PCS access, change to kFLEXIO_TimerDisableNever to enable discontinuous PCS access. */
379 timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
380 timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
381 }
382 else
383 {
384 timerConfig.timerDisable = kFLEXIO_TimerDisableOnTriggerFallingEdge;
385 timerConfig.timerStart = kFLEXIO_TimerStartBitEnabled;
386 }
387
388 timerConfig.timerCompare = slaveConfig->dataMode * 2 - 1U;
389
390 FLEXIO_SetTimerConfig(base->flexioBase, base->timerIndex[0], &timerConfig);
391 }
392
FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type * base)393 void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base)
394 {
395 FLEXIO_SPI_MasterDeinit(base);
396 }
397
FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t * slaveConfig)398 void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig)
399 {
400 assert(slaveConfig);
401
402 slaveConfig->enableSlave = true;
403 slaveConfig->enableInDoze = false;
404 slaveConfig->enableInDebug = true;
405 slaveConfig->enableFastAccess = false;
406 /* Default CPHA = 0. */
407 slaveConfig->phase = kFLEXIO_SPI_ClockPhaseFirstEdge;
408 /* Default bit count at 8. */
409 slaveConfig->dataMode = kFLEXIO_SPI_8BitMode;
410 }
411
FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type * base,uint32_t mask)412 void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
413 {
414 if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
415 {
416 FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
417 }
418 if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
419 {
420 FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
421 }
422 }
423
FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type * base,uint32_t mask)424 void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask)
425 {
426 if (mask & kFLEXIO_SPI_TxEmptyInterruptEnable)
427 {
428 FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[0]);
429 }
430 if (mask & kFLEXIO_SPI_RxFullInterruptEnable)
431 {
432 FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, 1 << base->shifterIndex[1]);
433 }
434 }
435
FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type * base,uint32_t mask,bool enable)436 void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable)
437 {
438 if (mask & kFLEXIO_SPI_TxDmaEnable)
439 {
440 FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[0], enable);
441 }
442
443 if (mask & kFLEXIO_SPI_RxDmaEnable)
444 {
445 FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1U << base->shifterIndex[1], enable);
446 }
447 }
448
FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type * base)449 uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base)
450 {
451 uint32_t shifterStatus = FLEXIO_GetShifterStatusFlags(base->flexioBase);
452 uint32_t status = 0;
453
454 status = ((shifterStatus & (1U << base->shifterIndex[0])) >> base->shifterIndex[0]);
455 status |= (((shifterStatus & (1U << base->shifterIndex[1])) >> (base->shifterIndex[1])) << 1U);
456
457 return status;
458 }
459
FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type * base,uint32_t mask)460 void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask)
461 {
462 if (mask & kFLEXIO_SPI_TxBufferEmptyFlag)
463 {
464 FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[0]);
465 }
466 if (mask & kFLEXIO_SPI_RxBufferFullFlag)
467 {
468 FLEXIO_ClearShifterStatusFlags(base->flexioBase, 1U << base->shifterIndex[1]);
469 }
470 }
471
FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type * base,uint32_t baudRate_Bps,uint32_t srcClockHz)472 void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz)
473 {
474 uint16_t timerDiv = 0;
475 uint16_t timerCmp = 0;
476 FLEXIO_Type *flexioBase = base->flexioBase;
477
478 /* Set TIMCMP[7:0] = (baud rate divider / 2) - 1.*/
479 timerDiv = srcClockHz / baudRate_Bps;
480 timerDiv = timerDiv / 2 - 1U;
481
482 timerCmp = flexioBase->TIMCMP[base->timerIndex[0]];
483 timerCmp &= 0xFF00U;
484 timerCmp |= timerDiv;
485
486 flexioBase->TIMCMP[base->timerIndex[0]] = timerCmp;
487 }
488
FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type * base,flexio_spi_shift_direction_t direction,const uint8_t * buffer,size_t size)489 void FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
490 flexio_spi_shift_direction_t direction,
491 const uint8_t *buffer,
492 size_t size)
493 {
494 assert(buffer);
495 assert(size);
496
497 while (size--)
498 {
499 /* Wait until data transfer complete. */
500 while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
501 {
502 }
503 FLEXIO_SPI_WriteData(base, direction, *buffer++);
504 }
505 }
506
FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type * base,flexio_spi_shift_direction_t direction,uint8_t * buffer,size_t size)507 void FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
508 flexio_spi_shift_direction_t direction,
509 uint8_t *buffer,
510 size_t size)
511 {
512 assert(buffer);
513 assert(size);
514
515 while (size--)
516 {
517 /* Wait until data transfer complete. */
518 while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
519 {
520 }
521 *buffer++ = FLEXIO_SPI_ReadData(base, direction);
522 }
523 }
524
FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type * base,flexio_spi_transfer_t * xfer)525 void FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer)
526 {
527 flexio_spi_shift_direction_t direction;
528 uint8_t bytesPerFrame;
529 uint32_t dataMode = 0;
530 uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
531 uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
532
533 timerCmp &= 0x00FFU;
534 /* Configure the values in handle. */
535 switch (xfer->flags)
536 {
537 case kFLEXIO_SPI_8bitMsb:
538 dataMode = (8 * 2 - 1U) << 8U;
539 bytesPerFrame = 1;
540 direction = kFLEXIO_SPI_MsbFirst;
541 break;
542
543 case kFLEXIO_SPI_8bitLsb:
544 dataMode = (8 * 2 - 1U) << 8U;
545 bytesPerFrame = 1;
546 direction = kFLEXIO_SPI_LsbFirst;
547 break;
548
549 case kFLEXIO_SPI_16bitMsb:
550 dataMode = (16 * 2 - 1U) << 8U;
551 bytesPerFrame = 2;
552 direction = kFLEXIO_SPI_MsbFirst;
553 break;
554
555 case kFLEXIO_SPI_16bitLsb:
556 dataMode = (16 * 2 - 1U) << 8U;
557 bytesPerFrame = 2;
558 direction = kFLEXIO_SPI_LsbFirst;
559 break;
560
561 default:
562 dataMode = (8 * 2 - 1U) << 8U;
563 bytesPerFrame = 1;
564 direction = kFLEXIO_SPI_MsbFirst;
565 assert(true);
566 break;
567 }
568
569 dataMode |= timerCmp;
570
571 /* Configure transfer size. */
572 base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
573
574 while (xfer->dataSize)
575 {
576 /* Wait until data transfer complete. */
577 while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_TxBufferEmptyFlag))
578 {
579 }
580 if (xfer->txData != NULL)
581 {
582 /* Transmit data and update tx size/buff. */
583 if (bytesPerFrame == 1U)
584 {
585 tmpData = *(xfer->txData);
586 xfer->txData++;
587 }
588 else
589 {
590 if (direction == kFLEXIO_SPI_MsbFirst)
591 {
592 tmpData = (uint32_t)(xfer->txData[0]) << 8U;
593 tmpData += xfer->txData[1];
594 }
595 else
596 {
597 tmpData = (uint32_t)(xfer->txData[1]) << 8U;
598 tmpData += xfer->txData[0];
599 }
600 xfer->txData += 2U;
601 }
602 }
603 else
604 {
605 tmpData = FLEXIO_SPI_DUMMYDATA;
606 }
607
608 xfer->dataSize -= bytesPerFrame;
609
610 FLEXIO_SPI_WriteData(base, direction, tmpData);
611
612 while (!(FLEXIO_SPI_GetStatusFlags(base) & kFLEXIO_SPI_RxBufferFullFlag))
613 {
614 }
615 tmpData = FLEXIO_SPI_ReadData(base, direction);
616
617 if (xfer->rxData != NULL)
618 {
619 if (bytesPerFrame == 1U)
620 {
621 *xfer->rxData = tmpData;
622 xfer->rxData++;
623 }
624 else
625 {
626 if (direction == kFLEXIO_SPI_MsbFirst)
627 {
628 *((uint16_t *)(xfer->rxData)) = tmpData;
629 }
630 else
631 {
632 *((uint16_t *)(xfer->rxData)) = (((tmpData << 8) & 0xff00U) | ((tmpData >> 8) & 0x00ffU));
633 }
634 xfer->rxData += 2U;
635 }
636 }
637 }
638 }
639
FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,flexio_spi_master_transfer_callback_t callback,void * userData)640 status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
641 flexio_spi_master_handle_t *handle,
642 flexio_spi_master_transfer_callback_t callback,
643 void *userData)
644 {
645 assert(handle);
646
647 IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
648
649 /* Zero the handle. */
650 memset(handle, 0, sizeof(*handle));
651
652 /* Register callback and userData. */
653 handle->callback = callback;
654 handle->userData = userData;
655
656 /* Enable interrupt in NVIC. */
657 EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
658
659 /* Save the context in global variables to support the double weak mechanism. */
660 return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_MasterTransferHandleIRQ);
661 }
662
FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,flexio_spi_transfer_t * xfer)663 status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
664 flexio_spi_master_handle_t *handle,
665 flexio_spi_transfer_t *xfer)
666 {
667 assert(handle);
668 assert(xfer);
669
670 uint32_t dataMode = 0;
671 uint16_t timerCmp = base->flexioBase->TIMCMP[base->timerIndex[0]];
672 uint16_t tmpData = FLEXIO_SPI_DUMMYDATA;
673
674 timerCmp &= 0x00FFU;
675
676 /* Check if SPI is busy. */
677 if (handle->state == kFLEXIO_SPI_Busy)
678 {
679 return kStatus_FLEXIO_SPI_Busy;
680 }
681
682 /* Check if the argument is legal. */
683 if ((xfer->txData == NULL) && (xfer->rxData == NULL))
684 {
685 return kStatus_InvalidArgument;
686 }
687
688 /* Configure the values in handle */
689 switch (xfer->flags)
690 {
691 case kFLEXIO_SPI_8bitMsb:
692 dataMode = (8 * 2 - 1U) << 8U;
693 handle->bytePerFrame = 1U;
694 handle->direction = kFLEXIO_SPI_MsbFirst;
695 break;
696 case kFLEXIO_SPI_8bitLsb:
697 dataMode = (8 * 2 - 1U) << 8U;
698 handle->bytePerFrame = 1U;
699 handle->direction = kFLEXIO_SPI_LsbFirst;
700 break;
701 case kFLEXIO_SPI_16bitMsb:
702 dataMode = (16 * 2 - 1U) << 8U;
703 handle->bytePerFrame = 2U;
704 handle->direction = kFLEXIO_SPI_MsbFirst;
705 break;
706 case kFLEXIO_SPI_16bitLsb:
707 dataMode = (16 * 2 - 1U) << 8U;
708 handle->bytePerFrame = 2U;
709 handle->direction = kFLEXIO_SPI_LsbFirst;
710 break;
711 default:
712 dataMode = (8 * 2 - 1U) << 8U;
713 handle->bytePerFrame = 1U;
714 handle->direction = kFLEXIO_SPI_MsbFirst;
715 assert(true);
716 break;
717 }
718
719 dataMode |= timerCmp;
720
721 /* Configure transfer size. */
722 base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
723
724 handle->state = kFLEXIO_SPI_Busy;
725 handle->txData = xfer->txData;
726 handle->rxData = xfer->rxData;
727 handle->rxRemainingBytes = xfer->dataSize;
728
729 /* Save total transfer size. */
730 handle->transferSize = xfer->dataSize;
731
732 /* Send first byte of data to trigger the rx interrupt. */
733 if (handle->txData != NULL)
734 {
735 /* Transmit data and update tx size/buff. */
736 if (handle->bytePerFrame == 1U)
737 {
738 tmpData = *(handle->txData);
739 handle->txData++;
740 }
741 else
742 {
743 if (handle->direction == kFLEXIO_SPI_MsbFirst)
744 {
745 tmpData = (uint32_t)(handle->txData[0]) << 8U;
746 tmpData += handle->txData[1];
747 }
748 else
749 {
750 tmpData = (uint32_t)(handle->txData[1]) << 8U;
751 tmpData += handle->txData[0];
752 }
753 handle->txData += 2U;
754 }
755 }
756 else
757 {
758 tmpData = FLEXIO_SPI_DUMMYDATA;
759 }
760
761 handle->txRemainingBytes = xfer->dataSize - handle->bytePerFrame;
762
763 FLEXIO_SPI_WriteData(base, handle->direction, tmpData);
764
765 /* Enable transmit and receive interrupt to handle rx. */
766 FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
767
768 return kStatus_Success;
769 }
770
FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle,size_t * count)771 status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count)
772 {
773 assert(handle);
774
775 if (!count)
776 {
777 return kStatus_InvalidArgument;
778 }
779
780 /* Return remaing bytes in different cases. */
781 if (handle->rxData)
782 {
783 *count = handle->transferSize - handle->rxRemainingBytes;
784 }
785 else
786 {
787 *count = handle->transferSize - handle->txRemainingBytes;
788 }
789
790 return kStatus_Success;
791 }
792
FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type * base,flexio_spi_master_handle_t * handle)793 void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle)
794 {
795 assert(handle);
796
797 FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
798 FLEXIO_SPI_DisableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
799
800 /* Transfer finished, set the state to idle. */
801 handle->state = kFLEXIO_SPI_Idle;
802
803 /* Clear the internal state. */
804 handle->rxRemainingBytes = 0;
805 handle->txRemainingBytes = 0;
806 }
807
FLEXIO_SPI_MasterTransferHandleIRQ(void * spiType,void * spiHandle)808 void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle)
809 {
810 assert(spiHandle);
811
812 flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
813 FLEXIO_SPI_Type *base;
814 uint32_t status;
815
816 if (handle->state == kFLEXIO_SPI_Idle)
817 {
818 return;
819 }
820
821 base = (FLEXIO_SPI_Type *)spiType;
822 status = FLEXIO_SPI_GetStatusFlags(base);
823
824 /* Handle rx. */
825 if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
826 {
827 FLEXIO_SPI_TransferReceiveTransaction(base, handle);
828 }
829
830 /* Handle tx. */
831 if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
832 {
833 FLEXIO_SPI_TransferSendTransaction(base, handle);
834 }
835
836 /* All the transfer finished. */
837 if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
838 {
839 FLEXIO_SPI_MasterTransferAbort(base, handle);
840 if (handle->callback)
841 {
842 (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
843 }
844 }
845 }
846
FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_slave_transfer_callback_t callback,void * userData)847 status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
848 flexio_spi_slave_handle_t *handle,
849 flexio_spi_slave_transfer_callback_t callback,
850 void *userData)
851 {
852 assert(handle);
853
854 IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
855
856 /* Zero the handle. */
857 memset(handle, 0, sizeof(*handle));
858
859 /* Register callback and userData. */
860 handle->callback = callback;
861 handle->userData = userData;
862
863 /* Enable interrupt in NVIC. */
864 EnableIRQ(flexio_irqs[FLEXIO_SPI_GetInstance(base)]);
865
866 /* Save the context in global variables to support the double weak mechanism. */
867 return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_SPI_SlaveTransferHandleIRQ);
868 }
869
FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type * base,flexio_spi_slave_handle_t * handle,flexio_spi_transfer_t * xfer)870 status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
871 flexio_spi_slave_handle_t *handle,
872 flexio_spi_transfer_t *xfer)
873 {
874 assert(handle);
875 assert(xfer);
876
877 uint32_t dataMode = 0;
878
879 /* Check if SPI is busy. */
880 if (handle->state == kFLEXIO_SPI_Busy)
881 {
882 return kStatus_FLEXIO_SPI_Busy;
883 }
884
885 /* Check if the argument is legal. */
886 if ((xfer->txData == NULL) && (xfer->rxData == NULL))
887 {
888 return kStatus_InvalidArgument;
889 }
890
891 /* Configure the values in handle */
892 switch (xfer->flags)
893 {
894 case kFLEXIO_SPI_8bitMsb:
895 dataMode = 8 * 2 - 1U;
896 handle->bytePerFrame = 1U;
897 handle->direction = kFLEXIO_SPI_MsbFirst;
898 break;
899 case kFLEXIO_SPI_8bitLsb:
900 dataMode = 8 * 2 - 1U;
901 handle->bytePerFrame = 1U;
902 handle->direction = kFLEXIO_SPI_LsbFirst;
903 break;
904 case kFLEXIO_SPI_16bitMsb:
905 dataMode = 16 * 2 - 1U;
906 handle->bytePerFrame = 2U;
907 handle->direction = kFLEXIO_SPI_MsbFirst;
908 break;
909 case kFLEXIO_SPI_16bitLsb:
910 dataMode = 16 * 2 - 1U;
911 handle->bytePerFrame = 2U;
912 handle->direction = kFLEXIO_SPI_LsbFirst;
913 break;
914 default:
915 dataMode = 8 * 2 - 1U;
916 handle->bytePerFrame = 1U;
917 handle->direction = kFLEXIO_SPI_MsbFirst;
918 assert(true);
919 break;
920 }
921
922 /* Configure transfer size. */
923 base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
924
925 handle->state = kFLEXIO_SPI_Busy;
926 handle->txData = xfer->txData;
927 handle->rxData = xfer->rxData;
928 handle->txRemainingBytes = xfer->dataSize;
929 handle->rxRemainingBytes = xfer->dataSize;
930
931 /* Save total transfer size. */
932 handle->transferSize = xfer->dataSize;
933
934 /* Enable transmit and receive interrupt to handle tx and rx. */
935 FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_TxEmptyInterruptEnable);
936 FLEXIO_SPI_EnableInterrupts(base, kFLEXIO_SPI_RxFullInterruptEnable);
937
938 return kStatus_Success;
939 }
940
FLEXIO_SPI_SlaveTransferHandleIRQ(void * spiType,void * spiHandle)941 void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle)
942 {
943 assert(spiHandle);
944
945 flexio_spi_master_handle_t *handle = (flexio_spi_master_handle_t *)spiHandle;
946 FLEXIO_SPI_Type *base;
947 uint32_t status;
948
949 if (handle->state == kFLEXIO_SPI_Idle)
950 {
951 return;
952 }
953
954 base = (FLEXIO_SPI_Type *)spiType;
955 status = FLEXIO_SPI_GetStatusFlags(base);
956
957 /* Handle tx. */
958 if ((status & kFLEXIO_SPI_TxBufferEmptyFlag) && (handle->txRemainingBytes))
959 {
960 FLEXIO_SPI_TransferSendTransaction(base, handle);
961 }
962
963 /* Handle rx. */
964 if ((status & kFLEXIO_SPI_RxBufferFullFlag) && (handle->rxRemainingBytes))
965 {
966 FLEXIO_SPI_TransferReceiveTransaction(base, handle);
967 }
968
969 /* All the transfer finished. */
970 if ((handle->txRemainingBytes == 0U) && (handle->rxRemainingBytes == 0U))
971 {
972 FLEXIO_SPI_SlaveTransferAbort(base, handle);
973 if (handle->callback)
974 {
975 (handle->callback)(base, handle, kStatus_FLEXIO_SPI_Idle, handle->userData);
976 }
977 }
978 }
979