1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2021 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_flexio_mculcd.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.flexio_mculcd"
14 #endif
15
16 /*******************************************************************************
17 * Definitations
18 ******************************************************************************/
19
20 enum _mculcd_transfer_state
21 {
22 kFLEXIO_MCULCD_StateIdle, /*!< No transfer in progress. */
23 kFLEXIO_MCULCD_StateReadArray, /*!< Reading array in progress. */
24 kFLEXIO_MCULCD_StateWriteArray, /*!< Writing array in progress. */
25 kFLEXIO_MCULCD_StateWriteSameValue, /*!< Writing the same value in progress. */
26 };
27
28 /* The TIMCFG[0:7] is used for baud rate divider in dual 8-bit counters baud/bit mode. */
29 #define FLEXIO_BAUDRATE_DIV_MASK 0xFFU
30
31 /*******************************************************************************
32 * Prototypes
33 ******************************************************************************/
34
35 /*******************************************************************************
36 * Variables
37 ******************************************************************************/
38
39 /*******************************************************************************
40 * Code
41 ******************************************************************************/
42 /*!
43 * brief Ungates the FlexIO clock, resets the FlexIO module, configures the
44 * FlexIO MCULCD hardware, and configures the FlexIO MCULCD with FlexIO MCULCD
45 * configuration.
46 * The configuration structure can be filled by the user, or be set with default
47 * values
48 * by the ref FLEXIO_MCULCD_GetDefaultConfig.
49 *
50 * param base Pointer to the FLEXIO_MCULCD_Type structure.
51 * param config Pointer to the flexio_mculcd_config_t structure.
52 * param srcClock_Hz FlexIO source clock in Hz.
53 * retval kStatus_Success Initialization success.
54 * retval kStatus_InvalidArgument Initialization failed because of invalid
55 * argument.
56 */
FLEXIO_MCULCD_Init(FLEXIO_MCULCD_Type * base,flexio_mculcd_config_t * config,uint32_t srcClock_Hz)57 status_t FLEXIO_MCULCD_Init(FLEXIO_MCULCD_Type *base, flexio_mculcd_config_t *config, uint32_t srcClock_Hz)
58 {
59 assert(NULL != config);
60
61 flexio_config_t flexioConfig = {config->enable, config->enableInDoze, config->enableInDebug,
62 config->enableFastAccess};
63
64 FLEXIO_Init(base->flexioBase, &flexioConfig);
65
66 if (kStatus_Success != FLEXIO_MCULCD_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz))
67 {
68 return kStatus_Success;
69 }
70
71 base->setCSPin(true);
72 base->setRSPin(true);
73
74 return kStatus_Success;
75 }
76
77 /*!
78 * brief Resets the FLEXIO_MCULCD timer and shifter configuration.
79 *
80 * param base Pointer to the FLEXIO_MCULCD_Type.
81 */
FLEXIO_MCULCD_Deinit(FLEXIO_MCULCD_Type * base)82 void FLEXIO_MCULCD_Deinit(FLEXIO_MCULCD_Type *base)
83 {
84 FLEXIO_MCULCD_ClearSingleBeatWriteConfig(base);
85 FLEXIO_MCULCD_ClearSingleBeatReadConfig(base);
86 }
87
88 /*!
89 * brief Gets the default configuration to configure the FlexIO MCULCD.
90 *
91 * The default configuration value is:
92 * code
93 * config->enable = true;
94 * config->enableInDoze = false;
95 * config->enableInDebug = true;
96 * config->enableFastAccess = true;
97 * config->baudRate_Bps = 96000000U;
98 * endcode
99 * param Config Pointer to the flexio_mculcd_config_t structure.
100 */
FLEXIO_MCULCD_GetDefaultConfig(flexio_mculcd_config_t * config)101 void FLEXIO_MCULCD_GetDefaultConfig(flexio_mculcd_config_t *config)
102 {
103 assert(NULL != config);
104
105 /* Initializes the configure structure to zero. */
106 (void)memset(config, 0, sizeof(*config));
107
108 config->enable = true;
109 config->enableInDoze = false;
110 config->enableInDebug = true;
111 config->enableFastAccess = true;
112 config->baudRate_Bps = 96000000U;
113 }
114
115 /*!
116 * brief Set desired baud rate.
117 *
118 * param base Pointer to the FLEXIO_MCULCD_Type structure.
119 * param baudRate_Bps Desired baud rate.
120 * param srcClock_Hz FLEXIO clock frequency in Hz.
121 * retval kStatus_Success Set successfully.
122 * retval kStatus_InvalidArgument Could not set the baud rate.
123 */
FLEXIO_MCULCD_SetBaudRate(FLEXIO_MCULCD_Type * base,uint32_t baudRate_Bps,uint32_t srcClock_Hz)124 status_t FLEXIO_MCULCD_SetBaudRate(FLEXIO_MCULCD_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
125 {
126 uint32_t baudRateDiv;
127 uint32_t baudRatePerDataLine;
128 uint32_t timerCompare;
129 status_t status;
130
131 baudRatePerDataLine = baudRate_Bps / (uint32_t)FLEXIO_MCULCD_DATA_BUS_WIDTH;
132
133 baudRateDiv = (srcClock_Hz + baudRatePerDataLine) / (baudRatePerDataLine * 2U);
134
135 if ((0U == baudRateDiv) || (baudRateDiv > (FLEXIO_BAUDRATE_DIV_MASK + 1U)))
136 {
137 status = kStatus_InvalidArgument;
138 }
139 else
140 {
141 baudRateDiv--;
142
143 timerCompare = base->flexioBase->TIMCMP[base->timerIndex];
144
145 timerCompare = (timerCompare & ~FLEXIO_BAUDRATE_DIV_MASK) | baudRateDiv;
146
147 base->flexioBase->TIMCMP[base->timerIndex] = timerCompare;
148
149 status = kStatus_Success;
150 }
151
152 return status;
153 }
154
155 /*!
156 * brief Gets FlexIO MCULCD status flags.
157 *
158 * param base Pointer to the FLEXIO_MCULCD_Type structure.
159 * return status flag; OR'ed value or the ref _flexio_mculcd_status_flags.
160 *
161 * note Don't use this function with DMA APIs.
162 */
FLEXIO_MCULCD_GetStatusFlags(FLEXIO_MCULCD_Type * base)163 uint32_t FLEXIO_MCULCD_GetStatusFlags(FLEXIO_MCULCD_Type *base)
164 {
165 uint32_t ret = 0U;
166 uint32_t flags;
167
168 /* Get shifter status. */
169 flags = FLEXIO_GetShifterStatusFlags(base->flexioBase);
170
171 if (0U != (flags & (1UL << base->rxShifterEndIndex)))
172 {
173 ret |= (uint32_t)kFLEXIO_MCULCD_RxFullFlag;
174 }
175
176 if (0U != (flags & (1UL << base->txShifterStartIndex)))
177 {
178 ret |= (uint32_t)kFLEXIO_MCULCD_TxEmptyFlag;
179 }
180
181 return ret;
182 }
183
184 /*!
185 * brief Clears FlexIO MCULCD status flags.
186 *
187 * param base Pointer to the FLEXIO_MCULCD_Type structure.
188 * param mask Status to clear, it is the OR'ed value of ref
189 * _flexio_mculcd_status_flags.
190 *
191 * note Don't use this function with DMA APIs.
192 */
FLEXIO_MCULCD_ClearStatusFlags(FLEXIO_MCULCD_Type * base,uint32_t mask)193 void FLEXIO_MCULCD_ClearStatusFlags(FLEXIO_MCULCD_Type *base, uint32_t mask)
194 {
195 uint32_t flags = 0U;
196
197 /* Clear the shifter flags. */
198 if (0U != (mask & (uint32_t)kFLEXIO_MCULCD_RxFullFlag))
199 {
200 flags |= (1UL << base->rxShifterEndIndex);
201 }
202
203 if (0U != (mask & (uint32_t)kFLEXIO_MCULCD_TxEmptyFlag))
204 {
205 flags |= (1UL << base->txShifterStartIndex);
206 }
207
208 FLEXIO_ClearShifterStatusFlags(base->flexioBase, flags);
209 }
210
211 /*!
212 * brief Enables the FlexIO MCULCD interrupt.
213 *
214 * This function enables the FlexIO MCULCD interrupt.
215 *
216 * param base Pointer to the FLEXIO_MCULCD_Type structure.
217 * param mask Interrupts to enable, it is the OR'ed value of ref
218 * _flexio_mculcd_interrupt_enable.
219 */
FLEXIO_MCULCD_EnableInterrupts(FLEXIO_MCULCD_Type * base,uint32_t mask)220 void FLEXIO_MCULCD_EnableInterrupts(FLEXIO_MCULCD_Type *base, uint32_t mask)
221 {
222 uint32_t interrupts = 0U;
223
224 /* Enable shifter interrupts. */
225 if (0U != (mask & (uint32_t)kFLEXIO_MCULCD_RxFullFlag))
226 {
227 interrupts |= (1UL << base->rxShifterEndIndex);
228 }
229
230 if (0U != (mask & (uint32_t)kFLEXIO_MCULCD_TxEmptyFlag))
231 {
232 interrupts |= (1UL << base->txShifterStartIndex);
233 }
234
235 FLEXIO_EnableShifterStatusInterrupts(base->flexioBase, interrupts);
236 }
237
238 /*!
239 * brief Disables the FlexIO MCULCD interrupt.
240 *
241 * This function disables the FlexIO MCULCD interrupt.
242 *
243 * param base Pointer to the FLEXIO_MCULCD_Type structure.
244 * param mask Interrupts to disable, it is the OR'ed value of ref
245 * _flexio_mculcd_interrupt_enable.
246 */
FLEXIO_MCULCD_DisableInterrupts(FLEXIO_MCULCD_Type * base,uint32_t mask)247 void FLEXIO_MCULCD_DisableInterrupts(FLEXIO_MCULCD_Type *base, uint32_t mask)
248 {
249 uint32_t interrupts = 0U;
250
251 /* Disable shifter interrupts. */
252 if (0U != (mask & (uint32_t)kFLEXIO_MCULCD_RxFullFlag))
253 {
254 interrupts |= (1UL << base->rxShifterEndIndex);
255 }
256
257 if (0U != (mask & (uint32_t)kFLEXIO_MCULCD_TxEmptyFlag))
258 {
259 interrupts |= (1UL << base->txShifterStartIndex);
260 }
261
262 FLEXIO_DisableShifterStatusInterrupts(base->flexioBase, interrupts);
263 }
264
265 /*!
266 * brief Read data from the FLEXIO MCULCD RX shifter buffer.
267 *
268 * Read data from the RX shift buffer directly, it does no check whether the
269 * buffer is empty or not.
270 *
271 * If the data bus width is 8-bit:
272 * code
273 * uint8_t value;
274 * value = (uint8_t)FLEXIO_MCULCD_ReadData(base);
275 * endcode
276 *
277 * If the data bus width is 16-bit:
278 * code
279 * uint16_t value;
280 * value = (uint16_t)FLEXIO_MCULCD_ReadData(base);
281 * endcode
282 *
283 * note This function returns the RX shifter buffer value (32-bit) directly.
284 * The return value should be converted according to data bus width.
285 *
286 * param base Pointer to the FLEXIO_MCULCD_Type structure.
287 * return The data read out.
288 *
289 * note Don't use this function with DMA APIs.
290 */
FLEXIO_MCULCD_ReadData(FLEXIO_MCULCD_Type * base)291 uint32_t FLEXIO_MCULCD_ReadData(FLEXIO_MCULCD_Type *base)
292 {
293 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
294 return base->flexioBase->SHIFTBUFBYS[base->rxShifterEndIndex];
295 #else
296 return base->flexioBase->SHIFTBUFHWS[base->rxShifterEndIndex];
297 #endif
298 }
299
300 /*!
301 * brief Configures the FLEXIO MCULCD to multiple beats write mode.
302 *
303 * At the begining multiple beats write operation, the FLEXIO MCULCD is configured to
304 * multiple beats write mode using this function. After write operation, the configuration
305 * is cleared by ref FLEXIO_MCULCD_ClearSingleBeatWriteConfig.
306 *
307 * param base Pointer to the FLEXIO_MCULCD_Type.
308 *
309 * note This is an internal used function, upper layer should not use.
310 */
FLEXIO_MCULCD_SetSingleBeatWriteConfig(FLEXIO_MCULCD_Type * base)311 void FLEXIO_MCULCD_SetSingleBeatWriteConfig(FLEXIO_MCULCD_Type *base)
312 {
313 /*
314 * This function will be called at the beginning of every data writing. For
315 * performance consideration, it access the FlexIO registers directly, but not
316 * call FlexIO driver APIs.
317 */
318
319 uint32_t timerCompare;
320
321 /* Enable the TX Shifter output. */
322 base->flexioBase->SHIFTCFG[base->txShifterStartIndex] =
323 FLEXIO_SHIFTCFG_PWIDTH((uint32_t)FLEXIO_MCULCD_DATA_BUS_WIDTH - 1U) |
324 FLEXIO_SHIFTCFG_INSRC(kFLEXIO_ShifterInputFromNextShifterOutput);
325
326 base->flexioBase->SHIFTCTL[base->txShifterStartIndex] =
327 FLEXIO_SHIFTCTL_TIMSEL(base->timerIndex) | FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnPositive) |
328 FLEXIO_SHIFTCTL_PINCFG(kFLEXIO_PinConfigOutput) | FLEXIO_SHIFTCTL_PINSEL(base->dataPinStartIndex) |
329 FLEXIO_SHIFTCTL_PINPOL(kFLEXIO_PinActiveHigh) | FLEXIO_SHIFTCTL_SMOD(kFLEXIO_ShifterModeTransmit);
330
331 timerCompare = base->flexioBase->TIMCMP[base->timerIndex] & 0xFFU;
332
333 /*
334 * TIMCMP[15:8] = (number of beats x 2) - 1. Because the number of beat is 1,
335 * so the TIMCMP[15:8] is 1.
336 */
337 base->flexioBase->TIMCMP[base->timerIndex] = (1UL << 8U) | timerCompare;
338
339 /* Use TX shifter flag as the inverted timer trigger. Timer output to WR/EN pin. */
340 base->flexioBase->TIMCFG[base->timerIndex] =
341 FLEXIO_TIMCFG_TIMOUT(kFLEXIO_TimerOutputOneNotAffectedByReset) |
342 FLEXIO_TIMCFG_TIMDEC(kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput) |
343 FLEXIO_TIMCFG_TIMRST(kFLEXIO_TimerResetNever) | FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare) |
344 FLEXIO_TIMCFG_TIMENA(kFLEXIO_TimerEnableOnTriggerHigh) | FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitDisabled) |
345 FLEXIO_TIMCFG_TSTART(kFLEXIO_TimerStartBitDisabled);
346
347 base->flexioBase->TIMCTL[base->timerIndex] =
348 FLEXIO_TIMCTL_TRGSEL(FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->txShifterStartIndex)) |
349 FLEXIO_TIMCTL_TRGPOL(kFLEXIO_TimerTriggerPolarityActiveLow) |
350 FLEXIO_TIMCTL_TRGSRC(kFLEXIO_TimerTriggerSourceInternal) | FLEXIO_TIMCTL_PINCFG(kFLEXIO_PinConfigOutput) |
351 FLEXIO_TIMCTL_PINSEL(base->ENWRPinIndex) | FLEXIO_TIMCTL_PINPOL(kFLEXIO_PinActiveLow) |
352 FLEXIO_TIMCTL_TIMOD(kFLEXIO_TimerModeDual8BitBaudBit);
353 }
354
355 /*!
356 * brief Clear the FLEXIO MCULCD multiple beats write mode configuration.
357 *
358 * Clear the write configuration set by ref FLEXIO_MCULCD_SetSingleBeatWriteConfig.
359 *
360 * param base Pointer to the FLEXIO_MCULCD_Type.
361 *
362 * note This is an internal used function, upper layer should not use.
363 */
FLEXIO_MCULCD_ClearSingleBeatWriteConfig(FLEXIO_MCULCD_Type * base)364 void FLEXIO_MCULCD_ClearSingleBeatWriteConfig(FLEXIO_MCULCD_Type *base)
365 {
366 /* Disable the timer. */
367 base->flexioBase->TIMCTL[base->timerIndex] = 0U;
368 base->flexioBase->TIMCFG[base->timerIndex] = 0U;
369 /* Clear the timer flag. */
370 base->flexioBase->TIMSTAT = (1UL << base->timerIndex);
371 /* Stop the TX shifter. */
372 base->flexioBase->SHIFTCTL[base->txShifterStartIndex] = 0U;
373 base->flexioBase->SHIFTCFG[base->txShifterStartIndex] = 0U;
374 /* Clear the shifter flag. */
375 base->flexioBase->SHIFTSTAT = (1UL << base->txShifterStartIndex);
376 }
377
378 /*!
379 * brief Configures the FLEXIO MCULCD to multiple beats read mode.
380 *
381 * At the begining or multiple beats read operation, the FLEXIO MCULCD is configured
382 * to multiple beats read mode using this function. After read operation, the configuration
383 * is cleared by ref FLEXIO_MCULCD_ClearSingleBeatReadConfig.
384 *
385 * param base Pointer to the FLEXIO_MCULCD_Type.
386 *
387 * note This is an internal used function, upper layer should not use.
388 */
FLEXIO_MCULCD_SetSingleBeatReadConfig(FLEXIO_MCULCD_Type * base)389 void FLEXIO_MCULCD_SetSingleBeatReadConfig(FLEXIO_MCULCD_Type *base)
390 {
391 /*
392 * This function will be called at the beginning of every data reading. For
393 * performance consideration, it access the FlexIO registers directly, but not
394 * call FlexIO driver APIs.
395 */
396
397 uint8_t timerPin;
398 uint32_t timerCompare;
399 flexio_pin_polarity_t timerPinPolarity;
400
401 /* Timer output to RD pin (8080 mode), to WR/EN pin in 6800 mode. */
402 if (kFLEXIO_MCULCD_8080 == base->busType)
403 {
404 timerPin = base->RDPinIndex;
405 timerPinPolarity = kFLEXIO_PinActiveLow;
406 }
407 else
408 {
409 timerPin = base->ENWRPinIndex;
410 timerPinPolarity = kFLEXIO_PinActiveHigh;
411 }
412
413 /* Enable the RX Shifter input. */
414 base->flexioBase->SHIFTCFG[base->rxShifterEndIndex] =
415 FLEXIO_SHIFTCFG_PWIDTH((uint32_t)FLEXIO_MCULCD_DATA_BUS_WIDTH - 1U);
416
417 base->flexioBase->SHIFTCTL[base->rxShifterEndIndex] =
418 FLEXIO_SHIFTCTL_TIMSEL(base->timerIndex) | FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnNegitive) |
419 FLEXIO_SHIFTCTL_PINCFG(kFLEXIO_PinConfigOutputDisabled) | FLEXIO_SHIFTCTL_PINSEL(base->dataPinStartIndex) |
420 FLEXIO_SHIFTCTL_PINPOL(kFLEXIO_PinActiveHigh) | FLEXIO_SHIFTCTL_SMOD(kFLEXIO_ShifterModeReceive);
421
422 /* Use RX shifter flag as the inverted timer trigger. */
423 base->flexioBase->TIMCFG[base->timerIndex] =
424 FLEXIO_TIMCFG_TIMOUT(kFLEXIO_TimerOutputOneNotAffectedByReset) |
425 FLEXIO_TIMCFG_TIMDEC(kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput) |
426 FLEXIO_TIMCFG_TIMRST(kFLEXIO_TimerResetNever) | FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare) |
427 FLEXIO_TIMCFG_TIMENA(kFLEXIO_TimerEnableOnTriggerHigh) |
428 FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitEnableOnTimerDisable) |
429 FLEXIO_TIMCFG_TSTART(kFLEXIO_TimerStartBitDisabled);
430
431 timerCompare = base->flexioBase->TIMCMP[base->timerIndex] & 0xFFU;
432
433 /*
434 * TIMCMP[15:8] = (number of beats x 2) - 1. Because the number of beat is 1,
435 * so the TIMCMP[15:8] is 1.
436 */
437 base->flexioBase->TIMCMP[base->timerIndex] = (1UL << 8U) | timerCompare;
438
439 base->flexioBase->TIMCTL[base->timerIndex] |=
440 FLEXIO_TIMCTL_TRGSEL(FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->rxShifterEndIndex)) |
441 FLEXIO_TIMCTL_TRGPOL(kFLEXIO_TimerTriggerPolarityActiveLow) |
442 FLEXIO_TIMCTL_TRGSRC(kFLEXIO_TimerTriggerSourceInternal) | FLEXIO_TIMCTL_PINCFG(kFLEXIO_PinConfigOutput) |
443 FLEXIO_TIMCTL_PINSEL(timerPin) | FLEXIO_TIMCTL_PINPOL(timerPinPolarity) |
444 FLEXIO_TIMCTL_TIMOD(kFLEXIO_TimerModeDual8BitBaudBit);
445 }
446
447 /*!
448 * brief Clear the FLEXIO MCULCD multiple beats read mode configuration.
449 *
450 * Clear the read configuration set by ref FLEXIO_MCULCD_SetSingleBeatReadConfig.
451 *
452 * param base Pointer to the FLEXIO_MCULCD_Type.
453 *
454 * note This is an internal used function, upper layer should not use.
455 */
FLEXIO_MCULCD_ClearSingleBeatReadConfig(FLEXIO_MCULCD_Type * base)456 void FLEXIO_MCULCD_ClearSingleBeatReadConfig(FLEXIO_MCULCD_Type *base)
457 {
458 /* Disable the timer. */
459 base->flexioBase->TIMCTL[base->timerIndex] = 0U;
460 base->flexioBase->TIMCFG[base->timerIndex] = 0U;
461 /* Clear the timer flag. */
462 base->flexioBase->TIMSTAT = (1UL << base->timerIndex);
463 /* Stop the RX shifter. */
464 base->flexioBase->SHIFTCTL[base->rxShifterEndIndex] = 0U;
465 base->flexioBase->SHIFTCFG[base->rxShifterEndIndex] = 0U;
466 /* Clear the shifter flag. */
467 base->flexioBase->SHIFTSTAT = (1UL << base->rxShifterEndIndex);
468 }
469
470 /*!
471 * brief Configures the FLEXIO MCULCD to multiple beats write mode.
472 *
473 * At the begining multiple beats write operation, the FLEXIO MCULCD is configured to
474 * multiple beats write mode using this function. After write operation, the configuration
475 * is cleared by ref FLEXIO_MCULCD_ClearMultBeatsWriteConfig.
476 *
477 * param base Pointer to the FLEXIO_MCULCD_Type.
478 *
479 * note This is an internal used function, upper layer should not use.
480 */
FLEXIO_MCULCD_SetMultiBeatsWriteConfig(FLEXIO_MCULCD_Type * base)481 void FLEXIO_MCULCD_SetMultiBeatsWriteConfig(FLEXIO_MCULCD_Type *base)
482 {
483 /*
484 * This function will be called at the beginning of every data writing. For
485 * performance consideration, it access the FlexIO registers directly, but not
486 * call FlexIO driver APIs.
487 */
488
489 uint32_t timerCompare;
490 uint8_t beats;
491 uint8_t i;
492
493 /* Enable the TX Shifter output. */
494 base->flexioBase->SHIFTCFG[base->txShifterStartIndex] =
495 FLEXIO_SHIFTCFG_PWIDTH((uint32_t)FLEXIO_MCULCD_DATA_BUS_WIDTH - 1U) |
496 FLEXIO_SHIFTCFG_INSRC(kFLEXIO_ShifterInputFromNextShifterOutput);
497
498 base->flexioBase->SHIFTCTL[base->txShifterStartIndex] =
499 FLEXIO_SHIFTCTL_TIMSEL(base->timerIndex) | FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnPositive) |
500 FLEXIO_SHIFTCTL_PINCFG(kFLEXIO_PinConfigOutput) | FLEXIO_SHIFTCTL_PINSEL(base->dataPinStartIndex) |
501 FLEXIO_SHIFTCTL_PINPOL(kFLEXIO_PinActiveHigh) | FLEXIO_SHIFTCTL_SMOD(kFLEXIO_ShifterModeTransmit);
502
503 for (i = base->txShifterStartIndex + 1U; i <= base->txShifterEndIndex; i++)
504 {
505 base->flexioBase->SHIFTCFG[i] = FLEXIO_SHIFTCFG_PWIDTH((uint32_t)FLEXIO_MCULCD_DATA_BUS_WIDTH - 1U) |
506 FLEXIO_SHIFTCFG_INSRC(kFLEXIO_ShifterInputFromNextShifterOutput);
507
508 base->flexioBase->SHIFTCTL[i] =
509 FLEXIO_SHIFTCTL_TIMSEL(base->timerIndex) | FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnPositive) |
510 FLEXIO_SHIFTCTL_PINCFG(kFLEXIO_PinConfigOutputDisabled) | FLEXIO_SHIFTCTL_PINSEL(0) |
511 FLEXIO_SHIFTCTL_PINPOL(kFLEXIO_PinActiveHigh) | FLEXIO_SHIFTCTL_SMOD(kFLEXIO_ShifterModeTransmit);
512 }
513
514 timerCompare = base->flexioBase->TIMCMP[base->timerIndex] & 0xFFU;
515
516 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
517 beats = 4U * (base->txShifterEndIndex - base->txShifterStartIndex + 1U);
518 #else
519 beats = 2U * (base->txShifterEndIndex - base->txShifterStartIndex + 1U);
520 #endif
521
522 /*
523 * TIMCMP[15:8] = (number of beats x 2) - 1.
524 */
525 base->flexioBase->TIMCMP[base->timerIndex] = ((beats * 2UL - 1UL) << 8U) | timerCompare;
526
527 /* Use TX shifter flag as the inverted timer trigger. Timer output to WR/EN pin. */
528 base->flexioBase->TIMCFG[base->timerIndex] =
529 FLEXIO_TIMCFG_TIMOUT(kFLEXIO_TimerOutputOneNotAffectedByReset) |
530 FLEXIO_TIMCFG_TIMDEC(kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput) |
531 FLEXIO_TIMCFG_TIMRST(kFLEXIO_TimerResetNever) | FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare) |
532 FLEXIO_TIMCFG_TIMENA(kFLEXIO_TimerEnableOnTriggerHigh) | FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitDisabled) |
533 FLEXIO_TIMCFG_TSTART(kFLEXIO_TimerStartBitDisabled);
534
535 base->flexioBase->TIMCTL[base->timerIndex] =
536 FLEXIO_TIMCTL_TRGSEL(FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->txShifterEndIndex)) |
537 FLEXIO_TIMCTL_TRGPOL(kFLEXIO_TimerTriggerPolarityActiveLow) |
538 FLEXIO_TIMCTL_TRGSRC(kFLEXIO_TimerTriggerSourceInternal) | FLEXIO_TIMCTL_PINCFG(kFLEXIO_PinConfigOutput) |
539 FLEXIO_TIMCTL_PINSEL(base->ENWRPinIndex) | FLEXIO_TIMCTL_PINPOL(kFLEXIO_PinActiveLow) |
540 FLEXIO_TIMCTL_TIMOD(kFLEXIO_TimerModeDual8BitBaudBit);
541 }
542
543 /*!
544 * brief Clear the FLEXIO MCULCD multiple beats write mode configuration.
545 *
546 * Clear the write configuration set by ref FLEXIO_MCULCD_SetMultBeatsWriteConfig.
547 *
548 * param base Pointer to the FLEXIO_MCULCD_Type.
549 *
550 * note This is an internal used function, upper layer should not use.
551 */
FLEXIO_MCULCD_ClearMultiBeatsWriteConfig(FLEXIO_MCULCD_Type * base)552 void FLEXIO_MCULCD_ClearMultiBeatsWriteConfig(FLEXIO_MCULCD_Type *base)
553 {
554 uint8_t i;
555 uint32_t statusFlags = 0U;
556
557 /* Disable the timer. */
558 base->flexioBase->TIMCTL[base->timerIndex] = 0U;
559 base->flexioBase->TIMCFG[base->timerIndex] = 0U;
560 /* Clear the timer flag. */
561 base->flexioBase->TIMSTAT = (1UL << base->timerIndex);
562
563 /* Stop the TX shifter. */
564 for (i = base->txShifterStartIndex; i <= base->txShifterEndIndex; i++)
565 {
566 base->flexioBase->SHIFTCFG[i] = 0U;
567 base->flexioBase->SHIFTCTL[i] = 0U;
568 statusFlags |= (1UL << i);
569 }
570 /* Clear the shifter flag. */
571 base->flexioBase->SHIFTSTAT = statusFlags;
572 }
573
574 /*!
575 * brief Configures the FLEXIO MCULCD to multiple beats read mode.
576 *
577 * At the begining or multiple beats read operation, the FLEXIO MCULCD is configured
578 * to multiple beats read mode using this function. After read operation, the configuration
579 * is cleared by ref FLEXIO_MCULCD_ClearMultBeatsReadConfig.
580 *
581 * param base Pointer to the FLEXIO_MCULCD_Type.
582 *
583 * note This is an internal used function, upper layer should not use.
584 */
FLEXIO_MCULCD_SetMultiBeatsReadConfig(FLEXIO_MCULCD_Type * base)585 void FLEXIO_MCULCD_SetMultiBeatsReadConfig(FLEXIO_MCULCD_Type *base)
586 {
587 /*
588 * This function will be called at the beginning of every data reading. For
589 * performance consideration, it access the FlexIO registers directly, but not
590 * call FlexIO driver APIs.
591 */
592
593 uint8_t timerPin;
594 uint8_t beats;
595 uint8_t i;
596 uint32_t timerCompare;
597 flexio_pin_polarity_t timerPinPolarity;
598
599 /* Timer output to RD pin (8080 mode), to WR/EN pin in 6800 mode. */
600 if (kFLEXIO_MCULCD_8080 == base->busType)
601 {
602 timerPin = base->RDPinIndex;
603 timerPinPolarity = kFLEXIO_PinActiveLow;
604 }
605 else
606 {
607 timerPin = base->ENWRPinIndex;
608 timerPinPolarity = kFLEXIO_PinActiveHigh;
609 }
610
611 /* Enable the RX Shifter input. */
612 for (i = base->rxShifterStartIndex; i < base->rxShifterEndIndex; i++)
613 {
614 base->flexioBase->SHIFTCFG[i] = FLEXIO_SHIFTCFG_PWIDTH((uint32_t)FLEXIO_MCULCD_DATA_BUS_WIDTH - 1U) |
615 FLEXIO_SHIFTCFG_INSRC(kFLEXIO_ShifterInputFromNextShifterOutput);
616
617 base->flexioBase->SHIFTCTL[i] =
618 FLEXIO_SHIFTCTL_TIMSEL(base->timerIndex) | FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnNegitive) |
619 FLEXIO_SHIFTCTL_PINCFG(kFLEXIO_PinConfigOutputDisabled) | FLEXIO_SHIFTCTL_PINSEL(base->dataPinStartIndex) |
620 FLEXIO_SHIFTCTL_PINPOL(kFLEXIO_PinActiveHigh) | FLEXIO_SHIFTCTL_SMOD(kFLEXIO_ShifterModeReceive);
621 }
622
623 base->flexioBase->SHIFTCFG[base->rxShifterEndIndex] =
624 FLEXIO_SHIFTCFG_PWIDTH((uint32_t)FLEXIO_MCULCD_DATA_BUS_WIDTH - 1U);
625 base->flexioBase->SHIFTCTL[base->rxShifterEndIndex] =
626 FLEXIO_SHIFTCTL_TIMSEL(base->timerIndex) | FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnNegitive) |
627 FLEXIO_SHIFTCTL_PINCFG(kFLEXIO_PinConfigOutputDisabled) | FLEXIO_SHIFTCTL_PINSEL(base->dataPinStartIndex) |
628 FLEXIO_SHIFTCTL_PINPOL(kFLEXIO_PinActiveHigh) | FLEXIO_SHIFTCTL_SMOD(kFLEXIO_ShifterModeReceive);
629
630 timerCompare = base->flexioBase->TIMCMP[base->timerIndex] & 0xFFU;
631
632 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
633 beats = 4U * (base->rxShifterEndIndex - base->rxShifterStartIndex + 1U);
634 #else
635 beats = 2U * (base->rxShifterEndIndex - base->rxShifterStartIndex + 1U);
636 #endif
637
638 /*
639 * TIMCMP[15:8] = (number of beats x 2) - 1.
640 */
641 base->flexioBase->TIMCMP[base->timerIndex] = ((beats * 2UL - 1UL) << 8U) | timerCompare;
642
643 /* Use RX shifter flag as the inverted timer trigger. */
644 base->flexioBase->TIMCFG[base->timerIndex] =
645 FLEXIO_TIMCFG_TIMOUT(kFLEXIO_TimerOutputOneNotAffectedByReset) |
646 FLEXIO_TIMCFG_TIMDEC(kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput) |
647 FLEXIO_TIMCFG_TIMRST(kFLEXIO_TimerResetNever) | FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare) |
648 FLEXIO_TIMCFG_TIMENA(kFLEXIO_TimerEnableOnTriggerHigh) |
649 FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitEnableOnTimerDisable) |
650 FLEXIO_TIMCFG_TSTART(kFLEXIO_TimerStartBitDisabled);
651
652 base->flexioBase->TIMCTL[base->timerIndex] |=
653 FLEXIO_TIMCTL_TRGSEL(FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(base->rxShifterEndIndex)) |
654 FLEXIO_TIMCTL_TRGPOL(kFLEXIO_TimerTriggerPolarityActiveLow) |
655 FLEXIO_TIMCTL_TRGSRC(kFLEXIO_TimerTriggerSourceInternal) | FLEXIO_TIMCTL_PINCFG(kFLEXIO_PinConfigOutput) |
656 FLEXIO_TIMCTL_PINSEL(timerPin) | FLEXIO_TIMCTL_PINPOL(timerPinPolarity) |
657 FLEXIO_TIMCTL_TIMOD(kFLEXIO_TimerModeDual8BitBaudBit);
658 }
659
660 /*!
661 * brief Clear the FLEXIO MCULCD multiple beats read mode configuration.
662 *
663 * Clear the read configuration set by ref FLEXIO_MCULCD_SetMultBeatsReadConfig.
664 *
665 * param base Pointer to the FLEXIO_MCULCD_Type.
666 *
667 * note This is an internal used function, upper layer should not use.
668 */
FLEXIO_MCULCD_ClearMultiBeatsReadConfig(FLEXIO_MCULCD_Type * base)669 void FLEXIO_MCULCD_ClearMultiBeatsReadConfig(FLEXIO_MCULCD_Type *base)
670 {
671 uint8_t i;
672 uint32_t statusFlags = 0U;
673
674 /* Disable the timer. */
675 base->flexioBase->TIMCTL[base->timerIndex] = 0U;
676 base->flexioBase->TIMCFG[base->timerIndex] = 0U;
677 /* Clear the timer flag. */
678 base->flexioBase->TIMSTAT = (1UL << base->timerIndex);
679 /* Stop the RX shifter. */
680 for (i = base->rxShifterStartIndex; i <= base->rxShifterEndIndex; i++)
681 {
682 base->flexioBase->SHIFTCTL[i] = 0U;
683 base->flexioBase->SHIFTCFG[i] = 0U;
684 statusFlags |= (1UL << i);
685 }
686 /* Clear the shifter flag. */
687 base->flexioBase->SHIFTSTAT = statusFlags;
688 }
689
690 /*!
691 * brief Wait for transmit data send out finished.
692 *
693 * Currently there is no effective method to wait for the data send out
694 * from the shiter, so here use a while loop to wait.
695 *
696 * note This is an internal used function.
697 */
FLEXIO_MCULCD_WaitTransmitComplete(void)698 void FLEXIO_MCULCD_WaitTransmitComplete(void)
699 {
700 uint32_t i = FLEXIO_MCULCD_WAIT_COMPLETE_TIME;
701
702 while (0U != (i--))
703 {
704 __NOP();
705 }
706 }
707
708 /*!
709 * brief Send command in blocking way.
710 *
711 * This function sends the command and returns when the command has been sent
712 * out.
713 *
714 * param base Pointer to the FLEXIO_MCULCD_Type structure.
715 * param command The command to send.
716 */
FLEXIO_MCULCD_WriteCommandBlocking(FLEXIO_MCULCD_Type * base,uint32_t command)717 void FLEXIO_MCULCD_WriteCommandBlocking(FLEXIO_MCULCD_Type *base, uint32_t command)
718 {
719 FLEXIO_Type *flexioBase = base->flexioBase;
720
721 /* De-assert the RS pin. */
722 base->setRSPin(false);
723
724 /* For 6800, de-assert the RDWR pin. */
725 if (kFLEXIO_MCULCD_6800 == base->busType)
726 {
727 base->setRDWRPin(false);
728 }
729
730 /* Configure the timer and TX shifter. */
731 FLEXIO_MCULCD_SetSingleBeatWriteConfig(base);
732
733 /* Write command to shifter buffer. */
734 flexioBase->SHIFTBUF[base->txShifterStartIndex] = command;
735
736 /* Wait for command send out. */
737 while (0U == ((1UL << base->timerIndex) & FLEXIO_GetTimerStatusFlags(flexioBase)))
738 {
739 }
740
741 /* Stop the timer and TX shifter. */
742 FLEXIO_MCULCD_ClearSingleBeatWriteConfig(base);
743
744 /* Assert the RS pin. */
745 base->setRSPin(true);
746 /* For 6800, assert the RDWR pin. */
747 if (kFLEXIO_MCULCD_6800 == base->busType)
748 {
749 base->setRDWRPin(true);
750 }
751 }
752
753 /*!
754 * brief Send data array in blocking way.
755 *
756 * This function sends the data array and returns when the data sent out.
757 *
758 * param base Pointer to the FLEXIO_MCULCD_Type structure.
759 * param data The data array to send.
760 * param size How many bytes to write.
761 */
FLEXIO_MCULCD_WriteDataArrayBlocking(FLEXIO_MCULCD_Type * base,const void * data,size_t size)762 void FLEXIO_MCULCD_WriteDataArrayBlocking(FLEXIO_MCULCD_Type *base, const void *data, size_t size)
763 {
764 assert(size > 0U);
765
766 uint32_t i;
767 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
768 const uint8_t *data8Bit;
769 #else
770 const uint16_t *data16Bit;
771 #endif
772 FLEXIO_Type *flexioBase = base->flexioBase;
773
774 /* Assert the RS pin. */
775 base->setRSPin(true);
776 /* For 6800, de-assert the RDWR pin. */
777 if (kFLEXIO_MCULCD_6800 == base->busType)
778 {
779 base->setRDWRPin(false);
780 }
781
782 /* Configure the timer and TX shifter. */
783 FLEXIO_MCULCD_SetSingleBeatWriteConfig(base);
784
785 /* If data bus width is 8. */
786 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
787 data8Bit = (const uint8_t *)data;
788
789 for (i = 0; i < size; i++)
790 {
791 flexioBase->SHIFTBUF[base->txShifterStartIndex] = data8Bit[i];
792
793 /* Wait for the data send out. */
794 while (0U == ((1UL << base->timerIndex) & flexioBase->TIMSTAT))
795 {
796 }
797
798 /* Clear the timer stat. */
799 flexioBase->TIMSTAT = 1UL << base->timerIndex;
800 }
801 #else
802 data16Bit = (const uint16_t *)data;
803 size /= 2U;
804
805 for (i = 0; i < size; i++)
806 {
807 flexioBase->SHIFTBUF[base->txShifterStartIndex] = data16Bit[i];
808
809 /* Wait for the data send out. */
810 while (0U == ((1UL << base->timerIndex) & flexioBase->TIMSTAT))
811 {
812 }
813
814 /* Clear the timer stat. */
815 flexioBase->TIMSTAT = 1UL << base->timerIndex;
816 }
817 #endif
818
819 /* Stop the timer and TX shifter. */
820 FLEXIO_MCULCD_ClearSingleBeatWriteConfig(base);
821 }
822
823 /*!
824 * brief Read data into array in blocking way.
825 *
826 * This function reads the data into array and returns when the data read
827 * finished.
828 *
829 * param base Pointer to the FLEXIO_MCULCD_Type structure.
830 * param data The array to save the data.
831 * param size How many bytes to read.
832 */
FLEXIO_MCULCD_ReadDataArrayBlocking(FLEXIO_MCULCD_Type * base,void * data,size_t size)833 void FLEXIO_MCULCD_ReadDataArrayBlocking(FLEXIO_MCULCD_Type *base, void *data, size_t size)
834 {
835 assert(size > 0U);
836
837 uint32_t i;
838
839 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
840 uint8_t *data8Bit = (uint8_t *)data;
841 #else
842 uint16_t *data16Bit = (uint16_t *)data;
843 #endif
844 FLEXIO_Type *flexioBase = base->flexioBase;
845
846 /* Assert the RS pin. */
847 base->setRSPin(true);
848 /* For 6800, de-assert the RDWR pin. */
849 if (kFLEXIO_MCULCD_6800 == base->busType)
850 {
851 base->setRDWRPin(false);
852 }
853
854 /* Enable the timer and RX shifter. */
855 FLEXIO_MCULCD_SetSingleBeatReadConfig(base);
856
857 /* If data bus width is 8. */
858 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
859 for (i = 0; i < (size - 1U); i++)
860 {
861 /* Wait for shifter buffer full. */
862 while (0U == ((1UL << base->rxShifterEndIndex) & FLEXIO_GetShifterStatusFlags(flexioBase)))
863 {
864 }
865
866 data8Bit[i] = (uint8_t)flexioBase->SHIFTBUFBYS[base->rxShifterEndIndex];
867 }
868 #else
869 /* Data bus width is 16. */
870 size /= 2U;
871
872 for (i = 0; i < (size - 1U); i++)
873 {
874 /* Wait for shifter buffer full. */
875 while (0U == ((1UL << base->rxShifterEndIndex) & FLEXIO_GetShifterStatusFlags(flexioBase)))
876 {
877 }
878
879 data16Bit[i] = (uint16_t)flexioBase->SHIFTBUFHWS[base->rxShifterEndIndex];
880 }
881 #endif
882
883 /* Wait for shifter buffer full. */
884 while (0U == ((1UL << base->rxShifterEndIndex) & FLEXIO_GetShifterStatusFlags(flexioBase)))
885 {
886 }
887
888 /* Stop the timer and disable the RX shifter. */
889 FLEXIO_MCULCD_ClearSingleBeatReadConfig(base);
890
891 /* Read out the last data. */
892 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
893 data8Bit[i] = (uint8_t)flexioBase->SHIFTBUFBYS[base->rxShifterEndIndex];
894 #else
895 data16Bit[i] = (uint16_t)flexioBase->SHIFTBUFHWS[base->rxShifterEndIndex];
896 #endif
897 }
898
899 /*!
900 * brief Send the same value many times in blocking way.
901 *
902 * This function sends the same value many times. It could be used to clear the
903 * LCD screen. If the data bus width is 8, this function will send LSB 8 bits of
904 * p sameValue for p size times. If the data bus is 16, this function will send
905 * LSB 16 bits of p sameValue for p size / 2 times.
906 *
907 * param base Pointer to the FLEXIO_MCULCD_Type structure.
908 * param sameValue The same value to send.
909 * param size How many bytes to send.
910 */
FLEXIO_MCULCD_WriteSameValueBlocking(FLEXIO_MCULCD_Type * base,uint32_t sameValue,size_t size)911 void FLEXIO_MCULCD_WriteSameValueBlocking(FLEXIO_MCULCD_Type *base, uint32_t sameValue, size_t size)
912 {
913 assert(size > 0U);
914
915 uint32_t i;
916 FLEXIO_Type *flexioBase = base->flexioBase;
917
918 #if (16 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
919 size /= 2U;
920 #endif
921
922 /* Assert the RS pin. */
923 base->setRSPin(true);
924 /* For 6800, de-assert the RDWR pin. */
925 if (kFLEXIO_MCULCD_6800 == base->busType)
926 {
927 base->setRDWRPin(false);
928 }
929
930 /* Configure the timer and TX shifter. */
931 FLEXIO_MCULCD_SetSingleBeatWriteConfig(base);
932
933 for (i = 0; i < size; i++)
934 {
935 flexioBase->SHIFTBUF[base->txShifterStartIndex] = sameValue;
936
937 /* Wait for the data send out. */
938 while (0U == ((1UL << base->timerIndex) & flexioBase->TIMSTAT))
939 {
940 }
941
942 /* Clear the timer stat. */
943 flexioBase->TIMSTAT = 1UL << base->timerIndex;
944 }
945
946 /* Stop the timer and TX shifter. */
947 FLEXIO_MCULCD_ClearSingleBeatWriteConfig(base);
948 }
949
950 /*!
951 * brief Performs a polling transfer.
952 *
953 * note The API does not return until the transfer finished.
954 *
955 * param base pointer to FLEXIO_MCULCD_Type structure.
956 * param xfer pointer to flexio_mculcd_transfer_t structure.
957 */
FLEXIO_MCULCD_TransferBlocking(FLEXIO_MCULCD_Type * base,flexio_mculcd_transfer_t * xfer)958 void FLEXIO_MCULCD_TransferBlocking(FLEXIO_MCULCD_Type *base, flexio_mculcd_transfer_t *xfer)
959 {
960 FLEXIO_MCULCD_StartTransfer(base);
961
962 FLEXIO_MCULCD_WriteCommandBlocking(base, xfer->command);
963
964 if (xfer->dataSize > 0U)
965 {
966 if (kFLEXIO_MCULCD_ReadArray == xfer->mode)
967 {
968 FLEXIO_MCULCD_ReadDataArrayBlocking(base, (uint8_t *)(xfer->dataAddrOrSameValue), xfer->dataSize);
969 }
970 else if (kFLEXIO_MCULCD_WriteArray == xfer->mode)
971 {
972 FLEXIO_MCULCD_WriteDataArrayBlocking(base, (uint8_t *)(xfer->dataAddrOrSameValue), xfer->dataSize);
973 }
974 else
975 {
976 FLEXIO_MCULCD_WriteSameValueBlocking(base, xfer->dataAddrOrSameValue, xfer->dataSize);
977 }
978 }
979
980 FLEXIO_MCULCD_StopTransfer(base);
981 }
982
983 /*!
984 * brief Initializes the FlexIO MCULCD handle, which is used in transactional
985 * functions.
986 *
987 * param base Pointer to the FLEXIO_MCULCD_Type structure.
988 * param handle Pointer to the flexio_mculcd_handle_t structure to store the
989 * transfer state.
990 * param callback The callback function.
991 * param userData The parameter of the callback function.
992 * retval kStatus_Success Successfully create the handle.
993 * retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
994 */
FLEXIO_MCULCD_TransferCreateHandle(FLEXIO_MCULCD_Type * base,flexio_mculcd_handle_t * handle,flexio_mculcd_transfer_callback_t callback,void * userData)995 status_t FLEXIO_MCULCD_TransferCreateHandle(FLEXIO_MCULCD_Type *base,
996 flexio_mculcd_handle_t *handle,
997 flexio_mculcd_transfer_callback_t callback,
998 void *userData)
999 {
1000 assert(NULL != handle);
1001
1002 IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
1003
1004 /* Zero the handle. */
1005 (void)memset(handle, 0, sizeof(*handle));
1006
1007 handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
1008
1009 /* Register callback and userData. */
1010 handle->completionCallback = callback;
1011 handle->userData = userData;
1012
1013 /* Enable interrupt in NVIC. */
1014 (void)EnableIRQ(flexio_irqs[FLEXIO_GetInstance(base->flexioBase)]);
1015
1016 /* Save the context in global variables to support the double weak mechanism.
1017 */
1018 return FLEXIO_RegisterHandleIRQ(base, handle, FLEXIO_MCULCD_TransferHandleIRQ);
1019 }
1020
1021 /*!
1022 * brief Transfer data using IRQ.
1023 *
1024 * This function sends data using IRQ. This is a non-blocking function, which
1025 * returns right away. When all data is sent out/received, the callback
1026 * function is called.
1027 *
1028 * param base Pointer to the FLEXIO_MCULCD_Type structure.
1029 * param handle Pointer to the flexio_mculcd_handle_t structure to store the
1030 * transfer state.
1031 * param xfer FlexIO MCULCD transfer structure. See #flexio_mculcd_transfer_t.
1032 * retval kStatus_Success Successfully start a transfer.
1033 * retval kStatus_InvalidArgument Input argument is invalid.
1034 * retval kStatus_FLEXIO_MCULCD_Busy MCULCD is busy with another transfer.
1035 */
FLEXIO_MCULCD_TransferNonBlocking(FLEXIO_MCULCD_Type * base,flexio_mculcd_handle_t * handle,flexio_mculcd_transfer_t * xfer)1036 status_t FLEXIO_MCULCD_TransferNonBlocking(FLEXIO_MCULCD_Type *base,
1037 flexio_mculcd_handle_t *handle,
1038 flexio_mculcd_transfer_t *xfer)
1039 {
1040 /* If previous transfer is in progress. */
1041 if ((uint32_t)kFLEXIO_MCULCD_StateIdle != handle->state)
1042 {
1043 return kStatus_FLEXIO_MCULCD_Busy;
1044 }
1045
1046 /* Set the state in handle. */
1047 if (kFLEXIO_MCULCD_ReadArray == xfer->mode)
1048 {
1049 handle->state = (uint32_t)kFLEXIO_MCULCD_StateReadArray;
1050 }
1051 else if (kFLEXIO_MCULCD_WriteArray == xfer->mode)
1052 {
1053 handle->state = (uint32_t)kFLEXIO_MCULCD_StateWriteArray;
1054 }
1055 else
1056 {
1057 handle->state = (uint32_t)kFLEXIO_MCULCD_StateWriteSameValue;
1058 }
1059
1060 /* Assert the nCS. */
1061 FLEXIO_MCULCD_StartTransfer(base);
1062
1063 /* Send the command. */
1064 FLEXIO_MCULCD_WriteCommandBlocking(base, xfer->command);
1065
1066 /* If transfer count is 0 (only to send command), return directly. */
1067 if (0U == xfer->dataSize)
1068 {
1069 handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
1070
1071 /* De-assert the nCS. */
1072 FLEXIO_MCULCD_StopTransfer(base);
1073
1074 if (NULL != handle->completionCallback)
1075 {
1076 handle->completionCallback(base, handle, kStatus_FLEXIO_MCULCD_Idle, handle->userData);
1077 }
1078 }
1079 else
1080 {
1081 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
1082 handle->dataCount = xfer->dataSize;
1083 #else
1084 handle->dataCount = xfer->dataSize / 2U;
1085 #endif
1086
1087 handle->remainingCount = handle->dataCount;
1088
1089 handle->dataAddrOrSameValue = xfer->dataAddrOrSameValue;
1090
1091 /* Enable interrupt. */
1092 if (kFLEXIO_MCULCD_ReadArray == xfer->mode)
1093 {
1094 /* For 6800, assert the RDWR pin. */
1095 if (kFLEXIO_MCULCD_6800 == base->busType)
1096 {
1097 base->setRDWRPin(true);
1098 }
1099 FLEXIO_MCULCD_SetSingleBeatReadConfig(base);
1100 FLEXIO_MCULCD_EnableInterrupts(base, (uint32_t)kFLEXIO_MCULCD_RxFullInterruptEnable);
1101 }
1102 else
1103 {
1104 /* For 6800, de-assert the RDWR pin. */
1105 if (kFLEXIO_MCULCD_6800 == base->busType)
1106 {
1107 base->setRDWRPin(false);
1108 }
1109 FLEXIO_MCULCD_SetSingleBeatWriteConfig(base);
1110 FLEXIO_MCULCD_EnableInterrupts(base, (uint32_t)kFLEXIO_MCULCD_TxEmptyInterruptEnable);
1111 }
1112 }
1113
1114 return kStatus_Success;
1115 }
1116
1117 /*!
1118 * brief Aborts the data transfer, which used IRQ.
1119 *
1120 * param base Pointer to the FLEXIO_MCULCD_Type structure.
1121 * param handle Pointer to the flexio_mculcd_handle_t structure to store the
1122 * transfer state.
1123 */
FLEXIO_MCULCD_TransferAbort(FLEXIO_MCULCD_Type * base,flexio_mculcd_handle_t * handle)1124 void FLEXIO_MCULCD_TransferAbort(FLEXIO_MCULCD_Type *base, flexio_mculcd_handle_t *handle)
1125 {
1126 /* If no transfer in process, return directly. */
1127 if ((uint32_t)kFLEXIO_MCULCD_StateIdle == handle->state)
1128 {
1129 return;
1130 }
1131
1132 /* Disable the interrupt. */
1133 FLEXIO_MCULCD_DisableInterrupts(
1134 base, (uint32_t)kFLEXIO_MCULCD_RxFullInterruptEnable | (uint32_t)kFLEXIO_MCULCD_TxEmptyInterruptEnable);
1135
1136 if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == handle->state)
1137 {
1138 /* Stop the timer and disable the RX shifter. */
1139 FLEXIO_MCULCD_ClearSingleBeatReadConfig(base);
1140 }
1141 else
1142 {
1143 /* Stop the timer and disable the TX shifter. */
1144 FLEXIO_MCULCD_ClearSingleBeatWriteConfig(base);
1145 }
1146
1147 /* Clean the flags. */
1148 FLEXIO_MCULCD_ClearStatusFlags(base, (uint32_t)kFLEXIO_MCULCD_TxEmptyFlag | (uint32_t)kFLEXIO_MCULCD_RxFullFlag);
1149
1150 /* De-assert the nCS. */
1151 FLEXIO_MCULCD_StopTransfer(base);
1152
1153 handle->dataCount = 0;
1154 handle->remainingCount = 0;
1155 handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
1156 }
1157
1158 /*!
1159 * brief Gets the data transfer status which used IRQ.
1160 *
1161 * param base Pointer to the FLEXIO_MCULCD_Type structure.
1162 * param handle Pointer to the flexio_mculcd_handle_t structure to store the
1163 * transfer state.
1164 * param count How many bytes transferred so far by the non-blocking transaction.
1165 * retval kStatus_Success Get the transferred count Successfully.
1166 * retval kStatus_NoTransferInProgress No transfer in process.
1167 */
FLEXIO_MCULCD_TransferGetCount(FLEXIO_MCULCD_Type * base,flexio_mculcd_handle_t * handle,size_t * count)1168 status_t FLEXIO_MCULCD_TransferGetCount(FLEXIO_MCULCD_Type *base, flexio_mculcd_handle_t *handle, size_t *count)
1169 {
1170 assert(NULL != count);
1171
1172 if ((uint32_t)kFLEXIO_MCULCD_StateIdle == handle->state)
1173 {
1174 return kStatus_NoTransferInProgress;
1175 }
1176
1177 *count = handle->dataCount - handle->remainingCount;
1178
1179 #if (16 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
1180 *count *= 2U;
1181 #endif
1182
1183 return kStatus_Success;
1184 }
1185
1186 /*!
1187 * brief FlexIO MCULCD IRQ handler function.
1188 *
1189 * param base Pointer to the FLEXIO_MCULCD_Type structure.
1190 * param handle Pointer to the flexio_mculcd_handle_t structure to store the
1191 * transfer state.
1192 */
FLEXIO_MCULCD_TransferHandleIRQ(void * base,void * handle)1193 void FLEXIO_MCULCD_TransferHandleIRQ(void *base, void *handle)
1194 {
1195 FLEXIO_MCULCD_Type *flexioLcdMcuBase = (FLEXIO_MCULCD_Type *)base;
1196 flexio_mculcd_handle_t *flexioLcdMcuHandle = (flexio_mculcd_handle_t *)handle;
1197 uint32_t statusFlags = FLEXIO_MCULCD_GetStatusFlags(flexioLcdMcuBase);
1198 uint32_t data;
1199
1200 if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == flexioLcdMcuHandle->state)
1201 {
1202 /* Handle the reading process. */
1203 while ((0U != ((uint32_t)kFLEXIO_MCULCD_RxFullFlag & statusFlags)) && (flexioLcdMcuHandle->remainingCount > 0U))
1204 {
1205 if (1U == flexioLcdMcuHandle->remainingCount)
1206 {
1207 /* If this is the last data, stop the RX shifter and timer. */
1208 FLEXIO_MCULCD_DisableInterrupts(flexioLcdMcuBase, (uint32_t)kFLEXIO_MCULCD_RxFullInterruptEnable);
1209 FLEXIO_MCULCD_ClearSingleBeatReadConfig(flexioLcdMcuBase);
1210 FLEXIO_MCULCD_StopTransfer(flexioLcdMcuBase);
1211 }
1212
1213 /* Read out the data. */
1214 data = FLEXIO_MCULCD_ReadData(flexioLcdMcuBase);
1215
1216 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
1217 *(uint8_t *)(flexioLcdMcuHandle->dataAddrOrSameValue) = (uint8_t)data;
1218 flexioLcdMcuHandle->dataAddrOrSameValue++;
1219 #else
1220 *(uint16_t *)(flexioLcdMcuHandle->dataAddrOrSameValue) = (uint16_t)data;
1221 flexioLcdMcuHandle->dataAddrOrSameValue += 2U;
1222 #endif
1223
1224 flexioLcdMcuHandle->remainingCount--;
1225
1226 /* Transfer finished, call the callback. */
1227 if (0U == flexioLcdMcuHandle->remainingCount)
1228 {
1229 flexioLcdMcuHandle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
1230
1231 if (NULL != flexioLcdMcuHandle->completionCallback)
1232 {
1233 flexioLcdMcuHandle->completionCallback(flexioLcdMcuBase, flexioLcdMcuHandle,
1234 kStatus_FLEXIO_MCULCD_Idle, flexioLcdMcuHandle->userData);
1235 }
1236 }
1237
1238 /* Is the shifter buffer ready to send the next data? */
1239 statusFlags = FLEXIO_MCULCD_GetStatusFlags(flexioLcdMcuBase);
1240 }
1241 }
1242 else
1243 {
1244 /* Handle the writing process. */
1245 while ((0U != ((uint32_t)kFLEXIO_MCULCD_TxEmptyFlag & statusFlags)) &&
1246 (flexioLcdMcuHandle->remainingCount > 0U))
1247 {
1248 /* Send the data. */
1249 if ((uint32_t)kFLEXIO_MCULCD_StateWriteSameValue == flexioLcdMcuHandle->state)
1250 {
1251 data = flexioLcdMcuHandle->dataAddrOrSameValue;
1252 }
1253 else
1254 {
1255 #if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
1256 data = *(uint8_t *)(flexioLcdMcuHandle->dataAddrOrSameValue);
1257 flexioLcdMcuHandle->dataAddrOrSameValue++;
1258 #else
1259 data = *(uint16_t *)(flexioLcdMcuHandle->dataAddrOrSameValue);
1260 flexioLcdMcuHandle->dataAddrOrSameValue += 2U;
1261 #endif
1262 }
1263
1264 /* If this is the last data to send, delay to wait for the data shift out. */
1265 if (1U == flexioLcdMcuHandle->remainingCount)
1266 {
1267 FLEXIO_MCULCD_DisableInterrupts(flexioLcdMcuBase, (uint32_t)kFLEXIO_MCULCD_TxEmptyInterruptEnable);
1268
1269 /* Write the last data. */
1270 FLEXIO_MCULCD_WriteData(flexioLcdMcuBase, data);
1271
1272 /* Wait for the last data send finished. */
1273 FLEXIO_MCULCD_WaitTransmitComplete();
1274 flexioLcdMcuHandle->remainingCount = 0;
1275
1276 FLEXIO_MCULCD_ClearSingleBeatWriteConfig(flexioLcdMcuBase);
1277 FLEXIO_MCULCD_StopTransfer(flexioLcdMcuBase);
1278 flexioLcdMcuHandle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
1279
1280 if (NULL != flexioLcdMcuHandle->completionCallback)
1281 {
1282 flexioLcdMcuHandle->completionCallback(flexioLcdMcuBase, flexioLcdMcuHandle,
1283 kStatus_FLEXIO_MCULCD_Idle, flexioLcdMcuHandle->userData);
1284 }
1285 }
1286 else
1287 {
1288 FLEXIO_MCULCD_WriteData(flexioLcdMcuBase, data);
1289 flexioLcdMcuHandle->remainingCount--;
1290 }
1291 /* Is the shifter buffer ready to send the next data? */
1292 statusFlags = FLEXIO_MCULCD_GetStatusFlags(flexioLcdMcuBase);
1293 }
1294 }
1295 }
1296