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