added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Revision:
144:ef7eb2e8f9f7
Parent:
50:a417edff4437
diff -r 423e1876dc07 -r ef7eb2e8f9f7 targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_usart.c
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_usart.c	Tue Aug 02 14:07:36 2016 +0000
+++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_usart.c	Fri Sep 02 15:07:44 2016 +0100
@@ -1,1215 +1,1215 @@
-/***************************************************************************//**
- * @file em_usart.c
- * @brief Universal synchronous/asynchronous receiver/transmitter (USART/UART)
- *   Peripheral API
- * @version 4.2.1
- *******************************************************************************
- * @section License
- * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
- *******************************************************************************
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- *
- * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
- * obligation to support this Software. Silicon Labs is providing the
- * Software "AS IS", with no express or implied warranties of any kind,
- * including, but not limited to, any implied warranties of merchantability
- * or fitness for any particular purpose or warranties against infringement
- * of any proprietary rights of a third party.
- *
- * Silicon Labs will not be liable for any consequential, incidental, or
- * special damages, or any other relief, or for any claim by any third party,
- * arising from your use of this Software.
- *
- ******************************************************************************/
-
-#include "em_usart.h"
-#if defined(USART_COUNT) && (USART_COUNT > 0)
-
-#include "em_cmu.h"
-#include "em_bus.h"
-#include "em_assert.h"
-
-/***************************************************************************//**
- * @addtogroup EM_Library
- * @{
- ******************************************************************************/
-
-/***************************************************************************//**
- * @addtogroup USART
- * @brief Universal Synchronous/Asynchronous Receiver/Transmitter
- *   Peripheral API
- * @{
- ******************************************************************************/
-
-/*******************************************************************************
- *******************************   DEFINES   ***********************************
- ******************************************************************************/
-
-/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
-
-
-/** Validation of USART register block pointer reference for assert statements. */
-#if (USART_COUNT == 1) && defined(USART0)
-#define USART_REF_VALID(ref)    ((ref) == USART0)
-
-#elif (USART_COUNT == 1) && defined(USART1)
-#define USART_REF_VALID(ref)    ((ref) == USART1)
-
-#elif (USART_COUNT == 2) && defined(USART2)
-#define USART_REF_VALID(ref)    (((ref) == USART1) || ((ref) == USART2))
-
-#elif (USART_COUNT == 2)
-#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1))
-
-#elif (USART_COUNT == 3)
-#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
-                                 ((ref) == USART2))
-#elif (USART_COUNT == 4)
-#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
-                                 ((ref) == USART2) || ((ref) == USART3))
-#elif (USART_COUNT == 5)
-#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
-                                 ((ref) == USART2) || ((ref) == USART3) || \
-                                 ((ref) == USART4))
-#elif (USART_COUNT == 6)
-#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
-                                 ((ref) == USART2) || ((ref) == USART3) || \
-                                 ((ref) == USART4) || ((ref) == USART5))
-#else
-#error "Undefined number of USARTs."
-#endif
-
-#if defined(USARTRF_COUNT) && (USARTRF_COUNT > 0)
-#if (USARTRF_COUNT == 1) && defined(USARTRF0)
-#define USARTRF_REF_VALID(ref)  ((ref) == USARTRF0)
-#elif (USARTRF_COUNT == 1) && defined(USARTRF1)
-#define USARTRF_REF_VALID(ref)  ((ref) == USARTRF1)
-#else
-#define USARTRF_REF_VALID(ref)  (0)
-#endif
-#else
-#define USARTRF_REF_VALID(ref)  (0)
-#endif
-
-#if defined(_EZR32_HAPPY_FAMILY)
-#define USART_IRDA_VALID(ref)    ((ref) == USART0)
-#elif defined(_EFM32_HAPPY_FAMILY)
-#define USART_IRDA_VALID(ref)    (((ref) == USART0) || ((ref) == USART1))
-#elif defined(USART0)
-#define USART_IRDA_VALID(ref)    ((ref) == USART0)
-#elif (USART_COUNT == 1) && defined(USART1)
-#define USART_IRDA_VALID(ref)    ((ref) == USART1)
-#else
-#define USART_IRDA_VALID(ref)    (0)
-#endif
-
-#if defined(_EZR32_HAPPY_FAMILY)
-#define USART_I2S_VALID(ref)    ((ref) == USART0)
-#elif defined(_EFM32_HAPPY_FAMILY)
-#define USART_I2S_VALID(ref)    (((ref) == USART0) || ((ref) == USART1))
-#elif defined(_EFM32_TINY_FAMILY) || defined(_EFM32_ZERO_FAMILY) || defined(_SILICON_LABS_32B_PLATFORM_2)
-#define USART_I2S_VALID(ref)    ((ref) == USART1)
-#elif defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
-#define USART_I2S_VALID(ref)    (((ref) == USART1) || ((ref) == USART2))
-#endif
-
-#if (UART_COUNT == 1)
-#define UART_REF_VALID(ref)    ((ref) == UART0)
-#elif (UART_COUNT == 2)
-#define UART_REF_VALID(ref)    (((ref) == UART0) || ((ref) == UART1))
-#else
-#define UART_REF_VALID(ref)    (0)
-#endif
-
-/** @endcond */
-
-
-/*******************************************************************************
- **************************   GLOBAL FUNCTIONS   *******************************
- ******************************************************************************/
-
-/***************************************************************************//**
- * @brief
- *   Configure USART/UART operating in asynchronous mode to use a given
- *   baudrate (or as close as possible to specified baudrate).
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @param[in] refFreq
- *   USART/UART reference clock frequency in Hz that will be used. If set to 0,
- *   the currently configured reference clock is assumed.
- *
- * @param[in] baudrate
- *   Baudrate to try to achieve for USART/UART.
- *
- * @param[in] ovs
- *   Oversampling to be used. Normal is 16x oversampling, but lower oversampling
- *   may be used to achieve higher rates or better baudrate accuracy in some
- *   cases. Notice that lower oversampling frequency makes channel more
- *   vulnerable to bit faults during reception due to clock inaccuracies
- *   compared to link partner.
- ******************************************************************************/
-void USART_BaudrateAsyncSet(USART_TypeDef *usart,
-                            uint32_t refFreq,
-                            uint32_t baudrate,
-                            USART_OVS_TypeDef ovs)
-{
-  uint32_t clkdiv;
-  uint32_t oversample;
-
-  /* Inhibit divide by 0 */
-  EFM_ASSERT(baudrate);
-
-  /*
-   * We want to use integer division to avoid forcing in float division
-   * utils, and yet keep rounding effect errors to a minimum.
-   *
-   * CLKDIV in asynchronous mode is given by:
-   *
-   * CLKDIV = 256 * (fHFPERCLK/(oversample * br) - 1)
-   * or
-   * CLKDIV = (256 * fHFPERCLK)/(oversample * br) - 256
-   *
-   * The basic problem with integer division in the above formula is that
-   * the dividend (256 * fHFPERCLK) may become higher than max 32 bit
-   * integer. Yet, we want to evaluate dividend first before dividing in
-   * order to get as small rounding effects as possible. We do not want
-   * to make too harsh restrictions on max fHFPERCLK value either.
-   *
-   * One can possibly factorize 256 and oversample/br. However,
-   * since the last 6 or 3 bits of CLKDIV are don't care, we can base our
-   * integer arithmetic on the below formula
-   *
-   * CLKDIV / 64 = (4 * fHFPERCLK)/(oversample * br) - 4 (3 bits dont care)
-   * or
-   * CLKDIV / 8  = (32 * fHFPERCLK)/(oversample * br) - 32 (6 bits dont care)
-   *
-   * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
-   * up to 1GHz without overflowing a 32 bit value!
-   */
-
-  /* HFPERCLK used to clock all USART/UART peripheral modules */
-  if (!refFreq)
-  {
-    refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
-  }
-
-  /* Map oversampling */
-  switch (ovs)
-  {
-    case USART_CTRL_OVS_X16:
-      EFM_ASSERT(baudrate <= (refFreq / 16));
-      oversample = 16;
-      break;
-
-    case USART_CTRL_OVS_X8:
-      EFM_ASSERT(baudrate <= (refFreq / 8));
-      oversample = 8;
-      break;
-
-    case USART_CTRL_OVS_X6:
-      EFM_ASSERT(baudrate <= (refFreq / 6));
-      oversample = 6;
-      break;
-
-    case USART_CTRL_OVS_X4:
-      EFM_ASSERT(baudrate <= (refFreq / 4));
-      oversample = 4;
-      break;
-
-    default:
-      /* Invalid input */
-      EFM_ASSERT(0);
-      return;
-  }
-
-  /* Calculate and set CLKDIV with fractional bits.
-   * The addend (oversample*baudrate)/2 in the first line is to round the
-   * divisor up by half the divisor before the division in order to reduce the
-   * integer division error, which consequently results in a higher baudrate
-   * than desired. */
-#if defined(_USART_CLKDIV_DIV_MASK) && (_USART_CLKDIV_DIV_MASK >= 0x7FFFF8UL)
-  clkdiv  = 32 * refFreq + (oversample * baudrate) / 2;
-  clkdiv /= (oversample * baudrate);
-  clkdiv -= 32;
-  clkdiv *= 8;
-#else
-  clkdiv  = 4 * refFreq + (oversample * baudrate) / 2;
-  clkdiv /= (oversample * baudrate);
-  clkdiv -= 4;
-  clkdiv *= 64;
-#endif
-
-  /* Verify that resulting clock divider is within limits */
-  EFM_ASSERT(clkdiv <= _USART_CLKDIV_DIV_MASK);
-
-  /* If EFM_ASSERT is not enabled, make sure we don't write to reserved bits */
-  clkdiv &= _USART_CLKDIV_DIV_MASK;
-
-  usart->CTRL  &= ~_USART_CTRL_OVS_MASK;
-  usart->CTRL  |= ovs;
-  usart->CLKDIV = clkdiv;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Calculate baudrate for USART/UART given reference frequency, clock division
- *   and oversampling rate (if async mode).
- *
- * @details
- *   This function returns the baudrate that a USART/UART module will use if
- *   configured with the given frequency, clock divisor and mode. Notice that
- *   this function will not use actual HW configuration. It can be used
- *   to determinate if a given configuration is sufficiently accurate for the
- *   application.
- *
- * @param[in] refFreq
- *   USART/UART HF peripheral frequency used.
- *
- * @param[in] clkdiv
- *   Clock division factor to be used.
- *
- * @param[in] syncmode
- *   @li true - synchronous mode operation.
- *   @li false - asynchronous mode operation.
- *
- * @param[in] ovs
- *   Oversampling used if asynchronous mode. Not used if @p syncmode is true.
- *
- * @return
- *   Baudrate with given settings.
- ******************************************************************************/
-uint32_t USART_BaudrateCalc(uint32_t refFreq,
-                            uint32_t clkdiv,
-                            bool syncmode,
-                            USART_OVS_TypeDef ovs)
-{
-  uint32_t oversample;
-  uint64_t divisor;
-  uint64_t factor;
-  uint64_t remainder;
-  uint64_t quotient;
-  uint32_t br;
-
-  /* Mask out unused bits */
-  clkdiv &= _USART_CLKDIV_MASK;
-
-  /* We want to use integer division to avoid forcing in float division */
-  /* utils, and yet keep rounding effect errors to a minimum. */
-
-  /* Baudrate calculation depends on if synchronous or asynchronous mode */
-  if (syncmode)
-  {
-    /*
-     * Baudrate is given by:
-     *
-     * br = fHFPERCLK/(2 * (1 + (CLKDIV / 256)))
-     *
-     * which can be rewritten to
-     *
-     * br = (128 * fHFPERCLK)/(256 + CLKDIV)
-     */
-    oversample = 1; /* Not used in sync mode, ie 1 */
-    factor     = 128;
-  }
-  else
-  {
-    /*
-     * Baudrate in asynchronous mode is given by:
-     *
-     * br = fHFPERCLK/(oversample * (1 + (CLKDIV / 256)))
-     *
-     * which can be rewritten to
-     *
-     * br = (256 * fHFPERCLK)/(oversample * (256 + CLKDIV))
-     *
-     * First of all we can reduce the 256 factor of the dividend with
-     * (part of) oversample part of the divisor.
-     */
-
-    switch (ovs)
-    {
-      case USART_CTRL_OVS_X16:
-        oversample = 1;
-        factor     = 256 / 16;
-        break;
-
-      case USART_CTRL_OVS_X8:
-        oversample = 1;
-        factor     = 256 / 8;
-        break;
-
-      case USART_CTRL_OVS_X6:
-        oversample = 3;
-        factor     = 256 / 2;
-        break;
-
-      default:
-        oversample = 1;
-        factor     = 256 / 4;
-        break;
-    }
-  }
-
-  /*
-   * The basic problem with integer division in the above formula is that
-   * the dividend (factor * fHFPERCLK) may become larger than a 32 bit
-   * integer. Yet we want to evaluate dividend first before dividing in
-   * order to get as small rounding effects as possible. We do not want
-   * to make too harsh restrictions on max fHFPERCLK value either.
-   *
-   * For division a/b, we can write
-   *
-   * a = qb + r
-   *
-   * where q is the quotient and r is the remainder, both integers.
-   *
-   * The orignal baudrate formula can be rewritten as
-   *
-   * br = xa / b = x(qb + r)/b = xq + xr/b
-   *
-   * where x is 'factor', a is 'refFreq' and b is 'divisor', referring to
-   * variable names.
-   */
-
-  /* Divisor will never exceed max 32 bit value since clkdiv <= 0xFFFFF8 */
-  /* and 'oversample' has been reduced to <= 3. */
-  divisor = oversample * (256 + clkdiv);
-
-  quotient  = refFreq / divisor;
-  remainder = refFreq % divisor;
-
-  /* factor <= 128 and since divisor >= 256, the below cannot exceed max */
-  /* 32 bit value. However, factor * remainder can become larger than 32-bit */
-  /* because of the size of _USART_CLKDIV_DIV_MASK on some families. */
-  br = (uint32_t)(factor * quotient);
-
-  /*
-   * factor <= 128 and remainder < (oversample*(256 + clkdiv)), which
-   * means dividend (factor * remainder) worst case is
-   * 128 * (3 * (256 + _USART_CLKDIV_DIV_MASK)) = 0x1_8001_7400.
-   */
-  br += (uint32_t)((factor * remainder) / divisor);
-
-  return br;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Get current baudrate for USART/UART.
- *
- * @details
- *   This function returns the actual baudrate (not considering oscillator
- *   inaccuracies) used by a USART/UART peripheral.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @return
- *   Current baudrate.
- ******************************************************************************/
-uint32_t USART_BaudrateGet(USART_TypeDef *usart)
-{
-  uint32_t          freq;
-  USART_OVS_TypeDef ovs;
-  bool              syncmode;
-
-  if (usart->CTRL & USART_CTRL_SYNC)
-  {
-    syncmode = true;
-  }
-  else
-  {
-    syncmode = false;
-  }
-
-  /* HFPERCLK used to clock all USART/UART peripheral modules */
-  freq = CMU_ClockFreqGet(cmuClock_HFPER);
-  ovs  = (USART_OVS_TypeDef)(usart->CTRL & _USART_CTRL_OVS_MASK);
-  return USART_BaudrateCalc(freq, usart->CLKDIV, syncmode, ovs);
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Configure USART operating in synchronous mode to use a given baudrate
- *   (or as close as possible to specified baudrate).
- *
- * @details
- *   The configuration will be set to use a baudrate <= the specified baudrate
- *   in order to ensure that the baudrate does not exceed the specified value.
- *
- *   Fractional clock division is suppressed, although the HW design allows it.
- *   It could cause half clock cycles to exceed specified limit, and thus
- *   potentially violate specifications for the slave device. In some special
- *   situations fractional clock division may be useful even in synchronous
- *   mode, but in those cases it must be directly adjusted, possibly assisted
- *   by USART_BaudrateCalc():
- *
- * @param[in] usart
- *   Pointer to USART peripheral register block. (Cannot be used on UART
- *   modules.)
- *
- * @param[in] refFreq
- *   USART reference clock frequency in Hz that will be used. If set to 0,
- *   the currently configured reference clock is assumed.
- *
- * @param[in] baudrate
- *   Baudrate to try to achieve for USART.
- ******************************************************************************/
-void USART_BaudrateSyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate)
-{
-#if defined(_USART_CLKDIV_DIV_MASK) && (_USART_CLKDIV_DIV_MASK >= 0x7FFFF8UL)
-  uint64_t clkdiv;
-#else
-  uint32_t clkdiv;
-#endif
-
-  /* Inhibit divide by 0 */
-  EFM_ASSERT(baudrate);
-
-  /*
-   * CLKDIV in synchronous mode is given by:
-   *
-   * CLKDIV = 256 * (fHFPERCLK/(2 * br) - 1)
-   */
-
-  /* HFPERCLK used to clock all USART/UART peripheral modules */
-  if (!refFreq)
-  {
-    refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
-  }
-
-#if defined(_USART_CLKDIV_DIV_MASK) && (_USART_CLKDIV_DIV_MASK >= 0x7FFFF8UL)
-  /* Calculate and set CLKDIV without fractional bits */
-  clkdiv = 2 * baudrate;
-  clkdiv = (0x100ULL * (uint64_t)refFreq) / clkdiv;
-
-  /* Round up by not subtracting 256 and mask off fractional part */
-  clkdiv &= ~0xFF;
-#else
-  /* Calculate and set CLKDIV with fractional bits */
-  clkdiv  = 2 * refFreq;
-  clkdiv += baudrate - 1;
-  clkdiv /= baudrate;
-  clkdiv -= 4;
-  clkdiv *= 64;
-  /* Make sure we don't use fractional bits by rounding CLKDIV */
-  /* up (and thus reducing baudrate, not increasing baudrate above */
-  /* specified value). */
-  clkdiv += 0xc0;
-  clkdiv &= 0xffffff00;
-#endif
-
-  /* Verify that resulting clock divider is within limits */
-  EFM_ASSERT(!(clkdiv & ~_USART_CLKDIV_DIV_MASK));
-
-  /* If EFM_ASSERT is not enabled, make sure we don't write to reserved bits */
-  clkdiv &= _USART_CLKDIV_DIV_MASK;
-
-  BUS_RegMaskedWrite(&usart->CLKDIV, _USART_CLKDIV_DIV_MASK, clkdiv);
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Enable/disable USART/UART receiver and/or transmitter.
- *
- * @details
- *   Notice that this function does not do any configuration. Enabling should
- *   normally be done after initialization is done (if not enabled as part
- *   of init).
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @param[in] enable
- *   Select status for receiver/transmitter.
- ******************************************************************************/
-void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
-{
-  uint32_t tmp;
-
-  /* Make sure the module exists on the selected chip */
-  EFM_ASSERT( USART_REF_VALID(usart)
-              || USARTRF_REF_VALID(usart)
-              || UART_REF_VALID(usart) );
-
-  /* Disable as specified */
-  tmp        = ~((uint32_t) (enable));
-  tmp       &= _USART_CMD_RXEN_MASK | _USART_CMD_TXEN_MASK;
-  usart->CMD = tmp << 1;
-
-  /* Enable as specified */
-  usart->CMD = (uint32_t) (enable);
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Init USART/UART for normal asynchronous mode.
- *
- * @details
- *   This function will configure basic settings in order to operate in normal
- *   asynchronous mode.
- *
- *   Special control setup not covered by this function must be done after
- *   using this function by direct modification of the CTRL register.
- *
- *   Notice that pins used by the USART/UART module must be properly configured
- *   by the user explicitly, in order for the USART/UART to work as intended.
- *   (When configuring pins, one should remember to consider the sequence of
- *   configuration, in order to avoid unintended pulses/glitches on output
- *   pins.)
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @param[in] init
- *   Pointer to initialization structure used to configure basic async setup.
- ******************************************************************************/
-void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
-{
-  /* Make sure the module exists on the selected chip */
-  EFM_ASSERT( USART_REF_VALID(usart)
-              || USARTRF_REF_VALID(usart)
-              || UART_REF_VALID(usart) );
-
-  /* Init USART registers to HW reset state. */
-  USART_Reset(usart);
-
-#if defined(USART_INPUT_RXPRS) && defined(USART_CTRL_MVDIS)
-  /* Disable majority vote if specified. */
-  if (init->mvdis)
-  {
-    usart->CTRL |= USART_CTRL_MVDIS;
-  }
-
-  /* Configure PRS input mode. */
-  if (init->prsRxEnable)
-  {
-    usart->INPUT = (uint32_t) init->prsRxCh | USART_INPUT_RXPRS;
-  }
-#endif
-
-  /* Configure databits, stopbits and parity */
-  usart->FRAME = (uint32_t)init->databits
-                 | (uint32_t)init->stopbits
-                 | (uint32_t)init->parity;
-
-  /* Configure baudrate */
-  USART_BaudrateAsyncSet(usart, init->refFreq, init->baudrate, init->oversampling);
-
-#if defined(_USART_TIMING_CSHOLD_MASK)
-  usart->TIMING = ((init->autoCsHold << _USART_TIMING_CSHOLD_SHIFT)
-                   & _USART_TIMING_CSHOLD_MASK)
-                  | ((init->autoCsSetup << _USART_TIMING_CSSETUP_SHIFT)
-                     & _USART_TIMING_CSSETUP_MASK);
-  if (init->autoCsEnable)
-  {
-    usart->CTRL |= USART_CTRL_AUTOCS;
-  }
-#endif
-  /* Finally enable (as specified) */
-  usart->CMD = (uint32_t)init->enable;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Init USART for synchronous mode.
- *
- * @details
- *   This function will configure basic settings in order to operate in
- *   synchronous mode.
- *
- *   Special control setup not covered by this function must be done after
- *   using this function by direct modification of the CTRL register.
- *
- *   Notice that pins used by the USART module must be properly configured
- *   by the user explicitly, in order for the USART to work as intended.
- *   (When configuring pins, one should remember to consider the sequence of
- *   configuration, in order to avoid unintended pulses/glitches on output
- *   pins.)
- *
- * @param[in] usart
- *   Pointer to USART peripheral register block. (UART does not support this
- *   mode.)
- *
- * @param[in] init
- *   Pointer to initialization structure used to configure basic async setup.
- ******************************************************************************/
-void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init)
-{
-  /* Make sure the module exists on the selected chip */
-  EFM_ASSERT( USART_REF_VALID(usart) || USARTRF_REF_VALID(usart) );
-
-  /* Init USART registers to HW reset state. */
-  USART_Reset(usart);
-
-  /* Set bits for synchronous mode */
-  usart->CTRL |= (USART_CTRL_SYNC)
-                 | (uint32_t)init->clockMode
-                 | (init->msbf ? USART_CTRL_MSBF : 0);
-
-#if defined(_USART_CTRL_AUTOTX_MASK)
-  usart->CTRL |= init->autoTx ? USART_CTRL_AUTOTX : 0;
-#endif
-
-#if defined(_USART_INPUT_RXPRS_MASK)
-  /* Configure PRS input mode. */
-  if (init->prsRxEnable)
-  {
-    usart->INPUT = (uint32_t)init->prsRxCh | USART_INPUT_RXPRS;
-  }
-#endif
-
-  /* Configure databits, leave stopbits and parity at reset default (not used) */
-  usart->FRAME = (uint32_t)init->databits
-                 | USART_FRAME_STOPBITS_DEFAULT
-                 | USART_FRAME_PARITY_DEFAULT;
-
-  /* Configure baudrate */
-  USART_BaudrateSyncSet(usart, init->refFreq, init->baudrate);
-
-  /* Finally enable (as specified) */
-  if (init->master)
-  {
-    usart->CMD = USART_CMD_MASTEREN;
-  }
-
-#if defined(_USART_TIMING_CSHOLD_MASK)
-  usart->TIMING = ((init->autoCsHold << _USART_TIMING_CSHOLD_SHIFT)
-                   & _USART_TIMING_CSHOLD_MASK)
-                  | ((init->autoCsSetup << _USART_TIMING_CSSETUP_SHIFT)
-                     & _USART_TIMING_CSSETUP_MASK);
-  if (init->autoCsEnable)
-  {
-    usart->CTRL |= USART_CTRL_AUTOCS;
-  }
-#endif
-
-  usart->CMD = (uint32_t)init->enable;
-}
-
-
-#if defined(USART0) || ((USART_COUNT == 1) && defined(USART1))
-/***************************************************************************//**
- * @brief
- *   Init USART0 for asynchronous IrDA mode.
- *
- * @details
- *   This function will configure basic settings in order to operate in
- *   asynchronous IrDA mode.
- *
- *   Special control setup not covered by this function must be done after
- *   using this function by direct modification of the CTRL and IRCTRL
- *   registers.
- *
- *   Notice that pins used by the USART/UART module must be properly configured
- *   by the user explicitly, in order for the USART/UART to work as intended.
- *   (When configuring pins, one should remember to consider the sequence of
- *   configuration, in order to avoid unintended pulses/glitches on output
- *   pins.)
- *
- * @param[in] init
- *   Pointer to initialization structure used to configure async IrDA setup.
- *
- * @note
- *   This function only applies to USART0 as IrDA is not supported on the other
- *   USART modules.
- *
- ******************************************************************************/
-void USART_InitIrDA(const USART_InitIrDA_TypeDef *init)
-{
-  #if (USART_COUNT == 1) && defined(USART1)
-  USART_TypeDef *usart = USART1;
-  #else
-  USART_TypeDef *usart = USART0;
-  #endif
-
-  /* Init USART as async device */
-  USART_InitAsync(usart, &(init->async));
-
-  /* Set IrDA modulation to RZI (return-to-zero-inverted) */
-  usart->CTRL |= USART_CTRL_TXINV;
-
-  /* Invert Rx signal before demodulator if enabled */
-  if (init->irRxInv)
-  {
-    usart->CTRL |= USART_CTRL_RXINV;
-  }
-
-  /* Configure IrDA */
-  usart->IRCTRL |= (uint32_t)init->irPw
-                   | (uint32_t)init->irPrsSel
-                   | ((uint32_t)init->irFilt << _USART_IRCTRL_IRFILT_SHIFT)
-                   | ((uint32_t)init->irPrsEn << _USART_IRCTRL_IRPRSEN_SHIFT);
-
-  /* Enable IrDA */
-  usart->IRCTRL |= USART_IRCTRL_IREN;
-}
-#endif
-
-
-#if defined(_USART_I2SCTRL_MASK)
-/***************************************************************************//**
- * @brief
- *   Init USART for I2S mode.
- *
- * @details
- *   This function will configure basic settings in order to operate in I2S
- *   mode.
- *
- *   Special control setup not covered by this function must be done after
- *   using this function by direct modification of the CTRL and I2SCTRL
- *   registers.
- *
- *   Notice that pins used by the USART module must be properly configured
- *   by the user explicitly, in order for the USART to work as intended.
- *   (When configuring pins, one should remember to consider the sequence of
- *   configuration, in order to avoid unintended pulses/glitches on output
- *   pins.)
- *
- * @param[in] usart
- *   Pointer to USART peripheral register block. (UART does not support this
- *   mode.)
- *
- * @param[in] init
- *   Pointer to initialization structure used to configure basic I2S setup.
- *
- * @note
- *   This function does not apply to all USART's. Refer to chip manuals.
- *
- ******************************************************************************/
-void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init)
-{
-  USART_Enable_TypeDef enable;
-
-  /* Make sure the module exists on the selected chip */
-  EFM_ASSERT(USART_I2S_VALID(usart));
-
-  /* Override the enable setting. */
-  enable            = init->sync.enable;
-  init->sync.enable = usartDisable;
-
-  /* Init USART as a sync device. */
-  USART_InitSync(usart, &init->sync);
-
-  /* Configure and enable I2CCTRL register acording to selected mode. */
-  usart->I2SCTRL = (uint32_t)init->format
-                   | (uint32_t)init->justify
-                   | (init->delay    ? USART_I2SCTRL_DELAY    : 0)
-                   | (init->dmaSplit ? USART_I2SCTRL_DMASPLIT : 0)
-                   | (init->mono     ? USART_I2SCTRL_MONO     : 0)
-                   | USART_I2SCTRL_EN;
-
-  if (enable != usartDisable)
-  {
-    USART_Enable(usart, enable);
-  }
-}
-#endif
-
-
-/***************************************************************************//**
- * @brief
- *   Initialize automatic transmissions using PRS channel as trigger
- * @note
- *   Initialize USART with USART_Init() before setting up PRS configuration
- *
- * @param[in] usart Pointer to USART to configure
- * @param[in] init Pointer to initialization structure
- ******************************************************************************/
-void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init)
-{
-  uint32_t trigctrl;
-
-  /* Clear values that will be reconfigured  */
-  trigctrl = usart->TRIGCTRL & ~(_USART_TRIGCTRL_RXTEN_MASK
-                                 | _USART_TRIGCTRL_TXTEN_MASK
-#if defined(USART_TRIGCTRL_AUTOTXTEN)
-                                 | _USART_TRIGCTRL_AUTOTXTEN_MASK
-#endif
-                                 | _USART_TRIGCTRL_TSEL_MASK);
-
-#if defined(USART_TRIGCTRL_AUTOTXTEN)
-  if (init->autoTxTriggerEnable)
-  {
-    trigctrl |= USART_TRIGCTRL_AUTOTXTEN;
-  }
-#endif
-  if (init->txTriggerEnable)
-  {
-    trigctrl |= USART_TRIGCTRL_TXTEN;
-  }
-  if (init->rxTriggerEnable)
-  {
-    trigctrl |= USART_TRIGCTRL_RXTEN;
-  }
-  trigctrl |= init->prsTriggerChannel;
-
-  /* Enable new configuration */
-  usart->TRIGCTRL = trigctrl;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Reset USART/UART to same state as after a HW reset.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- ******************************************************************************/
-void USART_Reset(USART_TypeDef *usart)
-{
-  /* Make sure the module exists on the selected chip */
-  EFM_ASSERT( USART_REF_VALID(usart)
-              || USARTRF_REF_VALID(usart)
-              || UART_REF_VALID(usart) );
-
-  /* Make sure disabled first, before resetting other registers */
-  usart->CMD = USART_CMD_RXDIS | USART_CMD_TXDIS | USART_CMD_MASTERDIS
-               | USART_CMD_RXBLOCKDIS | USART_CMD_TXTRIDIS | USART_CMD_CLEARTX
-               | USART_CMD_CLEARRX;
-  usart->CTRL      = _USART_CTRL_RESETVALUE;
-  usart->FRAME     = _USART_FRAME_RESETVALUE;
-  usart->TRIGCTRL  = _USART_TRIGCTRL_RESETVALUE;
-  usart->CLKDIV    = _USART_CLKDIV_RESETVALUE;
-  usart->IEN       = _USART_IEN_RESETVALUE;
-  usart->IFC       = _USART_IFC_MASK;
-#if defined(_USART_ROUTEPEN_MASK) || defined(_UART_ROUTEPEN_MASK)
-  usart->ROUTEPEN  = _USART_ROUTEPEN_RESETVALUE;
-  usart->ROUTELOC0 = _USART_ROUTELOC0_RESETVALUE;
-  usart->ROUTELOC1 = _USART_ROUTELOC1_RESETVALUE;
-#else
-  usart->ROUTE     = _USART_ROUTE_RESETVALUE;
-#endif
-
-  if (USART_IRDA_VALID(usart))
-  {
-    usart->IRCTRL = _USART_IRCTRL_RESETVALUE;
-  }
-
-#if defined(_USART_INPUT_RESETVALUE)
-  usart->INPUT = _USART_INPUT_RESETVALUE;
-#endif
-
-#if defined(_USART_I2SCTRL_RESETVALUE)
-  if (USART_I2S_VALID(usart))
-  {
-    usart->I2SCTRL = _USART_I2SCTRL_RESETVALUE;
-  }
-#endif
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Receive one 4-8 bit frame, (or part of 10-16 bit frame).
- *
- * @details
- *   This function is normally used to receive one frame when operating with
- *   frame length 4-8 bits. Please refer to @ref USART_RxExt() for reception of
- *   9 bit frames.
- *
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if the buffer is empty, until data is received.
- *   Alternatively the user can explicitly check whether data is available, and
- *   if data is avaliable, call @ref USART_RxDataGet() to read the RXDATA
- *   register directly.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @return
- *   Data received.
- ******************************************************************************/
-uint8_t USART_Rx(USART_TypeDef *usart)
-{
-  while (!(usart->STATUS & USART_STATUS_RXDATAV))
-    ;
-
-  return (uint8_t)usart->RXDATA;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Receive two 4-8 bit frames, or one 10-16 bit frame.
- *
- * @details
- *   This function is normally used to receive one frame when operating with
- *   frame length 10-16 bits. Please refer to @ref USART_RxDoubleExt() for
- *   reception of two 9 bit frames.
- *
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if buffer is empty, until data is received.
- *   Alternatively the user can explicitly check whether data is available, and
- *   if data is avaliable, call @ref USART_RxDoubleGet() to read the RXDOUBLE
- *   register directly.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @return
- *   Data received.
- ******************************************************************************/
-uint16_t USART_RxDouble(USART_TypeDef *usart)
-{
-  while (!(usart->STATUS & USART_STATUS_RXFULL))
-    ;
-
-  return (uint16_t)usart->RXDOUBLE;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Receive two 4-9 bit frames, or one 10-16 bit frame with extended
- *   information.
- *
- * @details
- *   This function is normally used to receive one frame when operating with
- *   frame length 10-16 bits and additional RX status information is required.
- *
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if buffer is empty, until data is received.
- *   Alternatively the user can explicitly check whether data is available, and
- *   if data is avaliable, call @ref USART_RxDoubleXGet() to read the RXDOUBLEX
- *   register directly.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @return
- *   Data received.
- ******************************************************************************/
-uint32_t USART_RxDoubleExt(USART_TypeDef *usart)
-{
-  while (!(usart->STATUS & USART_STATUS_RXFULL))
-    ;
-
-  return usart->RXDOUBLEX;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Receive one 4-9 bit frame, (or part of 10-16 bit frame) with extended
- *   information.
- *
- * @details
- *   This function is normally used to receive one frame when operating with
- *   frame length 4-9 bits and additional RX status information is required.
- *
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if buffer is empty, until data is received.
- *   Alternatively the user can explicitly check whether data is available, and
- *   if data is avaliable, call @ref USART_RxDataXGet() to read the RXDATAX
- *   register directly.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @return
- *   Data received.
- ******************************************************************************/
-uint16_t USART_RxExt(USART_TypeDef *usart)
-{
-  while (!(usart->STATUS & USART_STATUS_RXDATAV))
-    ;
-
-  return (uint16_t)usart->RXDATAX;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Perform one 8 bit frame SPI transfer.
- *
- * @note
- *   This function will stall if the transmit buffer is full. When a transmit
- *   buffer becomes available, data is written and the function will wait until
- *   the data is fully transmitted. The SPI return value is then read out and
- *   returned.
- *
- * @param[in] usart
- *   Pointer to USART peripheral register block.
- *
- * @param[in] data
- *   Data to transmit.
- *
- * @return
- *   Data received.
- ******************************************************************************/
-uint8_t USART_SpiTransfer(USART_TypeDef *usart, uint8_t data)
-{
-  while (!(usart->STATUS & USART_STATUS_TXBL))
-    ;
-  usart->TXDATA = (uint32_t)data;
-  while (!(usart->STATUS & USART_STATUS_TXC))
-    ;
-  return (uint8_t)usart->RXDATA;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Transmit one 4-9 bit frame.
- *
- * @details
- *   Depending on frame length configuration, 4-8 (least significant) bits from
- *   @p data are transmitted. If frame length is 9, 8 bits are transmitted from
- *   @p data and one bit as specified by CTRL register, BIT8DV field. Please
- *   refer to USART_TxExt() for transmitting 9 bit frame with full control of
- *   all 9 bits.
- *
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if buffer is full, until buffer becomes available.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @param[in] data
- *   Data to transmit. See details above for further info.
- ******************************************************************************/
-void USART_Tx(USART_TypeDef *usart, uint8_t data)
-{
-  /* Check that transmit buffer is empty */
-  while (!(usart->STATUS & USART_STATUS_TXBL))
-    ;
-  usart->TXDATA = (uint32_t)data;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Transmit two 4-9 bit frames, or one 10-16 bit frame.
- *
- * @details
- *   Depending on frame length configuration, 4-8 (least significant) bits from
- *   each byte in @p data are transmitted. If frame length is 9, 8 bits are
- *   transmitted from each byte in @p data adding one bit as specified by CTRL
- *   register, BIT8DV field, to each byte. Please refer to USART_TxDoubleExt()
- *   for transmitting two 9 bit frames with full control of all 9 bits.
- *
- *   If frame length is 10-16, 10-16 (least significant) bits from @p data
- *   are transmitted.
- *
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if buffer is full, until buffer becomes available.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @param[in] data
- *   Data to transmit, the least significant byte holds the frame transmitted
- *   first. See details above for further info.
- ******************************************************************************/
-void USART_TxDouble(USART_TypeDef *usart, uint16_t data)
-{
-  /* Check that transmit buffer is empty */
-  while (!(usart->STATUS & USART_STATUS_TXBL))
-    ;
-  usart->TXDOUBLE = (uint32_t)data;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Transmit two 4-9 bit frames, or one 10-16 bit frame with extended control.
- *
- * @details
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if buffer is full, until buffer becomes available.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @param[in] data
- *   Data to transmit with extended control. Contains two 16 bit words
- *   concatenated. Least significant word holds frame transitted first. If frame
- *   length is 4-9, two frames with 4-9 least significant bits from each 16 bit
- *   word are transmitted.
- * @par
- *   If frame length is 10-16 bits, 8 data bits are taken from the least
- *   significant 16 bit word, and the remaining bits from the other 16 bit word.
- * @par
- *   Additional control bits are available as documented in the reference
- *   manual (set to 0 if not used). For 10-16 bit frame length, these control
- *   bits are taken from the most significant 16 bit word.
- ******************************************************************************/
-void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data)
-{
-  /* Check that transmit buffer is empty */
-  while (!(usart->STATUS & USART_STATUS_TXBL))
-    ;
-  usart->TXDOUBLEX = data;
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Transmit one 4-9 bit frame with extended control.
- *
- * @details
- *   Notice that possible parity/stop bits in asynchronous mode are not
- *   considered part of specified frame bit length.
- *
- * @note
- *   This function will stall if buffer is full, until buffer becomes available.
- *
- * @param[in] usart
- *   Pointer to USART/UART peripheral register block.
- *
- * @param[in] data
- *   Data to transmit with extended control. Least significant bits contains
- *   frame bits, and additional control bits are available as documented in
- *   the reference manual (set to 0 if not used).
- ******************************************************************************/
-void USART_TxExt(USART_TypeDef *usart, uint16_t data)
-{
-  /* Check that transmit buffer is empty */
-  while (!(usart->STATUS & USART_STATUS_TXBL))
-    ;
-  usart->TXDATAX = (uint32_t)data;
-}
-
-
-/** @} (end addtogroup USART) */
-/** @} (end addtogroup EM_Library) */
-#endif /* defined(USART_COUNT) && (USART_COUNT > 0) */
+/***************************************************************************//**
+ * @file em_usart.c
+ * @brief Universal synchronous/asynchronous receiver/transmitter (USART/UART)
+ *   Peripheral API
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include "em_usart.h"
+#if defined(USART_COUNT) && (USART_COUNT > 0)
+
+#include "em_cmu.h"
+#include "em_bus.h"
+#include "em_assert.h"
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup USART
+ * @brief Universal Synchronous/Asynchronous Receiver/Transmitter
+ *   Peripheral API
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ *******************************   DEFINES   ***********************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+
+/** Validation of USART register block pointer reference for assert statements. */
+#if (USART_COUNT == 1) && defined(USART0)
+#define USART_REF_VALID(ref)    ((ref) == USART0)
+
+#elif (USART_COUNT == 1) && defined(USART1)
+#define USART_REF_VALID(ref)    ((ref) == USART1)
+
+#elif (USART_COUNT == 2) && defined(USART2)
+#define USART_REF_VALID(ref)    (((ref) == USART1) || ((ref) == USART2))
+
+#elif (USART_COUNT == 2)
+#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1))
+
+#elif (USART_COUNT == 3)
+#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
+                                 ((ref) == USART2))
+#elif (USART_COUNT == 4)
+#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
+                                 ((ref) == USART2) || ((ref) == USART3))
+#elif (USART_COUNT == 5)
+#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
+                                 ((ref) == USART2) || ((ref) == USART3) || \
+                                 ((ref) == USART4))
+#elif (USART_COUNT == 6)
+#define USART_REF_VALID(ref)    (((ref) == USART0) || ((ref) == USART1) || \
+                                 ((ref) == USART2) || ((ref) == USART3) || \
+                                 ((ref) == USART4) || ((ref) == USART5))
+#else
+#error "Undefined number of USARTs."
+#endif
+
+#if defined(USARTRF_COUNT) && (USARTRF_COUNT > 0)
+#if (USARTRF_COUNT == 1) && defined(USARTRF0)
+#define USARTRF_REF_VALID(ref)  ((ref) == USARTRF0)
+#elif (USARTRF_COUNT == 1) && defined(USARTRF1)
+#define USARTRF_REF_VALID(ref)  ((ref) == USARTRF1)
+#else
+#define USARTRF_REF_VALID(ref)  (0)
+#endif
+#else
+#define USARTRF_REF_VALID(ref)  (0)
+#endif
+
+#if defined(_EZR32_HAPPY_FAMILY)
+#define USART_IRDA_VALID(ref)    ((ref) == USART0)
+#elif defined(_EFM32_HAPPY_FAMILY)
+#define USART_IRDA_VALID(ref)    (((ref) == USART0) || ((ref) == USART1))
+#elif defined(USART0)
+#define USART_IRDA_VALID(ref)    ((ref) == USART0)
+#elif (USART_COUNT == 1) && defined(USART1)
+#define USART_IRDA_VALID(ref)    ((ref) == USART1)
+#else
+#define USART_IRDA_VALID(ref)    (0)
+#endif
+
+#if defined(_EZR32_HAPPY_FAMILY)
+#define USART_I2S_VALID(ref)    ((ref) == USART0)
+#elif defined(_EFM32_HAPPY_FAMILY)
+#define USART_I2S_VALID(ref)    (((ref) == USART0) || ((ref) == USART1))
+#elif defined(_EFM32_TINY_FAMILY) || defined(_EFM32_ZERO_FAMILY) || defined(_SILICON_LABS_32B_PLATFORM_2)
+#define USART_I2S_VALID(ref)    ((ref) == USART1)
+#elif defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
+#define USART_I2S_VALID(ref)    (((ref) == USART1) || ((ref) == USART2))
+#endif
+
+#if (UART_COUNT == 1)
+#define UART_REF_VALID(ref)    ((ref) == UART0)
+#elif (UART_COUNT == 2)
+#define UART_REF_VALID(ref)    (((ref) == UART0) || ((ref) == UART1))
+#else
+#define UART_REF_VALID(ref)    (0)
+#endif
+
+/** @endcond */
+
+
+/*******************************************************************************
+ **************************   GLOBAL FUNCTIONS   *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ *   Configure USART/UART operating in asynchronous mode to use a given
+ *   baudrate (or as close as possible to specified baudrate).
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @param[in] refFreq
+ *   USART/UART reference clock frequency in Hz that will be used. If set to 0,
+ *   the currently configured reference clock is assumed.
+ *
+ * @param[in] baudrate
+ *   Baudrate to try to achieve for USART/UART.
+ *
+ * @param[in] ovs
+ *   Oversampling to be used. Normal is 16x oversampling, but lower oversampling
+ *   may be used to achieve higher rates or better baudrate accuracy in some
+ *   cases. Notice that lower oversampling frequency makes channel more
+ *   vulnerable to bit faults during reception due to clock inaccuracies
+ *   compared to link partner.
+ ******************************************************************************/
+void USART_BaudrateAsyncSet(USART_TypeDef *usart,
+                            uint32_t refFreq,
+                            uint32_t baudrate,
+                            USART_OVS_TypeDef ovs)
+{
+  uint32_t clkdiv;
+  uint32_t oversample;
+
+  /* Inhibit divide by 0 */
+  EFM_ASSERT(baudrate);
+
+  /*
+   * We want to use integer division to avoid forcing in float division
+   * utils, and yet keep rounding effect errors to a minimum.
+   *
+   * CLKDIV in asynchronous mode is given by:
+   *
+   * CLKDIV = 256 * (fHFPERCLK/(oversample * br) - 1)
+   * or
+   * CLKDIV = (256 * fHFPERCLK)/(oversample * br) - 256
+   *
+   * The basic problem with integer division in the above formula is that
+   * the dividend (256 * fHFPERCLK) may become higher than max 32 bit
+   * integer. Yet, we want to evaluate dividend first before dividing in
+   * order to get as small rounding effects as possible. We do not want
+   * to make too harsh restrictions on max fHFPERCLK value either.
+   *
+   * One can possibly factorize 256 and oversample/br. However,
+   * since the last 6 or 3 bits of CLKDIV are don't care, we can base our
+   * integer arithmetic on the below formula
+   *
+   * CLKDIV / 64 = (4 * fHFPERCLK)/(oversample * br) - 4 (3 bits dont care)
+   * or
+   * CLKDIV / 8  = (32 * fHFPERCLK)/(oversample * br) - 32 (6 bits dont care)
+   *
+   * and calculate 1/64 of CLKDIV first. This allows for fHFPERCLK
+   * up to 1GHz without overflowing a 32 bit value!
+   */
+
+  /* HFPERCLK used to clock all USART/UART peripheral modules */
+  if (!refFreq)
+  {
+    refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
+  }
+
+  /* Map oversampling */
+  switch (ovs)
+  {
+    case USART_CTRL_OVS_X16:
+      EFM_ASSERT(baudrate <= (refFreq / 16));
+      oversample = 16;
+      break;
+
+    case USART_CTRL_OVS_X8:
+      EFM_ASSERT(baudrate <= (refFreq / 8));
+      oversample = 8;
+      break;
+
+    case USART_CTRL_OVS_X6:
+      EFM_ASSERT(baudrate <= (refFreq / 6));
+      oversample = 6;
+      break;
+
+    case USART_CTRL_OVS_X4:
+      EFM_ASSERT(baudrate <= (refFreq / 4));
+      oversample = 4;
+      break;
+
+    default:
+      /* Invalid input */
+      EFM_ASSERT(0);
+      return;
+  }
+
+  /* Calculate and set CLKDIV with fractional bits.
+   * The addend (oversample*baudrate)/2 in the first line is to round the
+   * divisor up by half the divisor before the division in order to reduce the
+   * integer division error, which consequently results in a higher baudrate
+   * than desired. */
+#if defined(_USART_CLKDIV_DIV_MASK) && (_USART_CLKDIV_DIV_MASK >= 0x7FFFF8UL)
+  clkdiv  = 32 * refFreq + (oversample * baudrate) / 2;
+  clkdiv /= (oversample * baudrate);
+  clkdiv -= 32;
+  clkdiv *= 8;
+#else
+  clkdiv  = 4 * refFreq + (oversample * baudrate) / 2;
+  clkdiv /= (oversample * baudrate);
+  clkdiv -= 4;
+  clkdiv *= 64;
+#endif
+
+  /* Verify that resulting clock divider is within limits */
+  EFM_ASSERT(clkdiv <= _USART_CLKDIV_DIV_MASK);
+
+  /* If EFM_ASSERT is not enabled, make sure we don't write to reserved bits */
+  clkdiv &= _USART_CLKDIV_DIV_MASK;
+
+  usart->CTRL  &= ~_USART_CTRL_OVS_MASK;
+  usart->CTRL  |= ovs;
+  usart->CLKDIV = clkdiv;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Calculate baudrate for USART/UART given reference frequency, clock division
+ *   and oversampling rate (if async mode).
+ *
+ * @details
+ *   This function returns the baudrate that a USART/UART module will use if
+ *   configured with the given frequency, clock divisor and mode. Notice that
+ *   this function will not use actual HW configuration. It can be used
+ *   to determinate if a given configuration is sufficiently accurate for the
+ *   application.
+ *
+ * @param[in] refFreq
+ *   USART/UART HF peripheral frequency used.
+ *
+ * @param[in] clkdiv
+ *   Clock division factor to be used.
+ *
+ * @param[in] syncmode
+ *   @li true - synchronous mode operation.
+ *   @li false - asynchronous mode operation.
+ *
+ * @param[in] ovs
+ *   Oversampling used if asynchronous mode. Not used if @p syncmode is true.
+ *
+ * @return
+ *   Baudrate with given settings.
+ ******************************************************************************/
+uint32_t USART_BaudrateCalc(uint32_t refFreq,
+                            uint32_t clkdiv,
+                            bool syncmode,
+                            USART_OVS_TypeDef ovs)
+{
+  uint32_t oversample;
+  uint64_t divisor;
+  uint64_t factor;
+  uint64_t remainder;
+  uint64_t quotient;
+  uint32_t br;
+
+  /* Mask out unused bits */
+  clkdiv &= _USART_CLKDIV_MASK;
+
+  /* We want to use integer division to avoid forcing in float division */
+  /* utils, and yet keep rounding effect errors to a minimum. */
+
+  /* Baudrate calculation depends on if synchronous or asynchronous mode */
+  if (syncmode)
+  {
+    /*
+     * Baudrate is given by:
+     *
+     * br = fHFPERCLK/(2 * (1 + (CLKDIV / 256)))
+     *
+     * which can be rewritten to
+     *
+     * br = (128 * fHFPERCLK)/(256 + CLKDIV)
+     */
+    oversample = 1; /* Not used in sync mode, ie 1 */
+    factor     = 128;
+  }
+  else
+  {
+    /*
+     * Baudrate in asynchronous mode is given by:
+     *
+     * br = fHFPERCLK/(oversample * (1 + (CLKDIV / 256)))
+     *
+     * which can be rewritten to
+     *
+     * br = (256 * fHFPERCLK)/(oversample * (256 + CLKDIV))
+     *
+     * First of all we can reduce the 256 factor of the dividend with
+     * (part of) oversample part of the divisor.
+     */
+
+    switch (ovs)
+    {
+      case USART_CTRL_OVS_X16:
+        oversample = 1;
+        factor     = 256 / 16;
+        break;
+
+      case USART_CTRL_OVS_X8:
+        oversample = 1;
+        factor     = 256 / 8;
+        break;
+
+      case USART_CTRL_OVS_X6:
+        oversample = 3;
+        factor     = 256 / 2;
+        break;
+
+      default:
+        oversample = 1;
+        factor     = 256 / 4;
+        break;
+    }
+  }
+
+  /*
+   * The basic problem with integer division in the above formula is that
+   * the dividend (factor * fHFPERCLK) may become larger than a 32 bit
+   * integer. Yet we want to evaluate dividend first before dividing in
+   * order to get as small rounding effects as possible. We do not want
+   * to make too harsh restrictions on max fHFPERCLK value either.
+   *
+   * For division a/b, we can write
+   *
+   * a = qb + r
+   *
+   * where q is the quotient and r is the remainder, both integers.
+   *
+   * The orignal baudrate formula can be rewritten as
+   *
+   * br = xa / b = x(qb + r)/b = xq + xr/b
+   *
+   * where x is 'factor', a is 'refFreq' and b is 'divisor', referring to
+   * variable names.
+   */
+
+  /* Divisor will never exceed max 32 bit value since clkdiv <= 0xFFFFF8 */
+  /* and 'oversample' has been reduced to <= 3. */
+  divisor = oversample * (256 + clkdiv);
+
+  quotient  = refFreq / divisor;
+  remainder = refFreq % divisor;
+
+  /* factor <= 128 and since divisor >= 256, the below cannot exceed max */
+  /* 32 bit value. However, factor * remainder can become larger than 32-bit */
+  /* because of the size of _USART_CLKDIV_DIV_MASK on some families. */
+  br = (uint32_t)(factor * quotient);
+
+  /*
+   * factor <= 128 and remainder < (oversample*(256 + clkdiv)), which
+   * means dividend (factor * remainder) worst case is
+   * 128 * (3 * (256 + _USART_CLKDIV_DIV_MASK)) = 0x1_8001_7400.
+   */
+  br += (uint32_t)((factor * remainder) / divisor);
+
+  return br;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Get current baudrate for USART/UART.
+ *
+ * @details
+ *   This function returns the actual baudrate (not considering oscillator
+ *   inaccuracies) used by a USART/UART peripheral.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @return
+ *   Current baudrate.
+ ******************************************************************************/
+uint32_t USART_BaudrateGet(USART_TypeDef *usart)
+{
+  uint32_t          freq;
+  USART_OVS_TypeDef ovs;
+  bool              syncmode;
+
+  if (usart->CTRL & USART_CTRL_SYNC)
+  {
+    syncmode = true;
+  }
+  else
+  {
+    syncmode = false;
+  }
+
+  /* HFPERCLK used to clock all USART/UART peripheral modules */
+  freq = CMU_ClockFreqGet(cmuClock_HFPER);
+  ovs  = (USART_OVS_TypeDef)(usart->CTRL & _USART_CTRL_OVS_MASK);
+  return USART_BaudrateCalc(freq, usart->CLKDIV, syncmode, ovs);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Configure USART operating in synchronous mode to use a given baudrate
+ *   (or as close as possible to specified baudrate).
+ *
+ * @details
+ *   The configuration will be set to use a baudrate <= the specified baudrate
+ *   in order to ensure that the baudrate does not exceed the specified value.
+ *
+ *   Fractional clock division is suppressed, although the HW design allows it.
+ *   It could cause half clock cycles to exceed specified limit, and thus
+ *   potentially violate specifications for the slave device. In some special
+ *   situations fractional clock division may be useful even in synchronous
+ *   mode, but in those cases it must be directly adjusted, possibly assisted
+ *   by USART_BaudrateCalc():
+ *
+ * @param[in] usart
+ *   Pointer to USART peripheral register block. (Cannot be used on UART
+ *   modules.)
+ *
+ * @param[in] refFreq
+ *   USART reference clock frequency in Hz that will be used. If set to 0,
+ *   the currently configured reference clock is assumed.
+ *
+ * @param[in] baudrate
+ *   Baudrate to try to achieve for USART.
+ ******************************************************************************/
+void USART_BaudrateSyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate)
+{
+#if defined(_USART_CLKDIV_DIV_MASK) && (_USART_CLKDIV_DIV_MASK >= 0x7FFFF8UL)
+  uint64_t clkdiv;
+#else
+  uint32_t clkdiv;
+#endif
+
+  /* Inhibit divide by 0 */
+  EFM_ASSERT(baudrate);
+
+  /*
+   * CLKDIV in synchronous mode is given by:
+   *
+   * CLKDIV = 256 * (fHFPERCLK/(2 * br) - 1)
+   */
+
+  /* HFPERCLK used to clock all USART/UART peripheral modules */
+  if (!refFreq)
+  {
+    refFreq = CMU_ClockFreqGet(cmuClock_HFPER);
+  }
+
+#if defined(_USART_CLKDIV_DIV_MASK) && (_USART_CLKDIV_DIV_MASK >= 0x7FFFF8UL)
+  /* Calculate and set CLKDIV without fractional bits */
+  clkdiv = 2 * baudrate;
+  clkdiv = (0x100ULL * (uint64_t)refFreq) / clkdiv;
+
+  /* Round up by not subtracting 256 and mask off fractional part */
+  clkdiv &= ~0xFF;
+#else
+  /* Calculate and set CLKDIV with fractional bits */
+  clkdiv  = 2 * refFreq;
+  clkdiv += baudrate - 1;
+  clkdiv /= baudrate;
+  clkdiv -= 4;
+  clkdiv *= 64;
+  /* Make sure we don't use fractional bits by rounding CLKDIV */
+  /* up (and thus reducing baudrate, not increasing baudrate above */
+  /* specified value). */
+  clkdiv += 0xc0;
+  clkdiv &= 0xffffff00;
+#endif
+
+  /* Verify that resulting clock divider is within limits */
+  EFM_ASSERT(!(clkdiv & ~_USART_CLKDIV_DIV_MASK));
+
+  /* If EFM_ASSERT is not enabled, make sure we don't write to reserved bits */
+  clkdiv &= _USART_CLKDIV_DIV_MASK;
+
+  BUS_RegMaskedWrite(&usart->CLKDIV, _USART_CLKDIV_DIV_MASK, clkdiv);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Enable/disable USART/UART receiver and/or transmitter.
+ *
+ * @details
+ *   Notice that this function does not do any configuration. Enabling should
+ *   normally be done after initialization is done (if not enabled as part
+ *   of init).
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @param[in] enable
+ *   Select status for receiver/transmitter.
+ ******************************************************************************/
+void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
+{
+  uint32_t tmp;
+
+  /* Make sure the module exists on the selected chip */
+  EFM_ASSERT( USART_REF_VALID(usart)
+              || USARTRF_REF_VALID(usart)
+              || UART_REF_VALID(usart) );
+
+  /* Disable as specified */
+  tmp        = ~((uint32_t) (enable));
+  tmp       &= _USART_CMD_RXEN_MASK | _USART_CMD_TXEN_MASK;
+  usart->CMD = tmp << 1;
+
+  /* Enable as specified */
+  usart->CMD = (uint32_t) (enable);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Init USART/UART for normal asynchronous mode.
+ *
+ * @details
+ *   This function will configure basic settings in order to operate in normal
+ *   asynchronous mode.
+ *
+ *   Special control setup not covered by this function must be done after
+ *   using this function by direct modification of the CTRL register.
+ *
+ *   Notice that pins used by the USART/UART module must be properly configured
+ *   by the user explicitly, in order for the USART/UART to work as intended.
+ *   (When configuring pins, one should remember to consider the sequence of
+ *   configuration, in order to avoid unintended pulses/glitches on output
+ *   pins.)
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @param[in] init
+ *   Pointer to initialization structure used to configure basic async setup.
+ ******************************************************************************/
+void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
+{
+  /* Make sure the module exists on the selected chip */
+  EFM_ASSERT( USART_REF_VALID(usart)
+              || USARTRF_REF_VALID(usart)
+              || UART_REF_VALID(usart) );
+
+  /* Init USART registers to HW reset state. */
+  USART_Reset(usart);
+
+#if defined(USART_INPUT_RXPRS) && defined(USART_CTRL_MVDIS)
+  /* Disable majority vote if specified. */
+  if (init->mvdis)
+  {
+    usart->CTRL |= USART_CTRL_MVDIS;
+  }
+
+  /* Configure PRS input mode. */
+  if (init->prsRxEnable)
+  {
+    usart->INPUT = (uint32_t) init->prsRxCh | USART_INPUT_RXPRS;
+  }
+#endif
+
+  /* Configure databits, stopbits and parity */
+  usart->FRAME = (uint32_t)init->databits
+                 | (uint32_t)init->stopbits
+                 | (uint32_t)init->parity;
+
+  /* Configure baudrate */
+  USART_BaudrateAsyncSet(usart, init->refFreq, init->baudrate, init->oversampling);
+
+#if defined(_USART_TIMING_CSHOLD_MASK)
+  usart->TIMING = ((init->autoCsHold << _USART_TIMING_CSHOLD_SHIFT)
+                   & _USART_TIMING_CSHOLD_MASK)
+                  | ((init->autoCsSetup << _USART_TIMING_CSSETUP_SHIFT)
+                     & _USART_TIMING_CSSETUP_MASK);
+  if (init->autoCsEnable)
+  {
+    usart->CTRL |= USART_CTRL_AUTOCS;
+  }
+#endif
+  /* Finally enable (as specified) */
+  usart->CMD = (uint32_t)init->enable;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Init USART for synchronous mode.
+ *
+ * @details
+ *   This function will configure basic settings in order to operate in
+ *   synchronous mode.
+ *
+ *   Special control setup not covered by this function must be done after
+ *   using this function by direct modification of the CTRL register.
+ *
+ *   Notice that pins used by the USART module must be properly configured
+ *   by the user explicitly, in order for the USART to work as intended.
+ *   (When configuring pins, one should remember to consider the sequence of
+ *   configuration, in order to avoid unintended pulses/glitches on output
+ *   pins.)
+ *
+ * @param[in] usart
+ *   Pointer to USART peripheral register block. (UART does not support this
+ *   mode.)
+ *
+ * @param[in] init
+ *   Pointer to initialization structure used to configure basic async setup.
+ ******************************************************************************/
+void USART_InitSync(USART_TypeDef *usart, const USART_InitSync_TypeDef *init)
+{
+  /* Make sure the module exists on the selected chip */
+  EFM_ASSERT( USART_REF_VALID(usart) || USARTRF_REF_VALID(usart) );
+
+  /* Init USART registers to HW reset state. */
+  USART_Reset(usart);
+
+  /* Set bits for synchronous mode */
+  usart->CTRL |= (USART_CTRL_SYNC)
+                 | (uint32_t)init->clockMode
+                 | (init->msbf ? USART_CTRL_MSBF : 0);
+
+#if defined(_USART_CTRL_AUTOTX_MASK)
+  usart->CTRL |= init->autoTx ? USART_CTRL_AUTOTX : 0;
+#endif
+
+#if defined(_USART_INPUT_RXPRS_MASK)
+  /* Configure PRS input mode. */
+  if (init->prsRxEnable)
+  {
+    usart->INPUT = (uint32_t)init->prsRxCh | USART_INPUT_RXPRS;
+  }
+#endif
+
+  /* Configure databits, leave stopbits and parity at reset default (not used) */
+  usart->FRAME = (uint32_t)init->databits
+                 | USART_FRAME_STOPBITS_DEFAULT
+                 | USART_FRAME_PARITY_DEFAULT;
+
+  /* Configure baudrate */
+  USART_BaudrateSyncSet(usart, init->refFreq, init->baudrate);
+
+  /* Finally enable (as specified) */
+  if (init->master)
+  {
+    usart->CMD = USART_CMD_MASTEREN;
+  }
+
+#if defined(_USART_TIMING_CSHOLD_MASK)
+  usart->TIMING = ((init->autoCsHold << _USART_TIMING_CSHOLD_SHIFT)
+                   & _USART_TIMING_CSHOLD_MASK)
+                  | ((init->autoCsSetup << _USART_TIMING_CSSETUP_SHIFT)
+                     & _USART_TIMING_CSSETUP_MASK);
+  if (init->autoCsEnable)
+  {
+    usart->CTRL |= USART_CTRL_AUTOCS;
+  }
+#endif
+
+  usart->CMD = (uint32_t)init->enable;
+}
+
+
+#if defined(USART0) || ((USART_COUNT == 1) && defined(USART1))
+/***************************************************************************//**
+ * @brief
+ *   Init USART0 for asynchronous IrDA mode.
+ *
+ * @details
+ *   This function will configure basic settings in order to operate in
+ *   asynchronous IrDA mode.
+ *
+ *   Special control setup not covered by this function must be done after
+ *   using this function by direct modification of the CTRL and IRCTRL
+ *   registers.
+ *
+ *   Notice that pins used by the USART/UART module must be properly configured
+ *   by the user explicitly, in order for the USART/UART to work as intended.
+ *   (When configuring pins, one should remember to consider the sequence of
+ *   configuration, in order to avoid unintended pulses/glitches on output
+ *   pins.)
+ *
+ * @param[in] init
+ *   Pointer to initialization structure used to configure async IrDA setup.
+ *
+ * @note
+ *   This function only applies to USART0 as IrDA is not supported on the other
+ *   USART modules.
+ *
+ ******************************************************************************/
+void USART_InitIrDA(const USART_InitIrDA_TypeDef *init)
+{
+  #if (USART_COUNT == 1) && defined(USART1)
+  USART_TypeDef *usart = USART1;
+  #else
+  USART_TypeDef *usart = USART0;
+  #endif
+
+  /* Init USART as async device */
+  USART_InitAsync(usart, &(init->async));
+
+  /* Set IrDA modulation to RZI (return-to-zero-inverted) */
+  usart->CTRL |= USART_CTRL_TXINV;
+
+  /* Invert Rx signal before demodulator if enabled */
+  if (init->irRxInv)
+  {
+    usart->CTRL |= USART_CTRL_RXINV;
+  }
+
+  /* Configure IrDA */
+  usart->IRCTRL |= (uint32_t)init->irPw
+                   | (uint32_t)init->irPrsSel
+                   | ((uint32_t)init->irFilt << _USART_IRCTRL_IRFILT_SHIFT)
+                   | ((uint32_t)init->irPrsEn << _USART_IRCTRL_IRPRSEN_SHIFT);
+
+  /* Enable IrDA */
+  usart->IRCTRL |= USART_IRCTRL_IREN;
+}
+#endif
+
+
+#if defined(_USART_I2SCTRL_MASK)
+/***************************************************************************//**
+ * @brief
+ *   Init USART for I2S mode.
+ *
+ * @details
+ *   This function will configure basic settings in order to operate in I2S
+ *   mode.
+ *
+ *   Special control setup not covered by this function must be done after
+ *   using this function by direct modification of the CTRL and I2SCTRL
+ *   registers.
+ *
+ *   Notice that pins used by the USART module must be properly configured
+ *   by the user explicitly, in order for the USART to work as intended.
+ *   (When configuring pins, one should remember to consider the sequence of
+ *   configuration, in order to avoid unintended pulses/glitches on output
+ *   pins.)
+ *
+ * @param[in] usart
+ *   Pointer to USART peripheral register block. (UART does not support this
+ *   mode.)
+ *
+ * @param[in] init
+ *   Pointer to initialization structure used to configure basic I2S setup.
+ *
+ * @note
+ *   This function does not apply to all USART's. Refer to chip manuals.
+ *
+ ******************************************************************************/
+void USART_InitI2s(USART_TypeDef *usart, USART_InitI2s_TypeDef *init)
+{
+  USART_Enable_TypeDef enable;
+
+  /* Make sure the module exists on the selected chip */
+  EFM_ASSERT(USART_I2S_VALID(usart));
+
+  /* Override the enable setting. */
+  enable            = init->sync.enable;
+  init->sync.enable = usartDisable;
+
+  /* Init USART as a sync device. */
+  USART_InitSync(usart, &init->sync);
+
+  /* Configure and enable I2CCTRL register acording to selected mode. */
+  usart->I2SCTRL = (uint32_t)init->format
+                   | (uint32_t)init->justify
+                   | (init->delay    ? USART_I2SCTRL_DELAY    : 0)
+                   | (init->dmaSplit ? USART_I2SCTRL_DMASPLIT : 0)
+                   | (init->mono     ? USART_I2SCTRL_MONO     : 0)
+                   | USART_I2SCTRL_EN;
+
+  if (enable != usartDisable)
+  {
+    USART_Enable(usart, enable);
+  }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ *   Initialize automatic transmissions using PRS channel as trigger
+ * @note
+ *   Initialize USART with USART_Init() before setting up PRS configuration
+ *
+ * @param[in] usart Pointer to USART to configure
+ * @param[in] init Pointer to initialization structure
+ ******************************************************************************/
+void USART_InitPrsTrigger(USART_TypeDef *usart, const USART_PrsTriggerInit_TypeDef *init)
+{
+  uint32_t trigctrl;
+
+  /* Clear values that will be reconfigured  */
+  trigctrl = usart->TRIGCTRL & ~(_USART_TRIGCTRL_RXTEN_MASK
+                                 | _USART_TRIGCTRL_TXTEN_MASK
+#if defined(USART_TRIGCTRL_AUTOTXTEN)
+                                 | _USART_TRIGCTRL_AUTOTXTEN_MASK
+#endif
+                                 | _USART_TRIGCTRL_TSEL_MASK);
+
+#if defined(USART_TRIGCTRL_AUTOTXTEN)
+  if (init->autoTxTriggerEnable)
+  {
+    trigctrl |= USART_TRIGCTRL_AUTOTXTEN;
+  }
+#endif
+  if (init->txTriggerEnable)
+  {
+    trigctrl |= USART_TRIGCTRL_TXTEN;
+  }
+  if (init->rxTriggerEnable)
+  {
+    trigctrl |= USART_TRIGCTRL_RXTEN;
+  }
+  trigctrl |= init->prsTriggerChannel;
+
+  /* Enable new configuration */
+  usart->TRIGCTRL = trigctrl;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Reset USART/UART to same state as after a HW reset.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ ******************************************************************************/
+void USART_Reset(USART_TypeDef *usart)
+{
+  /* Make sure the module exists on the selected chip */
+  EFM_ASSERT( USART_REF_VALID(usart)
+              || USARTRF_REF_VALID(usart)
+              || UART_REF_VALID(usart) );
+
+  /* Make sure disabled first, before resetting other registers */
+  usart->CMD = USART_CMD_RXDIS | USART_CMD_TXDIS | USART_CMD_MASTERDIS
+               | USART_CMD_RXBLOCKDIS | USART_CMD_TXTRIDIS | USART_CMD_CLEARTX
+               | USART_CMD_CLEARRX;
+  usart->CTRL      = _USART_CTRL_RESETVALUE;
+  usart->FRAME     = _USART_FRAME_RESETVALUE;
+  usart->TRIGCTRL  = _USART_TRIGCTRL_RESETVALUE;
+  usart->CLKDIV    = _USART_CLKDIV_RESETVALUE;
+  usart->IEN       = _USART_IEN_RESETVALUE;
+  usart->IFC       = _USART_IFC_MASK;
+#if defined(_USART_ROUTEPEN_MASK) || defined(_UART_ROUTEPEN_MASK)
+  usart->ROUTEPEN  = _USART_ROUTEPEN_RESETVALUE;
+  usart->ROUTELOC0 = _USART_ROUTELOC0_RESETVALUE;
+  usart->ROUTELOC1 = _USART_ROUTELOC1_RESETVALUE;
+#else
+  usart->ROUTE     = _USART_ROUTE_RESETVALUE;
+#endif
+
+  if (USART_IRDA_VALID(usart))
+  {
+    usart->IRCTRL = _USART_IRCTRL_RESETVALUE;
+  }
+
+#if defined(_USART_INPUT_RESETVALUE)
+  usart->INPUT = _USART_INPUT_RESETVALUE;
+#endif
+
+#if defined(_USART_I2SCTRL_RESETVALUE)
+  if (USART_I2S_VALID(usart))
+  {
+    usart->I2SCTRL = _USART_I2SCTRL_RESETVALUE;
+  }
+#endif
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Receive one 4-8 bit frame, (or part of 10-16 bit frame).
+ *
+ * @details
+ *   This function is normally used to receive one frame when operating with
+ *   frame length 4-8 bits. Please refer to @ref USART_RxExt() for reception of
+ *   9 bit frames.
+ *
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if the buffer is empty, until data is received.
+ *   Alternatively the user can explicitly check whether data is available, and
+ *   if data is avaliable, call @ref USART_RxDataGet() to read the RXDATA
+ *   register directly.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @return
+ *   Data received.
+ ******************************************************************************/
+uint8_t USART_Rx(USART_TypeDef *usart)
+{
+  while (!(usart->STATUS & USART_STATUS_RXDATAV))
+    ;
+
+  return (uint8_t)usart->RXDATA;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Receive two 4-8 bit frames, or one 10-16 bit frame.
+ *
+ * @details
+ *   This function is normally used to receive one frame when operating with
+ *   frame length 10-16 bits. Please refer to @ref USART_RxDoubleExt() for
+ *   reception of two 9 bit frames.
+ *
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if buffer is empty, until data is received.
+ *   Alternatively the user can explicitly check whether data is available, and
+ *   if data is avaliable, call @ref USART_RxDoubleGet() to read the RXDOUBLE
+ *   register directly.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @return
+ *   Data received.
+ ******************************************************************************/
+uint16_t USART_RxDouble(USART_TypeDef *usart)
+{
+  while (!(usart->STATUS & USART_STATUS_RXFULL))
+    ;
+
+  return (uint16_t)usart->RXDOUBLE;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Receive two 4-9 bit frames, or one 10-16 bit frame with extended
+ *   information.
+ *
+ * @details
+ *   This function is normally used to receive one frame when operating with
+ *   frame length 10-16 bits and additional RX status information is required.
+ *
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if buffer is empty, until data is received.
+ *   Alternatively the user can explicitly check whether data is available, and
+ *   if data is avaliable, call @ref USART_RxDoubleXGet() to read the RXDOUBLEX
+ *   register directly.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @return
+ *   Data received.
+ ******************************************************************************/
+uint32_t USART_RxDoubleExt(USART_TypeDef *usart)
+{
+  while (!(usart->STATUS & USART_STATUS_RXFULL))
+    ;
+
+  return usart->RXDOUBLEX;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Receive one 4-9 bit frame, (or part of 10-16 bit frame) with extended
+ *   information.
+ *
+ * @details
+ *   This function is normally used to receive one frame when operating with
+ *   frame length 4-9 bits and additional RX status information is required.
+ *
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if buffer is empty, until data is received.
+ *   Alternatively the user can explicitly check whether data is available, and
+ *   if data is avaliable, call @ref USART_RxDataXGet() to read the RXDATAX
+ *   register directly.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @return
+ *   Data received.
+ ******************************************************************************/
+uint16_t USART_RxExt(USART_TypeDef *usart)
+{
+  while (!(usart->STATUS & USART_STATUS_RXDATAV))
+    ;
+
+  return (uint16_t)usart->RXDATAX;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Perform one 8 bit frame SPI transfer.
+ *
+ * @note
+ *   This function will stall if the transmit buffer is full. When a transmit
+ *   buffer becomes available, data is written and the function will wait until
+ *   the data is fully transmitted. The SPI return value is then read out and
+ *   returned.
+ *
+ * @param[in] usart
+ *   Pointer to USART peripheral register block.
+ *
+ * @param[in] data
+ *   Data to transmit.
+ *
+ * @return
+ *   Data received.
+ ******************************************************************************/
+uint8_t USART_SpiTransfer(USART_TypeDef *usart, uint8_t data)
+{
+  while (!(usart->STATUS & USART_STATUS_TXBL))
+    ;
+  usart->TXDATA = (uint32_t)data;
+  while (!(usart->STATUS & USART_STATUS_TXC))
+    ;
+  return (uint8_t)usart->RXDATA;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Transmit one 4-9 bit frame.
+ *
+ * @details
+ *   Depending on frame length configuration, 4-8 (least significant) bits from
+ *   @p data are transmitted. If frame length is 9, 8 bits are transmitted from
+ *   @p data and one bit as specified by CTRL register, BIT8DV field. Please
+ *   refer to USART_TxExt() for transmitting 9 bit frame with full control of
+ *   all 9 bits.
+ *
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if buffer is full, until buffer becomes available.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @param[in] data
+ *   Data to transmit. See details above for further info.
+ ******************************************************************************/
+void USART_Tx(USART_TypeDef *usart, uint8_t data)
+{
+  /* Check that transmit buffer is empty */
+  while (!(usart->STATUS & USART_STATUS_TXBL))
+    ;
+  usart->TXDATA = (uint32_t)data;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Transmit two 4-9 bit frames, or one 10-16 bit frame.
+ *
+ * @details
+ *   Depending on frame length configuration, 4-8 (least significant) bits from
+ *   each byte in @p data are transmitted. If frame length is 9, 8 bits are
+ *   transmitted from each byte in @p data adding one bit as specified by CTRL
+ *   register, BIT8DV field, to each byte. Please refer to USART_TxDoubleExt()
+ *   for transmitting two 9 bit frames with full control of all 9 bits.
+ *
+ *   If frame length is 10-16, 10-16 (least significant) bits from @p data
+ *   are transmitted.
+ *
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if buffer is full, until buffer becomes available.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @param[in] data
+ *   Data to transmit, the least significant byte holds the frame transmitted
+ *   first. See details above for further info.
+ ******************************************************************************/
+void USART_TxDouble(USART_TypeDef *usart, uint16_t data)
+{
+  /* Check that transmit buffer is empty */
+  while (!(usart->STATUS & USART_STATUS_TXBL))
+    ;
+  usart->TXDOUBLE = (uint32_t)data;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Transmit two 4-9 bit frames, or one 10-16 bit frame with extended control.
+ *
+ * @details
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if buffer is full, until buffer becomes available.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @param[in] data
+ *   Data to transmit with extended control. Contains two 16 bit words
+ *   concatenated. Least significant word holds frame transitted first. If frame
+ *   length is 4-9, two frames with 4-9 least significant bits from each 16 bit
+ *   word are transmitted.
+ * @par
+ *   If frame length is 10-16 bits, 8 data bits are taken from the least
+ *   significant 16 bit word, and the remaining bits from the other 16 bit word.
+ * @par
+ *   Additional control bits are available as documented in the reference
+ *   manual (set to 0 if not used). For 10-16 bit frame length, these control
+ *   bits are taken from the most significant 16 bit word.
+ ******************************************************************************/
+void USART_TxDoubleExt(USART_TypeDef *usart, uint32_t data)
+{
+  /* Check that transmit buffer is empty */
+  while (!(usart->STATUS & USART_STATUS_TXBL))
+    ;
+  usart->TXDOUBLEX = data;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Transmit one 4-9 bit frame with extended control.
+ *
+ * @details
+ *   Notice that possible parity/stop bits in asynchronous mode are not
+ *   considered part of specified frame bit length.
+ *
+ * @note
+ *   This function will stall if buffer is full, until buffer becomes available.
+ *
+ * @param[in] usart
+ *   Pointer to USART/UART peripheral register block.
+ *
+ * @param[in] data
+ *   Data to transmit with extended control. Least significant bits contains
+ *   frame bits, and additional control bits are available as documented in
+ *   the reference manual (set to 0 if not used).
+ ******************************************************************************/
+void USART_TxExt(USART_TypeDef *usart, uint16_t data)
+{
+  /* Check that transmit buffer is empty */
+  while (!(usart->STATUS & USART_STATUS_TXBL))
+    ;
+  usart->TXDATAX = (uint32_t)data;
+}
+
+
+/** @} (end addtogroup USART) */
+/** @} (end addtogroup EM_Library) */
+#endif /* defined(USART_COUNT) && (USART_COUNT > 0) */