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 | |
63 | static uint32_t FLEXIO_SPI_GetInstance(FLEXIO_SPI_Type *base) |
64 | { |
65 | return FLEXIO_GetInstance(base->flexioBase); |
66 | } |
67 | |
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 | |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | |
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 | |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | */ |
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 | |