am_hal_uart.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. //*****************************************************************************
  2. //
  3. // am_hal_uart.c
  4. //! @file
  5. //!
  6. //! @brief Functions for interfacing with the UART.
  7. //!
  8. //! @addtogroup uart2 UART
  9. //! @ingroup apollo2hal
  10. //! @{
  11. //
  12. //*****************************************************************************
  13. //*****************************************************************************
  14. //
  15. // Copyright (c) 2017, Ambiq Micro
  16. // All rights reserved.
  17. //
  18. // Redistribution and use in source and binary forms, with or without
  19. // modification, are permitted provided that the following conditions are met:
  20. //
  21. // 1. Redistributions of source code must retain the above copyright notice,
  22. // this list of conditions and the following disclaimer.
  23. //
  24. // 2. Redistributions in binary form must reproduce the above copyright
  25. // notice, this list of conditions and the following disclaimer in the
  26. // documentation and/or other materials provided with the distribution.
  27. //
  28. // 3. Neither the name of the copyright holder nor the names of its
  29. // contributors may be used to endorse or promote products derived from this
  30. // software without specific prior written permission.
  31. //
  32. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  33. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  36. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  37. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  38. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  39. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  40. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42. // POSSIBILITY OF SUCH DAMAGE.
  43. //
  44. // This is part of revision 1.2.11 of the AmbiqSuite Development Package.
  45. //
  46. //*****************************************************************************
  47. #include <stdint.h>
  48. #include <stdbool.h>
  49. #include "am_mcu_apollo.h"
  50. //*****************************************************************************
  51. //
  52. // Transmit and receive queue pointers for each UART module.
  53. //
  54. //*****************************************************************************
  55. am_hal_queue_t g_psTxQueue[AM_REG_UART_NUM_MODULES];
  56. am_hal_queue_t g_psRxQueue[AM_REG_UART_NUM_MODULES];
  57. //*****************************************************************************
  58. //
  59. // Power tracking structure
  60. //
  61. //*****************************************************************************
  62. am_hal_uart_pwrsave_t am_hal_uart_pwrsave[AM_REG_UART_NUM_MODULES];
  63. //*****************************************************************************
  64. //
  65. // Set Baud Rate based on the UART clock frequency.
  66. //
  67. //*****************************************************************************
  68. #define BAUDCLK (32)
  69. static void
  70. config_baudrate(uint32_t ui32Module, uint32_t ui32Baudrate, uint32_t ui32UartClkFreq)
  71. {
  72. uint64_t ui64FractionDivisorLong;
  73. uint64_t ui64IntermediateLong;
  74. uint32_t ui32IntegerDivisor;
  75. uint32_t ui32FractionDivisor;
  76. uint32_t ui32BaudClk;
  77. //
  78. // Calculate register values.
  79. //
  80. ui32BaudClk = BAUDCLK * ui32Baudrate;
  81. ui32IntegerDivisor = (uint32_t)(ui32UartClkFreq / ui32BaudClk);
  82. ui64IntermediateLong = (ui32UartClkFreq * 64) / ui32BaudClk;
  83. ui64FractionDivisorLong = ui64IntermediateLong - (ui32IntegerDivisor * 64);
  84. ui32FractionDivisor = (uint32_t)ui64FractionDivisorLong;
  85. //
  86. // Check the result.
  87. //
  88. am_hal_debug_assert_msg(ui32IntegerDivisor > 0, "Integer divisor MUST be greater than or equal to 1.");
  89. //
  90. // Write the UART regs.
  91. //
  92. AM_REGn(UART, ui32Module, IBRD) = ui32IntegerDivisor;
  93. AM_REGn(UART, ui32Module, IBRD) = ui32IntegerDivisor;
  94. AM_REGn(UART, ui32Module, FBRD) = ui32FractionDivisor;
  95. }
  96. //*****************************************************************************
  97. //
  98. //! @brief Set up the UART.
  99. //!
  100. //! @param psConfig pointer to a structure that holds the settings for the UART.
  101. //! @param ui32UartclkFreq is clock frequency that the UART is running at.
  102. //!
  103. //! This function should be used to perform the initial set-up of the UART.
  104. //!
  105. //! @return none.
  106. //
  107. //*****************************************************************************
  108. void
  109. am_hal_uart_config(uint32_t ui32Module, am_hal_uart_config_t *psConfig)
  110. {
  111. uint32_t ui32ConfigVal = 0;
  112. //
  113. // Configure the Baudrate.
  114. //
  115. config_baudrate(ui32Module, psConfig->ui32BaudRate, am_hal_clkgen_sysclk_get());
  116. //
  117. // OR in the Data bits.
  118. //
  119. ui32ConfigVal |= psConfig->ui32DataBits;
  120. //
  121. // OR in the Two Stop bit if used.
  122. //
  123. ui32ConfigVal |= psConfig->bTwoStopBits ? AM_REG_UART_LCRH_STP2_M : 0;
  124. //
  125. // OR in the Parity.
  126. //
  127. ui32ConfigVal |= psConfig->ui32Parity;
  128. //
  129. // Write config to Line control register.
  130. //
  131. AM_REGn(UART, ui32Module, LCRH) |= ui32ConfigVal;
  132. //
  133. // Write the flow control settings to the control register.
  134. //
  135. AM_REGn(UART, ui32Module, CR) |= psConfig->ui32FlowCtrl;
  136. //
  137. // Set the clock select field for 24MHz from the HFRC
  138. //
  139. AM_REGn(UART, ui32Module, CR) |= AM_REG_UART_CR_CLKSEL_24MHZ;
  140. }
  141. //*****************************************************************************
  142. //
  143. //! @brief Gets the status.
  144. //!
  145. //! This function returns the current status.
  146. //!
  147. //! @return current status.
  148. //
  149. //*****************************************************************************
  150. uint32_t
  151. am_hal_uart_status_get(uint32_t ui32Module)
  152. {
  153. //
  154. // Read and return the Status.
  155. //
  156. return AM_REGn(UART, ui32Module, RSR);
  157. }
  158. //*****************************************************************************
  159. //
  160. //! @brief Gets the interrupt status.
  161. //!
  162. //! @param bEnabledOnly - If true returns the enabled interrupt status.
  163. //!
  164. //! This function returns the masked or raw interrupt status.
  165. //!
  166. //! @return Bitwise representation of the current interrupt status.
  167. //!
  168. //! The return value will be the logical OR of one or more of the following
  169. //! values:
  170. //!
  171. //! AM_HAL_UART_INT_OVER_RUN
  172. //! AM_HAL_UART_INT_BREAK_ERR
  173. //! AM_HAL_UART_INT_PARITY_ERR
  174. //! AM_HAL_UART_INT_FRAME_ERR
  175. //! AM_HAL_UART_INT_RX_TMOUT
  176. //! AM_HAL_UART_INT_TX
  177. //! AM_REG_UART_IER_TXIM_M
  178. //! AM_HAL_UART_INT_RX
  179. //! AM_HAL_UART_INT_DSRM
  180. //! AM_HAL_UART_INT_DCDM
  181. //! AM_HAL_UART_INT_CTSM
  182. //! AM_HAL_UART_INT_RIM
  183. //
  184. //*****************************************************************************
  185. uint32_t
  186. am_hal_uart_int_status_get(uint32_t ui32Module, bool bEnabledOnly)
  187. {
  188. if (bEnabledOnly)
  189. {
  190. //
  191. // Read and return the Masked Interrupt Status.
  192. //
  193. return AM_REGn(UART, ui32Module, MIS);
  194. }
  195. else
  196. {
  197. //
  198. // Read and return the Raw Interrupt Status.
  199. //
  200. return AM_REGn(UART, ui32Module, IES);
  201. }
  202. }
  203. //*****************************************************************************
  204. //
  205. //! @brief Clears the desired interrupts.
  206. //!
  207. //! @param ui32Interrupt - Interrupt bits to clear.
  208. //!
  209. //! This function clears the desired interrupts.
  210. //!
  211. //! ui32Interrupt should be a logical or of the following:
  212. //!
  213. //! AM_HAL_UART_INT_OVER_RUN
  214. //! AM_HAL_UART_INT_BREAK_ERR
  215. //! AM_HAL_UART_INT_PARITY_ERR
  216. //! AM_HAL_UART_INT_FRAME_ERR
  217. //! AM_HAL_UART_INT_RX_TMOUT
  218. //! AM_HAL_UART_INT_TX
  219. //! AM_REG_UART_IER_TXIM_M
  220. //! AM_HAL_UART_INT_RX
  221. //! AM_HAL_UART_INT_DSRM
  222. //! AM_HAL_UART_INT_DCDM
  223. //! AM_HAL_UART_INT_CTSM
  224. //! AM_HAL_UART_INT_RIM
  225. //!
  226. //! @return None.
  227. //
  228. //*****************************************************************************
  229. void
  230. am_hal_uart_int_clear(uint32_t ui32Module, uint32_t ui32Interrupt)
  231. {
  232. //
  233. // Clear the bits.
  234. //
  235. AM_REGn(UART, ui32Module, IEC) = ui32Interrupt;
  236. }
  237. //*****************************************************************************
  238. //
  239. //! @brief Disables the desired interrupts.
  240. //!
  241. //! @param ui32Interrupt - Interrupt bits to disable.
  242. //!
  243. //! This function disables the desired interrupts.
  244. //!
  245. //! ui32Interrupt should be a logical or of the following:
  246. //!
  247. //! AM_HAL_UART_INT_OVER_RUN
  248. //! AM_HAL_UART_INT_BREAK_ERR
  249. //! AM_HAL_UART_INT_PARITY_ERR
  250. //! AM_HAL_UART_INT_FRAME_ERR
  251. //! AM_HAL_UART_INT_RX_TMOUT
  252. //! AM_HAL_UART_INT_TX
  253. //! AM_REG_UART_IER_TXIM_M
  254. //! AM_HAL_UART_INT_RX
  255. //! AM_HAL_UART_INT_DSRM
  256. //! AM_HAL_UART_INT_DCDM
  257. //! AM_HAL_UART_INT_CTSM
  258. //! AM_HAL_UART_INT_RIM
  259. //!
  260. //! @return None.
  261. //
  262. //*****************************************************************************
  263. void
  264. am_hal_uart_int_disable(uint32_t ui32Module, uint32_t ui32Interrupt)
  265. {
  266. //
  267. // Disable the bits.
  268. //
  269. AM_REGn(UART, ui32Module, IER) &= ~ui32Interrupt;
  270. }
  271. //*****************************************************************************
  272. //
  273. //! @brief Enables the desired interrupts.
  274. //!
  275. //! @param ui32Interrupt - Interrupt bits to enable.
  276. //!
  277. //! This function enables the desired interrupts.
  278. //!
  279. //! ui32Interrupt should be a logical or of the following:
  280. //!
  281. //! AM_HAL_UART_INT_OVER_RUN
  282. //! AM_HAL_UART_INT_BREAK_ERR
  283. //! AM_HAL_UART_INT_PARITY_ERR
  284. //! AM_HAL_UART_INT_FRAME_ERR
  285. //! AM_HAL_UART_INT_RX_TMOUT
  286. //! AM_HAL_UART_INT_TX
  287. //! AM_REG_UART_IER_TXIM_M
  288. //! AM_HAL_UART_INT_RX
  289. //! AM_HAL_UART_INT_DSRM
  290. //! AM_HAL_UART_INT_DCDM
  291. //! AM_HAL_UART_INT_CTSM
  292. //! AM_HAL_UART_INT_RIM
  293. //!
  294. //! @return None.
  295. //
  296. //*****************************************************************************
  297. void
  298. am_hal_uart_int_enable(uint32_t ui32Module, uint32_t ui32Interrupt)
  299. {
  300. //
  301. // Enable the interrupts.
  302. //
  303. AM_REGn(UART, ui32Module, IER) |= ui32Interrupt;
  304. }
  305. //*****************************************************************************
  306. //
  307. //! @brief Returns the enabled interrupts.
  308. //!
  309. //! This function return the enabled interrupts.
  310. //!
  311. //! @return the enabled interrupts. This will be a logical or of the following:
  312. //!
  313. //! AM_HAL_UART_INT_OVER_RUN
  314. //! AM_HAL_UART_INT_BREAK_ERR
  315. //! AM_HAL_UART_INT_PARITY_ERR
  316. //! AM_HAL_UART_INT_FRAME_ERR
  317. //! AM_HAL_UART_INT_RX_TMOUT
  318. //! AM_HAL_UART_INT_TX
  319. //! AM_REG_UART_IER_TXIM_M
  320. //! AM_HAL_UART_INT_RX
  321. //! AM_HAL_UART_INT_DSRM
  322. //! AM_HAL_UART_INT_DCDM
  323. //! AM_HAL_UART_INT_CTSM
  324. //! AM_HAL_UART_INT_RIM
  325. //!
  326. //! @return Returns the enabled interrupts.
  327. //
  328. //*****************************************************************************
  329. uint32_t
  330. am_hal_uart_int_enable_get(uint32_t ui32Module)
  331. {
  332. //
  333. // Return the enabled interrupts.
  334. //
  335. return AM_REGn(UART, ui32Module, IER);
  336. }
  337. //*****************************************************************************
  338. //
  339. //! @brief Enable the UART, RX, and TX.
  340. //!
  341. //! This function enables the UART, RX, and TX.
  342. //!
  343. //! @return None.
  344. //
  345. //*****************************************************************************
  346. void
  347. am_hal_uart_enable(uint32_t ui32Module)
  348. {
  349. //
  350. // Enable the UART, RX, and TX.
  351. //
  352. AM_REGan_SET(UART, ui32Module, CR, (AM_REG_UART_CR_UARTEN_M |
  353. AM_REG_UART_CR_RXE_M |
  354. AM_REG_UART_CR_TXE_M) );
  355. }
  356. //*****************************************************************************
  357. //
  358. //! @brief Disable the UART, RX, and TX.
  359. //!
  360. //! This function disables the UART, RX, and TX.
  361. //!
  362. //! @return None.
  363. //
  364. //*****************************************************************************
  365. void
  366. am_hal_uart_disable(uint32_t ui32Module)
  367. {
  368. //
  369. // Disable the UART.
  370. //
  371. AM_REGan_CLR(UART, ui32Module, CR, (AM_REG_UART_CR_UARTEN_M |
  372. AM_REG_UART_CR_RXE_M |
  373. AM_REG_UART_CR_TXE_M) );
  374. }
  375. //*****************************************************************************
  376. //
  377. //! @brief Enable the UART in the power control block.
  378. //!
  379. //! This function enables the UART device in the power control block.
  380. //!
  381. //! @return None.
  382. //
  383. //*****************************************************************************
  384. void
  385. am_hal_uart_pwrctrl_enable(uint32_t ui32Module)
  386. {
  387. //
  388. // Check to make sure we're acting on a real UART module.
  389. //
  390. am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
  391. "Trying to disable a UART module that doesn't exist");
  392. am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_UART0 << ui32Module);
  393. }
  394. //*****************************************************************************
  395. //
  396. //! @brief Disable the UART in the power control block.
  397. //!
  398. //! This function disables the UART device in the power control block.
  399. //!
  400. //! @return None.
  401. //
  402. //*****************************************************************************
  403. void
  404. am_hal_uart_pwrctrl_disable(uint32_t ui32Module)
  405. {
  406. //
  407. // Check to make sure we're acting on a real UART module.
  408. //
  409. am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
  410. "Trying to disable a UART module that doesn't exist");
  411. am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_UART0 << ui32Module);
  412. }
  413. //*****************************************************************************
  414. //
  415. //! @brief Enable the UART in the power control block.
  416. //!
  417. //! This function enables the UART device in the power control block.
  418. //!
  419. //! @return None.
  420. //
  421. //*****************************************************************************
  422. void
  423. am_hal_uart_power_on_restore(uint32_t ui32Module)
  424. {
  425. //
  426. // Check to make sure we're acting on a real UART module.
  427. //
  428. am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
  429. "Trying to enable a UART module that doesn't exist");
  430. //
  431. // Make sure this restore is a companion to a previous save call.
  432. //
  433. if ( am_hal_uart_pwrsave[ui32Module].bValid == 0 )
  434. {
  435. return;
  436. }
  437. //
  438. // Enable power to the selected UART
  439. //
  440. am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_UART0 << ui32Module);
  441. //
  442. // Restore the clock settings
  443. //
  444. am_hal_clkgen_uarten_set(ui32Module, am_hal_uart_pwrsave[ui32Module].UARTEN);
  445. //
  446. // Restore the configuration registers from the global variable in SRAM.
  447. //
  448. AM_REGn(UART, ui32Module, ILPR) = am_hal_uart_pwrsave[ui32Module].ILPR;
  449. AM_REGn(UART, ui32Module, IBRD) = am_hal_uart_pwrsave[ui32Module].IBRD;
  450. AM_REGn(UART, ui32Module, FBRD) = am_hal_uart_pwrsave[ui32Module].FBRD;
  451. AM_REGn(UART, ui32Module, LCRH) = am_hal_uart_pwrsave[ui32Module].LCRH;
  452. AM_REGn(UART, ui32Module, CR) = am_hal_uart_pwrsave[ui32Module].CR;
  453. AM_REGn(UART, ui32Module, IFLS) = am_hal_uart_pwrsave[ui32Module].IFLS;
  454. AM_REGn(UART, ui32Module, IER) = am_hal_uart_pwrsave[ui32Module].IER;
  455. //
  456. // Indicates we have restored the configuration.
  457. //
  458. am_hal_uart_pwrsave[ui32Module].bValid = 0;
  459. return;
  460. }
  461. //*****************************************************************************
  462. //
  463. //! @brief Disable the UART in the power control block.
  464. //!
  465. //! This function disables the UART device in the power control block.
  466. //!
  467. //! @return None.
  468. //
  469. //*****************************************************************************
  470. void
  471. am_hal_uart_power_off_save(uint32_t ui32Module)
  472. {
  473. //
  474. // Check to make sure we're acting on a real UART module.
  475. //
  476. am_hal_debug_assert_msg(ui32Module < AM_REG_UART_NUM_MODULES,
  477. "Trying to disable a UART module that doesn't exist");
  478. //
  479. // Save all of the configuration register information for the selected
  480. // UART.
  481. //
  482. am_hal_uart_pwrsave[ui32Module].ILPR = AM_REGn(UART, ui32Module, ILPR);
  483. am_hal_uart_pwrsave[ui32Module].IBRD = AM_REGn(UART, ui32Module, IBRD);
  484. am_hal_uart_pwrsave[ui32Module].FBRD = AM_REGn(UART, ui32Module, FBRD);
  485. am_hal_uart_pwrsave[ui32Module].LCRH = AM_REGn(UART, ui32Module, LCRH);
  486. am_hal_uart_pwrsave[ui32Module].CR = AM_REGn(UART, ui32Module, CR);
  487. am_hal_uart_pwrsave[ui32Module].IFLS = AM_REGn(UART, ui32Module, IFLS);
  488. am_hal_uart_pwrsave[ui32Module].IER = AM_REGn(UART, ui32Module, IER);
  489. //
  490. // Save the clock setting and disable power to the selected UART.
  491. // Save the current enable value.
  492. //
  493. am_hal_uart_pwrsave[ui32Module].UARTEN =
  494. (AM_REG(CLKGEN, UARTEN) & AM_HAL_CLKGEN_UARTEN_UARTENn_M(ui32Module)) >>
  495. AM_HAL_CLKGEN_UARTEN_UARTENn_S(ui32Module);
  496. //
  497. // Disable the UART.
  498. //
  499. am_hal_clkgen_uarten_set(ui32Module, AM_HAL_CLKGEN_UARTEN_DIS);
  500. //
  501. // Indicates we have a valid saved configuration.
  502. //
  503. am_hal_uart_pwrsave[ui32Module].bValid = 1;
  504. //
  505. // Disable power to the selected UART.
  506. //
  507. am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_UART0 << ui32Module);
  508. return;
  509. }
  510. //*****************************************************************************
  511. //
  512. //! @brief Enable the UART clock.
  513. //!
  514. //! This function enables the clock to the UART.
  515. //!
  516. //! @return None.
  517. //
  518. //*****************************************************************************
  519. void
  520. am_hal_uart_clock_enable(uint32_t ui32Module)
  521. {
  522. //
  523. // Set CLKGEN.UARTEN, clear the field then write the desired enable value
  524. // Valid enable values are DIS, EN, REDUCE_FREQ, EN_POWER_SAV.
  525. //
  526. am_hal_clkgen_uarten_set(ui32Module, AM_HAL_CLKGEN_UARTEN_EN);
  527. //
  528. // Enable the UART clock.
  529. //
  530. AM_REGn(UART, ui32Module, CR) |= AM_REG_UART_CR_CLKEN_M;
  531. //
  532. // Select default UART clock source
  533. //
  534. AM_REGn(UART, ui32Module, CR) |= AM_REG_UART_CR_CLKSEL_24MHZ;
  535. }
  536. //*****************************************************************************
  537. //
  538. //! @brief Disable the UART clock.
  539. //!
  540. //! This function disables the clock to the UART.
  541. //!
  542. //! @return None.
  543. //
  544. //*****************************************************************************
  545. void
  546. am_hal_uart_clock_disable(uint32_t ui32Module)
  547. {
  548. //
  549. // Disable the UART clock.
  550. //
  551. AM_REGn(UART, ui32Module, CR) &= ~AM_REG_UART_CR_CLKEN_M;
  552. //
  553. // Disable the UART clock in the CLKGEN module.
  554. //
  555. am_hal_clkgen_uarten_set(ui32Module, AM_HAL_CLKGEN_UARTEN_DIS);
  556. }
  557. //*****************************************************************************
  558. //
  559. //! @brief Set and enable the desired interrupt levels for the RX/TX fifo.
  560. //!
  561. //! @param ui32LvlCfg - Desired FIFO RX/TX levels.
  562. //!
  563. //! This function sets the desired interrupt levels for the RX/TX fifo and
  564. //! enables the use of transmit and receive FIFO buffers.
  565. //!
  566. //! Valid values for ui32LvlCfg are:
  567. //!
  568. //! AM_HAL_UART_TX_FIFO_1_8
  569. //! AM_HAL_UART_TX_FIFO_1_4
  570. //! AM_HAL_UART_TX_FIFO_1_2
  571. //! AM_HAL_UART_TX_FIFO_3_4
  572. //! AM_HAL_UART_TX_FIFO_7_8
  573. //!
  574. //! AM_HAL_UART_RX_FIFO_1_8
  575. //! AM_HAL_UART_RX_FIFO_1_4
  576. //! AM_HAL_UART_RX_FIFO_1_2
  577. //! AM_HAL_UART_RX_FIFO_3_4
  578. //! AM_HAL_UART_RX_FIFO_7_8
  579. //!
  580. //! @return None.
  581. //
  582. //*****************************************************************************
  583. void
  584. am_hal_uart_fifo_config(uint32_t ui32Module, uint32_t ui32LvlCfg)
  585. {
  586. //
  587. // Enable the use of FIFOs.
  588. //
  589. AM_REGn(UART, ui32Module, LCRH) |= AM_REG_UART_LCRH_FEN_M;
  590. //
  591. // Write the FIFO level register.
  592. //
  593. AM_REGn(UART, ui32Module, IFLS) = ui32LvlCfg;
  594. }
  595. //*****************************************************************************
  596. //
  597. //! @brief Return the UART Flags.
  598. //!
  599. //! This function reads and returns the UART flags.
  600. //!
  601. //! @return Returns the Flags.
  602. //
  603. //*****************************************************************************
  604. uint32_t
  605. am_hal_uart_flags_get(uint32_t ui32Module)
  606. {
  607. //
  608. // Read and return the Flags.
  609. //
  610. return AM_REGn(UART, ui32Module, FR);
  611. }
  612. //*****************************************************************************
  613. //
  614. //! @brief Outputs a single character using polling.
  615. //!
  616. //! @param cChar - Character to send.
  617. //!
  618. //! This function outputs a single character using polling.
  619. //!
  620. //! @return None.
  621. //
  622. //*****************************************************************************
  623. void
  624. am_hal_uart_char_transmit_polled(uint32_t ui32Module, char cChar)
  625. {
  626. //
  627. // Wait for space, i.e. TX FIFO EMPTY
  628. //
  629. while (AM_BFRn(UART, ui32Module, FR, TXFF));
  630. //
  631. // Write the char.
  632. //
  633. AM_REGn(UART, ui32Module, DR) = cChar;
  634. }
  635. //*****************************************************************************
  636. //
  637. //! @brief Outputs a zero terminated string using polling.
  638. //!
  639. //! @param pcString - Pointer to character string to send.
  640. //!
  641. //! This function outputs a zero terminated string using polling.
  642. //!
  643. //! @return None.
  644. //
  645. //*****************************************************************************
  646. void
  647. am_hal_uart_string_transmit_polled(uint32_t ui32Module, char *pcString)
  648. {
  649. while (*pcString)
  650. {
  651. //
  652. // Wait for space, i.e. TX FIFO EMPTY.
  653. //
  654. while (AM_BFRn(UART, ui32Module, FR, TXFF));
  655. //
  656. // Write the char.
  657. //
  658. AM_REGn(UART, ui32Module, DR) = *pcString++;
  659. }
  660. }
  661. //*****************************************************************************
  662. //
  663. //! @brief Receives a character using polling.
  664. //!
  665. //! @param pcChar - Pointer to character to store received char.
  666. //!
  667. //! This function receives a character using polling.
  668. //!
  669. //! @return None.
  670. //
  671. //*****************************************************************************
  672. void
  673. am_hal_uart_char_receive_polled(uint32_t ui32Module, char *pcChar)
  674. {
  675. //
  676. // Wait for data, i.e. RX FIFO NOT EMPTY.
  677. //
  678. while (AM_BFRn(UART, ui32Module, FR, RXFE));
  679. //
  680. // Save the char.
  681. //
  682. *pcChar = AM_REGn(UART, ui32Module, DR);
  683. }
  684. //*****************************************************************************
  685. //
  686. //! @brief Receives one line using polling.
  687. //!
  688. //! @param ui32MaxChars - Maximum number of characters to receive.
  689. //! @param pcChar - Pointer to character string to store received line.
  690. //!
  691. //! This function receives a line (delimited by '/n' or '/r') using polling.
  692. //! Line buffer is 0 (NULL) terminated.
  693. //!
  694. //! @return None.
  695. //
  696. //*****************************************************************************
  697. void
  698. am_hal_uart_line_receive_polled(uint32_t ui32Module,
  699. uint32_t ui32MaxChars,
  700. char *pcChar)
  701. {
  702. char cRecChar;
  703. uint32_t i;
  704. //
  705. // Loop until we receive ui32MaxChars or receive a line ending.
  706. //
  707. for (i = 0; i < (ui32MaxChars - 1); i++)
  708. {
  709. //
  710. // Get char.
  711. //
  712. am_hal_uart_char_receive_polled(ui32Module, &cRecChar);
  713. if ((cRecChar == '\n') || (cRecChar == '\r'))
  714. {
  715. //
  716. // Zero terminate the buffer.
  717. //
  718. *pcChar = 0;
  719. return;
  720. }
  721. *pcChar++ = cRecChar;
  722. }
  723. }
  724. //*****************************************************************************
  725. //
  726. //! @brief Initialize the buffered UART.
  727. //!
  728. //! @param pui8RxArray - Pointer to the RX buffer to fill.
  729. //! @param ui32RxSize - size of RX buffer.
  730. //! @param pui8TxArray - Pointer to the TX buffer to fill.
  731. //! @param ui32TxSize - size of TX buffer.
  732. //!
  733. //! This function initializes the buffered UART.
  734. //!
  735. //! @return None.
  736. //
  737. //*****************************************************************************
  738. void
  739. am_hal_uart_init_buffered(uint32_t ui32Module,
  740. uint8_t *pui8RxArray, uint32_t ui32RxSize,
  741. uint8_t *pui8TxArray, uint32_t ui32TxSize)
  742. {
  743. //
  744. // Enable the UART RX timeout interrupt.
  745. //
  746. AM_REGn(UART, ui32Module, IER) |= (AM_REG_UART_IES_RTRIS_M |
  747. AM_REG_UART_IES_TXRIS_M);
  748. //
  749. // Initialize the ring buffers.
  750. //
  751. am_hal_queue_init(&g_psTxQueue[ui32Module], pui8TxArray, 1, ui32TxSize);
  752. am_hal_queue_init(&g_psRxQueue[ui32Module], pui8RxArray, 1, ui32RxSize);
  753. }
  754. //*****************************************************************************
  755. //
  756. //! @brief Get the status of the buffered UART.
  757. //!
  758. //! @param pui32RxSize - Pointer to variable to return the Rx ring data size.
  759. //! @param pui32TxSize - Pointer to variable to return the Tx ring data size.
  760. //!
  761. //! This function gets the status of the buffered UART.
  762. //!
  763. //! @return None.
  764. //
  765. //*****************************************************************************
  766. void
  767. am_hal_uart_get_status_buffered(uint32_t ui32Module,
  768. uint32_t *pui32RxSize,
  769. uint32_t *pui32TxSize)
  770. {
  771. //
  772. // Return the current size of ring buffers.
  773. //
  774. if ( pui32RxSize )
  775. {
  776. *pui32RxSize = am_hal_queue_data_left(&g_psRxQueue[ui32Module]);
  777. }
  778. if ( pui32TxSize )
  779. {
  780. *pui32TxSize = am_hal_queue_data_left(&g_psTxQueue[ui32Module]);
  781. }
  782. }
  783. //*****************************************************************************
  784. //
  785. //! @brief Services the buffered UART.
  786. //!
  787. //! @param ui32Status is the contents of the UART interrupt status register.
  788. //!
  789. //! This function is responsible for servicing the buffered UART. Designed to
  790. //! be called from the UART interrupt handler.
  791. //!
  792. //! @return None
  793. //
  794. //*****************************************************************************
  795. void
  796. am_hal_uart_service_buffered(uint32_t ui32Module, uint32_t ui32Status)
  797. {
  798. uint8_t ui8Character = '\x00';
  799. uint32_t ui32FifoEntry = 0;
  800. //
  801. // Check to see if we have filled the Rx FIFO past the configured limit, or
  802. // if we have an 'old' character or two sitting in the FIFO.
  803. //
  804. if (ui32Status & (AM_REG_UART_IES_RXRIS_M | AM_REG_UART_IES_RTRIS_M))
  805. {
  806. //
  807. // While there's stuff in the RX fifo....
  808. //
  809. while (!AM_BFRn(UART, ui32Module, FR, RXFE))
  810. {
  811. //
  812. // Read each character out one by one, and add it to the ring
  813. // buffer. This will start losing bytes if the fifo ever overflows.
  814. //
  815. ui32FifoEntry = AM_REGn(UART, ui32Module , DR);
  816. //
  817. // As long as no error bits were set, we should push this byte to
  818. // the FIFO.
  819. //
  820. if ( (ui32FifoEntry & 0xF00) == 0 )
  821. {
  822. ui8Character = ui32FifoEntry & 0xFF;
  823. am_hal_queue_item_add(&g_psRxQueue[ui32Module], &ui8Character, 1);
  824. }
  825. }
  826. }
  827. //
  828. // Check to see if our TX buffer has been recently emptied. If so, we
  829. // should refill it from the TX ring buffer.
  830. //
  831. if (ui32Status & AM_REG_UART_IES_TXRIS_M)
  832. {
  833. //
  834. // Keep refilling until the fifo is full, or the ring buffer is empty,
  835. // whichever happens first.
  836. //
  837. while (am_hal_queue_data_left(&g_psTxQueue[ui32Module]) &&
  838. !AM_BFRn(UART, ui32Module, FR, TXFF))
  839. {
  840. am_hal_queue_item_get(&g_psTxQueue[ui32Module], &ui8Character, 1);
  841. AM_REGn(UART, ui32Module , DR) = ui8Character;
  842. }
  843. }
  844. }
  845. //*****************************************************************************
  846. //
  847. //! @brief Services the buffered UART.
  848. //!
  849. //! @param ui32Status is the contents of the UART interrupt status register.
  850. //!
  851. //! This function is responsible for servicing the buffered UART. Designed to
  852. //! be called from the UART interrupt handler.
  853. //!
  854. //! This function behaves exactly like am_hal_uart_service_buffered() \e except
  855. //! it does not completely empty the RX FIFO on every interrupt event. Instead,
  856. //! it will leave at least one byte behind until it receives a UART RX TIMEOUT
  857. //! interrupt. If you use this service routine, you can treat the RX TIMEOUT
  858. //! interrupt as a UART IDLE interrupt. Every time the UART RX line goes IDLE
  859. //! for 32 consecutive bit-times you WILL receive a UART RX TIMEOUT interrupt.
  860. //! This behavior is not guaranteed for am_hal_uart_service_buffered().
  861. //!
  862. //! @return None
  863. //
  864. //*****************************************************************************
  865. void
  866. am_hal_uart_service_buffered_timeout_save(uint32_t ui32Module, uint32_t ui32Status)
  867. {
  868. uint8_t ui8Character = '\x00';
  869. uint32_t ui32Count = 0;
  870. uint32_t ui32FifoEntry = 0;
  871. //
  872. // Check to see if we have filled the Rx FIFO past the configured limit, or
  873. // if we have an 'old' character or two sitting in the FIFO.
  874. //
  875. if (ui32Status & (AM_REG_UART_IES_RXRIS_M | AM_REG_UART_IES_RTRIS_M))
  876. {
  877. //
  878. // Check to see what our FIFO configuration setting is.
  879. //
  880. uint32_t ui32FifoThreshold;
  881. uint32_t ui32FifoCfg = AM_BFMn(UART, ui32Module, IFLS, RXIFLSEL);
  882. //
  883. // Compute the number of bytes for receive interrupt from the FIFO level
  884. // register.
  885. //
  886. switch(ui32FifoCfg)
  887. {
  888. case AM_HAL_UART_RX_FIFO_1_8: ui32FifoThreshold = 4; break;
  889. case AM_HAL_UART_RX_FIFO_1_4: ui32FifoThreshold = 8; break;
  890. case AM_HAL_UART_RX_FIFO_1_2: ui32FifoThreshold = 16; break;
  891. case AM_HAL_UART_RX_FIFO_3_4: ui32FifoThreshold = 24; break;
  892. case AM_HAL_UART_RX_FIFO_7_8: ui32FifoThreshold = 28; break;
  893. default:
  894. ui32FifoThreshold = 32;
  895. }
  896. //
  897. // While there's stuff in the RX fifo....
  898. //
  899. while (!AM_BFRn(UART, ui32Module, FR, RXFE))
  900. {
  901. //
  902. // Read each character out one by one, and add it to the ring
  903. // buffer. This will start losing bytes if the fifo ever overflows.
  904. //
  905. ui32FifoEntry = AM_REGn(UART, ui32Module, DR);
  906. //
  907. // As long as no error bits were set, we should push this byte to
  908. // the FIFO.
  909. //
  910. if ( (ui32FifoEntry & 0xF00) == 0)
  911. {
  912. ui8Character = ui32FifoEntry & 0xFF;
  913. am_hal_queue_item_add(&g_psRxQueue[ui32Module], &ui8Character, 1);
  914. }
  915. //
  916. // Leave one byte to trigger the RX timeout interrupt.
  917. //
  918. if ( ++ui32Count >= (ui32FifoThreshold - 1) )
  919. {
  920. break;
  921. }
  922. }
  923. }
  924. //
  925. // Check to see if our TX buffer has been recently emptied. If so, we
  926. // should refill it from the TX ring buffer.
  927. //
  928. if (ui32Status & AM_REG_UART_IES_TXRIS_M)
  929. {
  930. //
  931. // Keep refilling until the fifo is full, or the ring buffer is empty,
  932. // whichever happens first.
  933. //
  934. while (am_hal_queue_data_left(&g_psTxQueue[ui32Module]) &&
  935. !AM_BFRn(UART, ui32Module, FR, TXFF))
  936. {
  937. am_hal_queue_item_get(&g_psTxQueue[ui32Module], &ui8Character, 1);
  938. AM_REGn(UART, ui32Module , DR) = ui8Character;
  939. }
  940. }
  941. }
  942. //*****************************************************************************
  943. //
  944. //! @brief Puts a char in the buffer or directly to the fifo if available.
  945. //!
  946. //! @param cChar - Character to send.
  947. //!
  948. //! This function puts a character in the buffer or directly to the fifo.
  949. //!
  950. //! @return None.
  951. //
  952. //*****************************************************************************
  953. void
  954. am_hal_uart_char_transmit_buffered(uint32_t ui32Module, char cChar)
  955. {
  956. //
  957. // Check the status of the Tx fifo and the Tx ring buffer.
  958. //
  959. if (am_hal_queue_empty(&g_psTxQueue[ui32Module]) &&
  960. !AM_BFRn(UART, ui32Module, FR, TXFF))
  961. {
  962. //
  963. // If the fifo isn't full yet, and the ring buffer isn't being used,
  964. // just write the new character directly to the fifo.
  965. //
  966. AM_REGn(UART, ui32Module, DR) = cChar;
  967. }
  968. else
  969. {
  970. //
  971. // If we get here, either the fifo is full, or the ring buffer is
  972. // already in use. In either case, we need to use the ring buffer
  973. // to make sure that the transmitted data gets sent in the right
  974. // order. If the buffer is already full, we will simply lose this
  975. // byte.
  976. //
  977. am_hal_queue_item_add(&g_psTxQueue[ui32Module], &cChar, 1);
  978. }
  979. }
  980. //*****************************************************************************
  981. //
  982. //! @brief Puts a null terminaled string in the buffer or directly to the fifo.
  983. //!
  984. //! @param pcString - Pointer to buffer used for sending.
  985. //!
  986. //! This function puts a string in the buffer or directly to the fifo if there
  987. //! is space available.
  988. //!
  989. //! @return None.
  990. //
  991. //*****************************************************************************
  992. void
  993. am_hal_uart_string_transmit_buffered(uint32_t ui32Module, char *pcString)
  994. {
  995. //
  996. // Check the status of the Tx fifo and the Tx ring buffer.
  997. //
  998. while (*pcString)
  999. {
  1000. if (am_hal_queue_empty(&g_psTxQueue[ui32Module]) &&
  1001. !AM_BFRn(UART, ui32Module, FR, TXFF))
  1002. {
  1003. //
  1004. // If the fifo isn't full yet, and the ring buffer isn't being used,
  1005. // just write the new character directly to the fifo.
  1006. //
  1007. AM_REGn(UART, ui32Module, DR) = *pcString;
  1008. }
  1009. else
  1010. {
  1011. //
  1012. // If we get here, either the fifo is full, or the ring buffer is
  1013. // already in use. In either case, we need to use the ring buffer
  1014. // to make sure that the transmitted data gets sent in the right
  1015. // order. If the buffer is already full, we will simply lose this
  1016. // byte.
  1017. //
  1018. am_hal_queue_item_add(&g_psTxQueue[ui32Module], pcString, 1);
  1019. }
  1020. //
  1021. // Move the pointer to the next character.
  1022. //
  1023. pcString++;
  1024. }
  1025. }
  1026. //*****************************************************************************
  1027. //
  1028. //! @brief Returns n number of characters from the ring buffer or until empty.
  1029. //!
  1030. //! @param pcString - Pointer to buffer for putting received characters.
  1031. //! @param ui32MaxChars - Maximum number of characters to receive.
  1032. //!
  1033. //! This function puts a char string in the buffer.
  1034. //!
  1035. //! @return Returns the number of chars received.
  1036. //
  1037. //*****************************************************************************
  1038. uint32_t
  1039. am_hal_uart_char_receive_buffered(uint32_t ui32Module,
  1040. char *pcString,
  1041. uint32_t ui32MaxChars)
  1042. {
  1043. uint32_t ui32NumChars = 0;
  1044. //
  1045. // Loop until ui32MaxChars or until empty.
  1046. //
  1047. while (am_hal_queue_data_left(&g_psRxQueue[ui32Module]) && ui32MaxChars)
  1048. {
  1049. //
  1050. // Pull a char out of the ring buffer.
  1051. //
  1052. am_hal_queue_item_get(&g_psRxQueue[ui32Module], pcString, 1);
  1053. //
  1054. // Subtract from ui32MaxChars.
  1055. // Add to ui32NumChars.
  1056. // Move pointer in buffer.
  1057. //
  1058. ui32MaxChars--;
  1059. ui32NumChars++;
  1060. pcString++;
  1061. }
  1062. //
  1063. // return the number of chars received.
  1064. //
  1065. return ui32NumChars;
  1066. }
  1067. //*****************************************************************************
  1068. //
  1069. // End Doxygen group.
  1070. //! @}
  1071. //
  1072. //*****************************************************************************