em_usart.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. /***************************************************************************//**
  2. * @file
  3. * @brief Universal synchronous/asynchronous receiver/transmitter (USART/UART)
  4. * Peripheral API
  5. * @author Energy Micro AS
  6. * @version 3.0.0
  7. *******************************************************************************
  8. * @section License
  9. * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
  10. *******************************************************************************
  11. *
  12. * Permission is granted to anyone to use this software for any purpose,
  13. * including commercial applications, and to alter it and redistribute it
  14. * freely, subject to the following restrictions:
  15. *
  16. * 1. The origin of this software must not be misrepresented; you must not
  17. * claim that you wrote the original software.
  18. * 2. Altered source versions must be plainly marked as such, and must not be
  19. * misrepresented as being the original software.
  20. * 3. This notice may not be removed or altered from any source distribution.
  21. *
  22. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  23. * obligation to support this Software. Energy Micro AS is providing the
  24. * Software "AS IS", with no express or implied warranties of any kind,
  25. * including, but not limited to, any implied warranties of merchantability
  26. * or fitness for any particular purpose or warranties against infringement
  27. * of any proprietary rights of a third party.
  28. *
  29. * Energy Micro AS will not be liable for any consequential, incidental, or
  30. * special damages, or any other relief, or for any claim by any third party,
  31. * arising from your use of this Software.
  32. *
  33. ******************************************************************************/
  34. #include "em_usart.h"
  35. #include "em_cmu.h"
  36. #include "em_assert.h"
  37. /***************************************************************************//**
  38. * @addtogroup EM_Library
  39. * @{
  40. ******************************************************************************/
  41. /***************************************************************************//**
  42. * @addtogroup USART
  43. * @brief Universal Synchronous/Asynchronous Receiver/Transmitter
  44. * Peripheral API
  45. * @{
  46. ******************************************************************************/
  47. /*******************************************************************************
  48. ******************************* DEFINES ***********************************
  49. ******************************************************************************/
  50. /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
  51. /** Validation of USART register block pointer reference for assert statements. */
  52. #if (USART_COUNT == 1)
  53. #define USART_REF_VALID(ref) ((ref) == USART0)
  54. #elif (USART_COUNT == 2)
  55. #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1))
  56. #elif (USART_COUNT == 3)
  57. #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1) || \
  58. ((ref) == USART2))
  59. #elif (USART_COUNT == 4)
  60. #define USART_REF_VALID(ref) (((ref) == USART0) || ((ref) == USART1) || \
  61. ((ref) == USART2) || ((ref) == USART3))
  62. #else
  63. #error Undefined number of USARTs.
  64. #endif
  65. #define USART_IRDA_VALID(ref) ((ref) == USART0)
  66. #if defined(_EFM32_TINY_FAMILY)
  67. #define USART_I2S_VALID(ref) ((ref) == USART1)
  68. #endif
  69. #if defined(_EFM32_GIANT_FAMILY)
  70. #define USART_I2S_VALID(ref) (((ref) == USART1) || ((ref) == USART2))
  71. #endif
  72. #if (UART_COUNT == 1)
  73. #define UART_REF_VALID(ref) ((ref)==UART0)
  74. #elif (UART_COUNT == 2)
  75. #define UART_REF_VALID(ref) (((ref)==UART0) || ((ref)==UART1))
  76. #else
  77. #define UART_REF_VALID(ref) (0)
  78. #endif
  79. /** @endcond */
  80. /*******************************************************************************
  81. ************************** GLOBAL FUNCTIONS *******************************
  82. ******************************************************************************/
  83. /***************************************************************************//**
  84. * @brief
  85. * Configure USART/UART operating in asynchronous mode to use a given
  86. * baudrate (or as close as possible to specified baudrate).
  87. *
  88. * @param[in] usart
  89. * Pointer to USART/UART peripheral register block.
  90. *
  91. * @param[in] refFreq
  92. * USART/UART reference clock frequency in Hz that will be used. If set to 0,
  93. * the currently configured reference clock is assumed.
  94. *
  95. * @param[in] baudrate
  96. * Baudrate to try to achieve for USART/UART.
  97. *
  98. * @param[in] ovs
  99. * Oversampling to be used. Normal is 16x oversampling, but lower oversampling
  100. * may be used to achieve higher rates or better baudrate accuracy in some
  101. * cases. Notice that lower oversampling frequency makes channel more
  102. * vulnerable to bit faults during reception due to clock inaccuracies
  103. * compared to link partner.
  104. ******************************************************************************/
  105. void USART_BaudrateAsyncSet(USART_TypeDef *usart,
  106. uint32_t refFreq,
  107. uint32_t baudrate,
  108. USART_OVS_TypeDef ovs)
  109. {
  110. uint32_t clkdiv;
  111. uint32_t oversample;
  112. /* Inhibit divide by 0 */
  113. EFM_ASSERT(baudrate);
  114. /*
  115. * We want to use integer division to avoid forcing in float division
  116. * utils, and yet keep rounding effect errors to a minimum.
  117. *
  118. * CLKDIV in asynchronous mode is given by:
  119. *
  120. * CLKDIV = 256 * (fHFPERCLK/(oversample * br) - 1)
  121. * or
  122. * CLKDIV = (256 * fHFPERCLK)/(oversample * br) - 256
  123. *
  124. * The basic problem with integer division in the above formula is that
  125. * the dividend (256 * fHFPERCLK) may become higher than max 32 bit
  126. * integer. Yet, we want to evaluate dividend first before dividing in
  127. * order to get as small rounding effects as possible. We do not want
  128. * to make too harsh restrictions on max fHFPERCLK value either.
  129. *
  130. * One can possibly factorize 256 and oversample/br. However,
  131. * since the last 6 bits of CLKDIV are don't care, we can base our
  132. * integer arithmetic on the below formula
  133. *
  134. * CLKDIV / 64 = (4 * fHFPERCLK)/(oversample * br) - 4
  135. *
  136. * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
  137. * up to 1GHz without overflowing a 32 bit value!
  138. */
  139. /* HFPERCLK used to clock all USART/UART peripheral modules */
  140. if (!refFreq)
  141. {
  142. refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
  143. }
  144. /* Map oversampling */
  145. switch (ovs)
  146. {
  147. case USART_CTRL_OVS_X16:
  148. EFM_ASSERT(baudrate <= (refFreq / 16));
  149. oversample = 16;
  150. break;
  151. case USART_CTRL_OVS_X8:
  152. EFM_ASSERT(baudrate <= (refFreq / 8));
  153. oversample = 8;
  154. break;
  155. case USART_CTRL_OVS_X6:
  156. EFM_ASSERT(baudrate <= (refFreq / 6));
  157. oversample = 6;
  158. break;
  159. case USART_CTRL_OVS_X4:
  160. EFM_ASSERT(baudrate <= (refFreq / 4));
  161. oversample = 4;
  162. break;
  163. default:
  164. /* Invalid input */
  165. EFM_ASSERT(0);
  166. return;
  167. }
  168. /* Calculate and set CLKDIV with fractional bits */
  169. clkdiv = 4 * refFreq + (oversample * baudrate) / 2;
  170. clkdiv /= (oversample * baudrate);
  171. clkdiv -= 4;
  172. clkdiv *= 64;
  173. usart->CTRL &= ~_USART_CTRL_OVS_MASK;
  174. usart->CTRL |= ovs;
  175. usart->CLKDIV = clkdiv;
  176. }
  177. /***************************************************************************//**
  178. * @brief
  179. * Calculate baudrate for USART/UART given reference frequency, clock division
  180. * and oversampling rate (if async mode).
  181. *
  182. * @details
  183. * This function returns the baudrate that a USART/UART module will use if
  184. * configured with the given frequency, clock divisor and mode. Notice that
  185. * this function will not use actual HW configuration. It can be used
  186. * to determinate if a given configuration is sufficiently accurate for the
  187. * application.
  188. *
  189. * @param[in] refFreq
  190. * USART/UART HF peripheral frequency used.
  191. *
  192. * @param[in] clkdiv
  193. * Clock division factor to be used.
  194. *
  195. * @param[in] syncmode
  196. * @li true - synchronous mode operation.
  197. * @li false - asynchronous mode operation.
  198. *
  199. * @param[in] ovs
  200. * Oversampling used if asynchronous mode. Not used if @p syncmode is true.
  201. *
  202. * @return
  203. * Baudrate with given settings.
  204. ******************************************************************************/
  205. uint32_t USART_BaudrateCalc(uint32_t refFreq,
  206. uint32_t clkdiv,
  207. bool syncmode,
  208. USART_OVS_TypeDef ovs)
  209. {
  210. uint32_t oversample;
  211. uint32_t divisor;
  212. uint32_t factor;
  213. uint32_t remainder;
  214. uint32_t quotient;
  215. uint32_t br;
  216. /* Mask out unused bits */
  217. clkdiv &= _USART_CLKDIV_MASK;
  218. /* We want to use integer division to avoid forcing in float division */
  219. /* utils, and yet keep rounding effect errors to a minimum. */
  220. /* Baudrate calculation depends on if synchronous or asynchronous mode */
  221. if (syncmode)
  222. {
  223. /*
  224. * Baudrate is given by:
  225. *
  226. * br = fHFPERCLK/(2 * (1 + (CLKDIV / 256)))
  227. *
  228. * which can be rewritten to
  229. *
  230. * br = (128 * fHFPERCLK)/(256 + CLKDIV)
  231. */
  232. oversample = 1; /* Not used in sync mode, ie 1 */
  233. factor = 128;
  234. }
  235. else
  236. {
  237. /*
  238. * Baudrate in asynchronous mode is given by:
  239. *
  240. * br = fHFPERCLK/(oversample * (1 + (CLKDIV / 256)))
  241. *
  242. * which can be rewritten to
  243. *
  244. * br = (256 * fHFPERCLK)/(oversample * (256 + CLKDIV))
  245. *
  246. * First of all we can reduce the 256 factor of the dividend with
  247. * (part of) oversample part of the divisor.
  248. */
  249. switch (ovs)
  250. {
  251. case USART_CTRL_OVS_X16:
  252. oversample = 1;
  253. factor = 256 / 16;
  254. break;
  255. case USART_CTRL_OVS_X8:
  256. oversample = 1;
  257. factor = 256 / 8;
  258. break;
  259. case USART_CTRL_OVS_X6:
  260. oversample = 3;
  261. factor = 256 / 2;
  262. break;
  263. default:
  264. oversample = 1;
  265. factor = 256 / 4;
  266. break;
  267. }
  268. }
  269. /*
  270. * The basic problem with integer division in the above formula is that
  271. * the dividend (factor * fHFPERCLK) may become higher than max 32 bit
  272. * integer. Yet we want to evaluate dividend first before dividing in
  273. * order to get as small rounding effects as possible. We do not want
  274. * to make too harsh restrictions on max fHFPERCLK value either.
  275. *
  276. * For division a/b, we can write
  277. *
  278. * a = qb + r
  279. *
  280. * where q is the quotient and r is the remainder, both integers.
  281. *
  282. * The orignal baudrate formula can be rewritten as
  283. *
  284. * br = xa / b = x(qb + r)/b = xq + xr/b
  285. *
  286. * where x is 'factor', a is 'refFreq' and b is 'divisor', referring to
  287. * variable names.
  288. */
  289. /* Divisor will never exceed max 32 bit value since clkdiv <= 0x1fffc0 */
  290. /* and 'oversample' has been reduced to <= 3. */
  291. divisor = oversample * (256 + clkdiv);
  292. quotient = refFreq / divisor;
  293. remainder = refFreq % divisor;
  294. /* factor <= 128 and since divisor >= 256, the below cannot exceed max */
  295. /* 32 bit value. */
  296. br = factor * quotient;
  297. /*
  298. * factor <= 128 and remainder < (oversample*(256 + clkdiv)), which
  299. * means dividend (factor * remainder) worst case is
  300. * 128*(3 * (256 + 0x1fffc0)) = 0x30012000.
  301. */
  302. br += (factor * remainder) / divisor;
  303. return br;
  304. }
  305. /***************************************************************************//**
  306. * @brief
  307. * Get current baudrate for USART/UART.
  308. *
  309. * @details
  310. * This function returns the actual baudrate (not considering oscillator
  311. * inaccuracies) used by a USART/UART peripheral.
  312. *
  313. * @param[in] usart
  314. * Pointer to USART/UART peripheral register block.
  315. *
  316. * @return
  317. * Current baudrate.
  318. ******************************************************************************/
  319. uint32_t USART_BaudrateGet(USART_TypeDef *usart)
  320. {
  321. uint32_t freq;
  322. USART_OVS_TypeDef ovs;
  323. bool syncmode;
  324. if (usart->CTRL & USART_CTRL_SYNC)
  325. {
  326. syncmode = true;
  327. }
  328. else
  329. {
  330. syncmode = false;
  331. }
  332. /* HFPERCLK used to clock all USART/UART peripheral modules */
  333. freq = CMU_ClockFreqGet(cmuClock_HFPER);
  334. ovs = (USART_OVS_TypeDef)(usart->CTRL & _USART_CTRL_OVS_MASK);
  335. return USART_BaudrateCalc(freq, usart->CLKDIV, syncmode, ovs);
  336. }
  337. /***************************************************************************//**
  338. * @brief
  339. * Configure USART operating in synchronous mode to use a given baudrate
  340. * (or as close as possible to specified baudrate).
  341. *
  342. * @details
  343. * The configuration will be set to use a baudrate <= the specified baudrate
  344. * in order to ensure that the baudrate does not exceed the specified value.
  345. *
  346. * Fractional clock division is suppressed, although the HW design allows it.
  347. * It could cause half clock cycles to exceed specified limit, and thus
  348. * potentially violate specifications for the slave device. In some special
  349. * situations fractional clock division may be useful even in synchronous
  350. * mode, but in those cases it must be directly adjusted, possibly assisted
  351. * by USART_BaudrateCalc():
  352. *
  353. * @param[in] usart
  354. * Pointer to USART peripheral register block. (Cannot be used on UART
  355. * modules.)
  356. *
  357. * @param[in] refFreq
  358. * USART reference clock frequency in Hz that will be used. If set to 0,
  359. * the currently configured reference clock is assumed.
  360. *
  361. * @param[in] baudrate
  362. * Baudrate to try to achieve for USART.
  363. ******************************************************************************/
  364. void USART_BaudrateSyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate)
  365. {
  366. uint32_t clkdiv;
  367. /* Inhibit divide by 0 */
  368. EFM_ASSERT(baudrate);
  369. /*
  370. * We want to use integer division to avoid forcing in float division
  371. * utils, and yet keep rounding effect errors to a minimum.
  372. *
  373. * CLKDIV in synchronous mode is given by:
  374. *
  375. * CLKDIV = 256 * (fHFPERCLK/(2 * br) - 1)
  376. * or
  377. * CLKDIV = (256 * fHFPERCLK)/(2 * br) - 256 = (128 * fHFPERCLK)/br - 256
  378. *
  379. * The basic problem with integer division in the above formula is that
  380. * the dividend (128 * fHFPERCLK) may become higher than max 32 bit
  381. * integer. Yet, we want to evaluate dividend first before dividing in
  382. * order to get as small rounding effects as possible. We do not want
  383. * to make too harsh restrictions on max fHFPERCLK value either.
  384. *
  385. * One can possibly factorize 128 and br. However, since the last
  386. * 6 bits of CLKDIV are don't care, we can base our integer arithmetic
  387. * on the below formula without loosing any extra precision:
  388. *
  389. * CLKDIV / 64 = (2 * fHFPERCLK)/br - 4
  390. *
  391. * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
  392. * up to 2GHz without overflowing a 32 bit value!
  393. */
  394. /* HFPERCLK used to clock all USART/UART peripheral modules */
  395. if (!refFreq)
  396. {
  397. refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
  398. }
  399. /* Calculate and set CLKDIV with fractional bits */
  400. clkdiv = 2 * refFreq;
  401. clkdiv += baudrate - 1;
  402. clkdiv /= baudrate;
  403. clkdiv -= 4;
  404. clkdiv *= 64;
  405. /* Make sure we don't use fractional bits by rounding CLKDIV */
  406. /* up (and thus reducing baudrate, not increasing baudrate above */
  407. /* specified value). */
  408. clkdiv += 0xc0;
  409. clkdiv &= 0xffffff00;
  410. /* Verify that resulting clock divider is within limits */
  411. EFM_ASSERT(clkdiv <= _USART_CLKDIV_MASK);
  412. /* If EFM_ASSERT is not enabled, make sure we don't write to reserved bits */
  413. clkdiv &= _USART_CLKDIV_DIV_MASK;
  414. usart->CLKDIV = clkdiv;
  415. }
  416. /***************************************************************************//**
  417. * @brief
  418. * Enable/disable USART/UART receiver and/or transmitter.
  419. *
  420. * @details
  421. * Notice that this function does not do any configuration. Enabling should
  422. * normally be done after initialization is done (if not enabled as part
  423. * of init).
  424. *
  425. * @param[in] usart
  426. * Pointer to USART/UART peripheral register block.
  427. *
  428. * @param[in] enable
  429. * Select status for receiver/transmitter.
  430. ******************************************************************************/
  431. void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
  432. {
  433. uint32_t tmp;
  434. /* Make sure the module exists on the selected chip */
  435. EFM_ASSERT(USART_REF_VALID(usart)||(UART_REF_VALID(usart)));
  436. /* Disable as specified */
  437. tmp = ~((uint32_t)(enable));
  438. tmp &= _USART_CMD_RXEN_MASK | _USART_CMD_TXEN_MASK;
  439. usart->CMD = tmp << 1;
  440. /* Enable as specified */
  441. usart->CMD = (uint32_t)(enable);
  442. }
  443. /***************************************************************************//**
  444. * @brief
  445. * Init USART/UART for normal asynchronous mode.
  446. *
  447. * @details
  448. * This function will configure basic settings in order to operate in normal
  449. * asynchronous mode.
  450. *
  451. * Special control setup not covered by this function must be done after
  452. * using this function by direct modification of the CTRL register.
  453. *
  454. * Notice that pins used by the USART/UART module must be properly configured
  455. * by the user explicitly, in order for the USART/UART to work as intended.
  456. * (When configuring pins, one should remember to consider the sequence of
  457. * configuration, in order to avoid unintended pulses/glitches on output
  458. * pins.)
  459. *
  460. * @param[in] usart
  461. * Pointer to USART/UART peripheral register block.
  462. *
  463. * @param[in] init
  464. * Pointer to initialization structure used to configure basic async setup.
  465. ******************************************************************************/
  466. void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
  467. {
  468. /* Make sure the module exists on the selected chip */
  469. EFM_ASSERT(USART_REF_VALID(usart)||UART_REF_VALID(usart));
  470. /* Init USART registers to HW reset state. */
  471. USART_Reset(usart);
  472. #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
  473. /* Disable majority vote if specified. */
  474. if (init->mvdis)
  475. {
  476. usart->CTRL |= USART_CTRL_MVDIS;
  477. }
  478. /* Configure PRS input mode. */
  479. if (init->prsRxEnable)
  480. {
  481. usart->INPUT = (uint32_t)init->prsRxCh | USART_INPUT_RXPRS;
  482. }
  483. #endif
  484. /* Configure databits, stopbits and parity */
  485. usart->FRAME = (uint32_t)(init->databits) |
  486. (uint32_t)(init->stopbits) |
  487. (uint32_t)(init->parity);
  488. /* Configure baudrate */
  489. USART_BaudrateAsyncSet(usart, init->refFreq, init->baudrate, init->oversampling);
  490. /* Finally enable (as specified) */
  491. usart->CMD = (uint32_t)(init->enable);
  492. }
  493. /***************************************************************************//**
  494. * @brief
  495. * Init USART for synchronous mode.
  496. *
  497. * @details
  498. * This function will configure basic settings in order to operate in
  499. * synchronous mode.
  500. *
  501. * Special control setup not covered by this function must be done after
  502. * using this function by direct modification of the CTRL register.
  503. *
  504. * Notice that pins used by the USART module must be properly configured
  505. * by the user explicitly, in order for the USART to work as intended.
  506. * (When configuring pins, one should remember to consider the sequence of
  507. * configuration, in order to avoid unintended pulses/glitches on output
  508. * pins.)
  509. *
  510. * @param[in] usart
  511. * Pointer to USART peripheral register block. (UART does not support this
  512. * mode.)
  513. *
  514. * @param[in] init
  515. * Pointer to initialization structure used to configure basic async setup.
  516. ******************************************************************************/
  517. void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init)
  518. {
  519. /* Make sure the module exists on the selected chip */
  520. EFM_ASSERT(USART_REF_VALID(usart));
  521. /* Init USART registers to HW reset state. */
  522. USART_Reset(usart);
  523. /* Set bits for synchronous mode */
  524. usart->CTRL |= (USART_CTRL_SYNC) |
  525. ((uint32_t)init->clockMode) |
  526. (init->msbf ? USART_CTRL_MSBF : 0);
  527. #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
  528. usart->CTRL |= (init->prsRxEnable ? USART_INPUT_RXPRS : 0) |
  529. (init->autoTx ? USART_CTRL_AUTOTX : 0);
  530. #endif
  531. /* Configure databits, leave stopbits and parity at reset default (not used) */
  532. usart->FRAME = ((uint32_t)(init->databits)) |
  533. (USART_FRAME_STOPBITS_DEFAULT) |
  534. (USART_FRAME_PARITY_DEFAULT);
  535. /* Configure baudrate */
  536. USART_BaudrateSyncSet(usart, init->refFreq, init->baudrate);
  537. /* Finally enable (as specified) */
  538. if (init->master)
  539. {
  540. usart->CMD = USART_CMD_MASTEREN;
  541. }
  542. usart->CMD = (uint32_t)(init->enable);
  543. }
  544. /***************************************************************************//**
  545. * @brief
  546. * Init USART0 for asynchronous IrDA mode.
  547. *
  548. * @details
  549. * This function will configure basic settings in order to operate in
  550. * asynchronous IrDA mode.
  551. *
  552. * Special control setup not covered by this function must be done after
  553. * using this function by direct modification of the CTRL and IRCTRL
  554. * registers.
  555. *
  556. * Notice that pins used by the USART/UART module must be properly configured
  557. * by the user explicitly, in order for the USART/UART to work as intended.
  558. * (When configuring pins, one should remember to consider the sequence of
  559. * configuration, in order to avoid unintended pulses/glitches on output
  560. * pins.)
  561. *
  562. * @param[in] init
  563. * Pointer to initialization structure used to configure async IrDA setup.
  564. *
  565. * @note
  566. * This function only applies to USART0 as IrDA is not supported on the other
  567. * USART modules.
  568. *
  569. ******************************************************************************/
  570. void USART_InitIrDA(const USART_InitIrDA_TypeDef *init)
  571. {
  572. /* Init USART0 as async device */
  573. USART_InitAsync(USART0, &(init->async));
  574. /* Set IrDA modulation to RZI (return-to-zero-inverted) */
  575. USART0->CTRL |= USART_CTRL_TXINV;
  576. /* Invert Rx signal before demodulator if enabled */
  577. if (init->irRxInv)
  578. {
  579. USART0->CTRL |= USART_CTRL_RXINV;
  580. }
  581. /* Configure IrDA */
  582. USART0->IRCTRL |= (uint32_t)init->irPw |
  583. (uint32_t)init->irPrsSel |
  584. ((uint32_t)init->irFilt << _USART_IRCTRL_IRFILT_SHIFT) |
  585. ((uint32_t)init->irPrsEn << _USART_IRCTRL_IRPRSEN_SHIFT);
  586. /* Enable IrDA */
  587. USART0->IRCTRL |= USART_IRCTRL_IREN;
  588. }
  589. #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
  590. /***************************************************************************//**
  591. * @brief
  592. * Init USART for I2S mode.
  593. *
  594. * @details
  595. * This function will configure basic settings in order to operate in I2S
  596. * mode.
  597. *
  598. * Special control setup not covered by this function must be done after
  599. * using this function by direct modification of the CTRL and I2SCTRL
  600. * registers.
  601. *
  602. * Notice that pins used by the USART module must be properly configured
  603. * by the user explicitly, in order for the USART to work as intended.
  604. * (When configuring pins, one should remember to consider the sequence of
  605. * configuration, in order to avoid unintended pulses/glitches on output
  606. * pins.)
  607. *
  608. * @param[in] usart
  609. * Pointer to USART peripheral register block. (UART does not support this
  610. * mode.)
  611. *
  612. * @param[in] init
  613. * Pointer to initialization structure used to configure basic I2S setup.
  614. *
  615. * @note
  616. * This function does not apply to all USART's. Refer to chip manuals.
  617. *
  618. ******************************************************************************/
  619. void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init)
  620. {
  621. USART_Enable_TypeDef enable;
  622. /* Make sure the module exists on the selected chip */
  623. EFM_ASSERT(USART_I2S_VALID(usart));
  624. /* Override the enable setting. */
  625. enable = init->sync.enable;
  626. init->sync.enable = usartDisable;
  627. /* Init USART as a sync device. */
  628. USART_InitSync(usart, &init->sync);
  629. /* Configure and enable I2CCTRL register acording to selected mode. */
  630. usart->I2SCTRL = ((uint32_t)init->format) |
  631. ((uint32_t)init->justify) |
  632. (init->delay ? USART_I2SCTRL_DELAY : 0) |
  633. (init->dmaSplit ? USART_I2SCTRL_DMASPLIT : 0) |
  634. (init->mono ? USART_I2SCTRL_MONO : 0) |
  635. (USART_I2SCTRL_EN);
  636. if (enable != usartDisable)
  637. {
  638. USART_Enable(usart, enable);
  639. }
  640. }
  641. /***************************************************************************//**
  642. * @brief
  643. * Initialize automatic transmissions using PRS channel as trigger
  644. * @note
  645. * Initialize USART with USART_Init() before setting up PRS configuration
  646. *
  647. * @param[in] usart Pointer to USART to configure
  648. * @param[in] init Pointer to initialization structure
  649. ******************************************************************************/
  650. void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init)
  651. {
  652. uint32_t trigctrl;
  653. /* Clear values that will be reconfigured */
  654. trigctrl = usart->TRIGCTRL & ~(_USART_TRIGCTRL_RXTEN_MASK|
  655. _USART_TRIGCTRL_TXTEN_MASK|
  656. #if defined(_EFM32_GIANT_FAMILY)
  657. _USART_TRIGCTRL_AUTOTXTEN_MASK|
  658. #endif
  659. _USART_TRIGCTRL_TSEL_MASK);
  660. #if defined(_EFM32_GIANT_FAMILY)
  661. if(init->autoTxTriggerEnable)
  662. {
  663. trigctrl |= USART_TRIGCTRL_AUTOTXTEN;
  664. }
  665. #endif
  666. if(init->txTriggerEnable)
  667. {
  668. trigctrl |= USART_TRIGCTRL_TXTEN;
  669. }
  670. if(init->rxTriggerEnable)
  671. {
  672. trigctrl |= USART_TRIGCTRL_RXTEN;
  673. }
  674. trigctrl |= init->prsTriggerChannel;
  675. /* Enable new configuration */
  676. usart->TRIGCTRL = trigctrl;
  677. }
  678. #endif
  679. /***************************************************************************//**
  680. * @brief
  681. * Reset USART/UART to same state as after a HW reset.
  682. *
  683. * @param[in] usart
  684. * Pointer to USART/UART peripheral register block.
  685. ******************************************************************************/
  686. void USART_Reset(USART_TypeDef *usart)
  687. {
  688. /* Make sure the module exists on the selected chip */
  689. EFM_ASSERT(USART_REF_VALID(usart)||UART_REF_VALID(usart));
  690. /* Make sure disabled first, before resetting other registers */
  691. usart->CMD = USART_CMD_RXDIS | USART_CMD_TXDIS | USART_CMD_MASTERDIS |
  692. USART_CMD_RXBLOCKDIS | USART_CMD_TXTRIDIS | USART_CMD_CLEARTX | USART_CMD_CLEARRX;
  693. usart->CTRL = _USART_CTRL_RESETVALUE;
  694. usart->FRAME = _USART_FRAME_RESETVALUE;
  695. usart->TRIGCTRL = _USART_TRIGCTRL_RESETVALUE;
  696. usart->CLKDIV = _USART_CLKDIV_RESETVALUE;
  697. usart->IEN = _USART_IEN_RESETVALUE;
  698. usart->IFC = _USART_IFC_MASK;
  699. usart->ROUTE = _USART_ROUTE_RESETVALUE;
  700. if (USART_IRDA_VALID(usart))
  701. {
  702. usart->IRCTRL = _USART_IRCTRL_RESETVALUE;
  703. }
  704. #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
  705. usart->INPUT = _USART_INPUT_RESETVALUE;
  706. if (USART_I2S_VALID(usart))
  707. {
  708. usart->I2SCTRL = _USART_I2SCTRL_RESETVALUE;
  709. }
  710. #endif
  711. /* Do not reset route register, setting should be done independently */
  712. }
  713. /***************************************************************************//**
  714. * @brief
  715. * Receive one 4-8 bit frame, (or part of 10-16 bit frame).
  716. *
  717. * @details
  718. * This function is normally used to receive one frame when operating with
  719. * frame length 4-8 bits. Please refer to USART_RxExt() for reception of
  720. * 9 bit frames.
  721. *
  722. * Notice that possible parity/stop bits in asynchronous mode are not
  723. * considered part of specified frame bit length.
  724. *
  725. * @note
  726. * This function will stall if buffer is empty, until data is received.
  727. *
  728. * @param[in] usart
  729. * Pointer to USART/UART peripheral register block.
  730. *
  731. * @return
  732. * Data received.
  733. ******************************************************************************/
  734. uint8_t USART_Rx(USART_TypeDef *usart)
  735. {
  736. while (!(usart->STATUS & USART_STATUS_RXDATAV))
  737. ;
  738. return (uint8_t)(usart->RXDATA);
  739. }
  740. /***************************************************************************//**
  741. * @brief
  742. * Receive two 4-8 bit frames, or one 10-16 bit frame.
  743. *
  744. * @details
  745. * This function is normally used to receive one frame when operating with
  746. * frame length 10-16 bits. Please refer to USART_RxDoubleExt() for reception
  747. * of two 9 bit frames.
  748. *
  749. * Notice that possible parity/stop bits in asynchronous mode are not
  750. * considered part of specified frame bit length.
  751. *
  752. * @note
  753. * This function will stall if buffer is empty, until data is received.
  754. *
  755. * @param[in] usart
  756. * Pointer to USART/UART peripheral register block.
  757. *
  758. * @return
  759. * Data received.
  760. ******************************************************************************/
  761. uint16_t USART_RxDouble(USART_TypeDef *usart)
  762. {
  763. while (!(usart->STATUS & USART_STATUS_RXFULL))
  764. ;
  765. return (uint16_t)(usart->RXDOUBLE);
  766. }
  767. /***************************************************************************//**
  768. * @brief
  769. * Receive two 4-9 bit frames, or one 10-16 bit frame with extended
  770. * information.
  771. *
  772. * @details
  773. * This function is normally used to receive one frame when operating with
  774. * frame length 10-16 bits and additional RX status information is required.
  775. *
  776. * Notice that possible parity/stop bits in asynchronous mode are not
  777. * considered part of specified frame bit length.
  778. *
  779. * @note
  780. * This function will stall if buffer is empty, until data is received.
  781. *
  782. * @param[in] usart
  783. * Pointer to USART/UART peripheral register block.
  784. *
  785. * @return
  786. * Data received.
  787. ******************************************************************************/
  788. uint32_t USART_RxDoubleExt(USART_TypeDef *usart)
  789. {
  790. while (!(usart->STATUS & USART_STATUS_RXFULL))
  791. ;
  792. return usart->RXDOUBLEX;
  793. }
  794. /***************************************************************************//**
  795. * @brief
  796. * Receive one 4-9 bit frame, (or part of 10-16 bit frame) with extended
  797. * information.
  798. *
  799. * @details
  800. * This function is normally used to receive one frame when operating with
  801. * frame length 4-9 bits and additional RX status information is required.
  802. *
  803. * Notice that possible parity/stop bits in asynchronous mode are not
  804. * considered part of specified frame bit length.
  805. *
  806. * @note
  807. * This function will stall if buffer is empty, until data is received.
  808. *
  809. * @param[in] usart
  810. * Pointer to USART/UART peripheral register block.
  811. *
  812. * @return
  813. * Data received.
  814. ******************************************************************************/
  815. uint16_t USART_RxExt(USART_TypeDef *usart)
  816. {
  817. while (!(usart->STATUS & USART_STATUS_RXDATAV))
  818. ;
  819. return (uint16_t)(usart->RXDATAX);
  820. }
  821. /***************************************************************************//**
  822. * @brief
  823. * Transmit one 4-9 bit frame.
  824. *
  825. * @details
  826. * Depending on frame length configuration, 4-8 (least significant) bits from
  827. * @p data are transmitted. If frame length is 9, 8 bits are transmitted from
  828. * @p data and one bit as specified by CTRL register, BIT8DV field. Please
  829. * refer to USART_TxExt() for transmitting 9 bit frame with full control of
  830. * all 9 bits.
  831. *
  832. * Notice that possible parity/stop bits in asynchronous mode are not
  833. * considered part of specified frame bit length.
  834. *
  835. * @note
  836. * This function will stall if buffer is full, until buffer becomes available.
  837. *
  838. * @param[in] usart
  839. * Pointer to USART/UART peripheral register block.
  840. *
  841. * @param[in] data
  842. * Data to transmit. See details above for further info.
  843. ******************************************************************************/
  844. void USART_Tx(USART_TypeDef *usart, uint8_t data)
  845. {
  846. /* Check that transmit buffer is empty */
  847. while (!(usart->STATUS & USART_STATUS_TXBL));
  848. usart->TXDATA = (uint32_t)data;
  849. }
  850. /***************************************************************************//**
  851. * @brief
  852. * Transmit two 4-9 bit frames, or one 10-16 bit frame.
  853. *
  854. * @details
  855. * Depending on frame length configuration, 4-8 (least significant) bits from
  856. * each byte in @p data are transmitted. If frame length is 9, 8 bits are
  857. * transmitted from each byte in @p data adding one bit as specified by CTRL
  858. * register, BIT8DV field, to each byte. Please refer to USART_TxDoubleExt()
  859. * for transmitting two 9 bit frames with full control of all 9 bits.
  860. *
  861. * If frame length is 10-16, 10-16 (least significant) bits from @p data
  862. * are transmitted.
  863. *
  864. * Notice that possible parity/stop bits in asynchronous mode are not
  865. * considered part of specified frame bit length.
  866. *
  867. * @note
  868. * This function will stall if buffer is full, until buffer becomes available.
  869. *
  870. * @param[in] usart
  871. * Pointer to USART/UART peripheral register block.
  872. *
  873. * @param[in] data
  874. * Data to transmit, the least significant byte holds the frame transmitted
  875. * first. See details above for further info.
  876. ******************************************************************************/
  877. void USART_TxDouble(USART_TypeDef *usart, uint16_t data)
  878. {
  879. /* Check that transmit buffer is empty */
  880. while (!(usart->STATUS & USART_STATUS_TXBL))
  881. ;
  882. usart->TXDOUBLE = (uint32_t)data;
  883. }
  884. /***************************************************************************//**
  885. * @brief
  886. * Transmit two 4-9 bit frames, or one 10-16 bit frame with extended control.
  887. *
  888. * @details
  889. * Notice that possible parity/stop bits in asynchronous mode are not
  890. * considered part of specified frame bit length.
  891. *
  892. * @note
  893. * This function will stall if buffer is full, until buffer becomes available.
  894. *
  895. * @param[in] usart
  896. * Pointer to USART/UART peripheral register block.
  897. *
  898. * @param[in] data
  899. * Data to transmit with extended control. Contains two 16 bit words
  900. * concatenated. Least significant word holds frame transitted first. If frame
  901. * length is 4-9, two frames with 4-9 least significant bits from each 16 bit
  902. * word are transmitted.
  903. * @par
  904. * If frame length is 10-16 bits, 8 data bits are taken from the least
  905. * significant 16 bit word, and the remaining bits from the other 16 bit word.
  906. * @par
  907. * Additional control bits are available as documented in the EFM32 reference
  908. * manual (set to 0 if not used). For 10-16 bit frame length, these control
  909. * bits are taken from the most significant 16 bit word.
  910. ******************************************************************************/
  911. void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data)
  912. {
  913. /* Check that transmit buffer is empty */
  914. while (!(usart->STATUS & USART_STATUS_TXBL))
  915. ;
  916. usart->TXDOUBLEX = data;
  917. }
  918. /***************************************************************************//**
  919. * @brief
  920. * Transmit one 4-9 bit frame with extended control.
  921. *
  922. * @details
  923. * Notice that possible parity/stop bits in asynchronous mode are not
  924. * considered part of specified frame bit length.
  925. *
  926. * @note
  927. * This function will stall if buffer is full, until buffer becomes available.
  928. *
  929. * @param[in] usart
  930. * Pointer to USART/UART peripheral register block.
  931. *
  932. * @param[in] data
  933. * Data to transmit with extended control. Least significant bits contains
  934. * frame bits, and additional control bits are available as documented in
  935. * the EFM32 reference manual (set to 0 if not used).
  936. ******************************************************************************/
  937. void USART_TxExt(USART_TypeDef *usart, uint16_t data)
  938. {
  939. /* Check that transmit buffer is empty */
  940. while (!(usart->STATUS & USART_STATUS_TXBL))
  941. ;
  942. usart->TXDATAX = (uint32_t)data;
  943. }
  944. /** @} (end addtogroup USART) */
  945. /** @} (end addtogroup EM_Library) */