fsl_flexio_mculcd.c 44 KB

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