2013-01-08 22:40:58 +08:00
|
|
|
/***************************************************************************//**
|
|
|
|
* @file
|
|
|
|
* @brief Low Energy Universal Asynchronous Receiver/Transmitter (LEUART)
|
|
|
|
* Peripheral API
|
|
|
|
* @author Energy Micro AS
|
|
|
|
* @version 3.0.0
|
|
|
|
*******************************************************************************
|
|
|
|
* @section License
|
|
|
|
* <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.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: Energy Micro AS has no
|
|
|
|
* obligation to support this Software. Energy Micro AS 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.
|
|
|
|
*
|
|
|
|
* Energy Micro AS 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_leuart.h"
|
|
|
|
#include "em_cmu.h"
|
|
|
|
#include "em_assert.h"
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @addtogroup EM_Library
|
|
|
|
* @{
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @addtogroup LEUART
|
|
|
|
* @brief Low Energy Universal Asynchronous Receiver/Transmitter (LEUART)
|
|
|
|
* Peripheral API
|
|
|
|
* @{
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
******************************* DEFINES ***********************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
|
|
|
|
|
|
|
|
|
|
|
/** Validation of LEUART register block pointer reference
|
|
|
|
* for assert statements. */
|
|
|
|
#if (LEUART_COUNT == 1)
|
|
|
|
#define LEUART_REF_VALID(ref) ((ref) == LEUART0)
|
|
|
|
#elif (LEUART_COUNT == 2)
|
|
|
|
#define LEUART_REF_VALID(ref) (((ref) == LEUART0) || ((ref) == LEUART1))
|
|
|
|
#else
|
|
|
|
#error Undefined number of low energy UARTs (LEUART).
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/** @endcond */
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
************************** LOCAL FUNCTIONS ********************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Wait for ongoing sync of register(s) to low frequency domain to complete.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block
|
|
|
|
*
|
|
|
|
* @param[in] mask
|
|
|
|
* Bitmask corresponding to SYNCBUSY register defined bits, indicating
|
|
|
|
* registers that must complete any ongoing synchronization.
|
|
|
|
******************************************************************************/
|
|
|
|
__STATIC_INLINE void LEUART_Sync(LEUART_TypeDef *leuart, uint32_t mask)
|
|
|
|
{
|
|
|
|
/* Avoid deadlock if modifying the same register twice when freeze mode is */
|
|
|
|
/* activated. */
|
|
|
|
if (leuart->FREEZE & LEUART_FREEZE_REGFREEZE)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait for any pending previous write operation to have been completed */
|
|
|
|
/* in low frequency domain */
|
|
|
|
while (leuart->SYNCBUSY & mask)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @endcond */
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
************************** GLOBAL FUNCTIONS *******************************
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Calculate baudrate for LEUART given reference frequency and clock division.
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* This function returns the baudrate that a LEUART module will use if
|
|
|
|
* configured with the given frequency and clock divisor. 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
|
|
|
|
* LEUART peripheral frequency used.
|
|
|
|
*
|
|
|
|
* @param[in] clkdiv
|
|
|
|
* Clock division factor to be used.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* Baudrate with given settings.
|
|
|
|
******************************************************************************/
|
|
|
|
uint32_t LEUART_BaudrateCalc(uint32_t refFreq, uint32_t clkdiv)
|
|
|
|
{
|
|
|
|
uint32_t divisor;
|
|
|
|
uint32_t remainder;
|
|
|
|
uint32_t quotient;
|
|
|
|
uint32_t br;
|
|
|
|
|
|
|
|
/* Mask out unused bits */
|
|
|
|
clkdiv &= _LEUART_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 is given by:
|
|
|
|
*
|
|
|
|
* br = fLEUARTn/(1 + (CLKDIV / 256))
|
|
|
|
*
|
|
|
|
* which can be rewritten to
|
|
|
|
*
|
|
|
|
* br = (256 * fLEUARTn)/(256 + CLKDIV)
|
|
|
|
*
|
|
|
|
* Normally, with fLEUARTn appr 32768Hz, there is no problem with overflow
|
|
|
|
* if using 32 bit arithmetic. However, since fLEUARTn may be derived from
|
|
|
|
* HFCORECLK as well, we must consider overflow when using integer arithmetic.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The basic problem with integer division in the above formula is that
|
|
|
|
* the dividend (256 * fLEUARTn) 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 fLEUARTn 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 = 256a / b = 256(qb + r)/b = 256q + 256r/b
|
|
|
|
*
|
|
|
|
* where a is 'refFreq' and b is 'divisor', referring to variable names.
|
|
|
|
*/
|
|
|
|
|
|
|
|
divisor = 256 + clkdiv;
|
|
|
|
|
|
|
|
quotient = refFreq / divisor;
|
|
|
|
remainder = refFreq % divisor;
|
|
|
|
|
|
|
|
/* Since divisor >= 256, the below cannot exceed max 32 bit value. */
|
|
|
|
br = 256 * quotient;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remainder < (256 + clkdiv), which means dividend (256 * remainder) worst case is
|
|
|
|
* 256*(256 + 0x7ff8) = 0x80F800.
|
|
|
|
*/
|
|
|
|
br += (256 * remainder) / divisor;
|
|
|
|
|
|
|
|
return br;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Get current baudrate for LEUART.
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* This function returns the actual baudrate (not considering oscillator
|
|
|
|
* inaccuracies) used by a LEUART peripheral.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* Current baudrate.
|
|
|
|
******************************************************************************/
|
|
|
|
uint32_t LEUART_BaudrateGet(LEUART_TypeDef *leuart)
|
|
|
|
{
|
|
|
|
uint32_t freq;
|
|
|
|
CMU_Clock_TypeDef clock;
|
|
|
|
|
|
|
|
/* Get current frequency */
|
|
|
|
if (leuart == LEUART0)
|
|
|
|
{
|
|
|
|
clock = cmuClock_LEUART0;
|
|
|
|
}
|
|
|
|
#if (LEUART_COUNT > 1)
|
|
|
|
else if (leuart == LEUART1)
|
|
|
|
{
|
|
|
|
clock = cmuClock_LEUART1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EFM_ASSERT(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
freq = CMU_ClockFreqGet(clock);
|
|
|
|
|
|
|
|
return LEUART_BaudrateCalc(freq, leuart->CLKDIV);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Configure baudrate (or as close as possible to specified baudrate).
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* The setting of a baudrate requires synchronization into the
|
|
|
|
* low frequency domain. If the same register is modified before a previous
|
|
|
|
* update has completed, this function will stall until the previous
|
|
|
|
* synchronization has completed.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @param[in] refFreq
|
|
|
|
* LEUART 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 LEUART.
|
|
|
|
******************************************************************************/
|
|
|
|
void LEUART_BaudrateSet(LEUART_TypeDef *leuart,
|
|
|
|
uint32_t refFreq,
|
|
|
|
uint32_t baudrate)
|
|
|
|
{
|
|
|
|
uint32_t clkdiv;
|
|
|
|
CMU_Clock_TypeDef clock;
|
|
|
|
|
|
|
|
/* 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*(fLEUARTn/br - 1) = ((256*fLEUARTn)/br) - 256
|
|
|
|
*
|
|
|
|
* Normally, with fLEUARTn appr 32768Hz, there is no problem with overflow
|
|
|
|
* if using 32 bit arithmetic. However, since fLEUARTn may be derived from
|
|
|
|
* HFCORECLK as well, we must consider overflow when using integer arithmetic.
|
|
|
|
*
|
|
|
|
* The basic problem with integer division in the above formula is that
|
|
|
|
* the dividend (256 * fLEUARTn) 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 fLEUARTn value either.
|
|
|
|
*
|
|
|
|
* Since the last 3 bits of CLKDIV are don't care, we can base our
|
|
|
|
* integer arithmetic on the below formula
|
|
|
|
*
|
|
|
|
* CLKDIV/8 = ((32*fLEUARTn)/br) - 32
|
|
|
|
*
|
|
|
|
* and calculate 1/8 of CLKDIV first. This allows for fLEUARTn
|
|
|
|
* up to 128MHz without overflowing a 32 bit value!
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Get current frequency? */
|
|
|
|
if (!refFreq)
|
|
|
|
{
|
|
|
|
if (leuart == LEUART0)
|
|
|
|
{
|
|
|
|
clock = cmuClock_LEUART0;
|
|
|
|
}
|
|
|
|
#if (LEUART_COUNT > 1)
|
|
|
|
else if (leuart == LEUART1)
|
|
|
|
{
|
|
|
|
clock = cmuClock_LEUART1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EFM_ASSERT(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
refFreq = CMU_ClockFreqGet(clock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate and set CLKDIV with fractional bits */
|
|
|
|
clkdiv = (32 * refFreq) / baudrate;
|
|
|
|
clkdiv -= 32;
|
|
|
|
clkdiv *= 8;
|
|
|
|
|
|
|
|
/* LF register about to be modified require sync. busy check */
|
|
|
|
LEUART_Sync(leuart, LEUART_SYNCBUSY_CLKDIV);
|
|
|
|
|
|
|
|
leuart->CLKDIV = clkdiv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Enable/disable LEUART 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).
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* Enabling/disabling requires synchronization into the low frequency domain.
|
|
|
|
* If the same register is modified before a previous update has completed,
|
|
|
|
* this function will stall until the previous synchronization has completed.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @param[in] enable
|
|
|
|
* Select status for receiver/transmitter.
|
|
|
|
******************************************************************************/
|
|
|
|
void LEUART_Enable(LEUART_TypeDef *leuart, LEUART_Enable_TypeDef enable)
|
|
|
|
{
|
|
|
|
uint32_t tmp;
|
|
|
|
|
|
|
|
/* Make sure the module exists on the selected chip */
|
|
|
|
EFM_ASSERT(LEUART_REF_VALID(leuart));
|
|
|
|
|
|
|
|
/* Disable as specified */
|
|
|
|
tmp = ~((uint32_t)(enable));
|
|
|
|
tmp &= (_LEUART_CMD_RXEN_MASK | _LEUART_CMD_TXEN_MASK);
|
|
|
|
tmp <<= 1;
|
|
|
|
/* Enable as specified */
|
|
|
|
tmp |= (uint32_t)(enable);
|
|
|
|
|
|
|
|
/* LF register about to be modified require sync. busy check */
|
|
|
|
LEUART_Sync(leuart, LEUART_SYNCBUSY_CMD);
|
|
|
|
|
|
|
|
leuart->CMD = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* LEUART register synchronization freeze control.
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* Some LEUART registers require synchronization into the low frequency (LF)
|
|
|
|
* domain. The freeze feature allows for several such registers to be
|
|
|
|
* modified before passing them to the LF domain simultaneously (which
|
|
|
|
* takes place when the freeze mode is disabled).
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* When enabling freeze mode, this function will wait for all current
|
|
|
|
* ongoing LEUART synchronization to LF domain to complete (Normally
|
|
|
|
* synchronization will not be in progress.) However for this reason, when
|
|
|
|
* using freeze mode, modifications of registers requiring LF synchronization
|
|
|
|
* should be done within one freeze enable/disable block to avoid unecessary
|
|
|
|
* stalling.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @param[in] enable
|
|
|
|
* @li true - enable freeze, modified registers are not propagated to the
|
|
|
|
* LF domain
|
|
|
|
* @li false - disables freeze, modified registers are propagated to LF
|
|
|
|
* domain
|
|
|
|
******************************************************************************/
|
|
|
|
void LEUART_FreezeEnable(LEUART_TypeDef *leuart, bool enable)
|
|
|
|
{
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Wait for any ongoing LF synchronization to complete. This is just to
|
|
|
|
* protect against the rare case when a user
|
|
|
|
* - modifies a register requiring LF sync
|
|
|
|
* - then enables freeze before LF sync completed
|
|
|
|
* - then modifies the same register again
|
|
|
|
* since modifying a register while it is in sync progress should be
|
|
|
|
* avoided.
|
|
|
|
*/
|
|
|
|
while (leuart->SYNCBUSY)
|
|
|
|
;
|
|
|
|
|
|
|
|
leuart->FREEZE = LEUART_FREEZE_REGFREEZE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
leuart->FREEZE = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Init LEUART.
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* This function will configure basic settings in order to operate in normal
|
|
|
|
* asynchronous mode. Consider using LEUART_Reset() prior to this function if
|
|
|
|
* state of configuration is not known, since only configuration settings
|
|
|
|
* specified by @p init are set.
|
|
|
|
*
|
|
|
|
* Special control setup not covered by this function may be done either
|
|
|
|
* before or after using this function (but normally before enabling)
|
|
|
|
* by direct modification of the CTRL register.
|
|
|
|
*
|
|
|
|
* Notice that pins used by the LEUART module must be properly configured
|
|
|
|
* by the user explicitly, in order for the LEUART 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.)
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* Initializing requires synchronization into the low frequency domain.
|
|
|
|
* If the same register is modified before a previous update has completed,
|
|
|
|
* this function will stall until the previous synchronization has completed.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @param[in] init
|
|
|
|
* Pointer to initialization structure used to configure basic async setup.
|
|
|
|
******************************************************************************/
|
|
|
|
void LEUART_Init(LEUART_TypeDef *leuart, LEUART_Init_TypeDef *init)
|
|
|
|
{
|
|
|
|
/* Make sure the module exists on the selected chip */
|
|
|
|
EFM_ASSERT(LEUART_REF_VALID(leuart));
|
|
|
|
|
|
|
|
/* LF register about to be modified require sync. busy check */
|
|
|
|
LEUART_Sync(leuart, LEUART_SYNCBUSY_CMD);
|
|
|
|
|
|
|
|
/* Ensure disabled while doing config */
|
|
|
|
leuart->CMD = LEUART_CMD_RXDIS | LEUART_CMD_TXDIS;
|
|
|
|
|
|
|
|
/* Freeze registers to avoid stalling for LF synchronization */
|
|
|
|
LEUART_FreezeEnable(leuart, true);
|
|
|
|
|
|
|
|
/* Configure databits and stopbits */
|
|
|
|
leuart->CTRL = (leuart->CTRL & ~(_LEUART_CTRL_PARITY_MASK |
|
|
|
|
_LEUART_CTRL_STOPBITS_MASK)) |
|
|
|
|
(uint32_t)(init->databits) |
|
|
|
|
(uint32_t)(init->parity) |
|
|
|
|
(uint32_t)(init->stopbits);
|
|
|
|
|
|
|
|
/* Configure baudrate */
|
|
|
|
LEUART_BaudrateSet(leuart, init->refFreq, init->baudrate);
|
|
|
|
|
|
|
|
/* Finally enable (as specified) */
|
|
|
|
leuart->CMD = (uint32_t)(init->enable);
|
|
|
|
|
|
|
|
/* Unfreeze registers, pass new settings on to LEUART */
|
|
|
|
LEUART_FreezeEnable(leuart, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Reset LEUART to same state as after a HW reset.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
******************************************************************************/
|
|
|
|
void LEUART_Reset(LEUART_TypeDef *leuart)
|
|
|
|
{
|
|
|
|
/* Make sure the module exists on the selected chip */
|
|
|
|
EFM_ASSERT(LEUART_REF_VALID(leuart));
|
|
|
|
|
|
|
|
/* Freeze registers to avoid stalling for LF synchronization */
|
|
|
|
LEUART_FreezeEnable(leuart, true);
|
|
|
|
|
|
|
|
/* Make sure disabled first, before resetting other registers */
|
|
|
|
leuart->CMD = LEUART_CMD_RXDIS | LEUART_CMD_TXDIS | LEUART_CMD_RXBLOCKDIS |
|
|
|
|
LEUART_CMD_CLEARTX | LEUART_CMD_CLEARRX;
|
|
|
|
leuart->CTRL = _LEUART_CTRL_RESETVALUE;
|
|
|
|
leuart->CLKDIV = _LEUART_CLKDIV_RESETVALUE;
|
|
|
|
leuart->STARTFRAME = _LEUART_STARTFRAME_RESETVALUE;
|
|
|
|
leuart->SIGFRAME = _LEUART_SIGFRAME_RESETVALUE;
|
|
|
|
leuart->IEN = _LEUART_IEN_RESETVALUE;
|
|
|
|
leuart->IFC = _LEUART_IFC_MASK;
|
|
|
|
leuart->PULSECTRL = _LEUART_PULSECTRL_RESETVALUE;
|
|
|
|
leuart->ROUTE = _LEUART_ROUTE_RESETVALUE;
|
|
|
|
/* Do not reset route register, setting should be done independently */
|
|
|
|
|
|
|
|
/* Unfreeze registers, pass new settings on to LEUART */
|
|
|
|
LEUART_FreezeEnable(leuart, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Receive one 8 bit frame, (or part of 9 bit frame).
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* This function is normally used to receive one frame when operating with
|
|
|
|
* frame length 8 bits. Please refer to LEUART_RxExt() for reception of
|
|
|
|
* 9 bit frames.
|
|
|
|
*
|
|
|
|
* Notice that possible parity/stop bits are not considered part of specified
|
|
|
|
* frame bit length.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* This function will stall if buffer is empty, until data is received.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* Data received.
|
|
|
|
******************************************************************************/
|
|
|
|
uint8_t LEUART_Rx(LEUART_TypeDef *leuart)
|
|
|
|
{
|
|
|
|
while (!(leuart->STATUS & LEUART_STATUS_RXDATAV))
|
|
|
|
;
|
|
|
|
|
|
|
|
return (uint8_t)(leuart->RXDATA);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Receive one 8-9 bit frame, with extended information.
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* This function is normally used to receive one frame and additional RX
|
|
|
|
* status information is required.
|
|
|
|
*
|
|
|
|
* @note
|
|
|
|
* This function will stall if buffer is empty, until data is received.
|
|
|
|
*
|
|
|
|
* @param[in] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
* Data received.
|
|
|
|
******************************************************************************/
|
|
|
|
uint16_t LEUART_RxExt(LEUART_TypeDef *leuart)
|
|
|
|
{
|
|
|
|
while (!(leuart->STATUS & LEUART_STATUS_RXDATAV))
|
|
|
|
;
|
|
|
|
|
|
|
|
return (uint16_t)(leuart->RXDATAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Transmit one frame.
|
|
|
|
*
|
|
|
|
* @details
|
|
|
|
* Depending on frame length configuration, 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 LEUART_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] leuart
|
|
|
|
* Pointer to LEUART peripheral register block.
|
|
|
|
*
|
|
|
|
* @param[in] data
|
|
|
|
* Data to transmit. See details above for further info.
|
|
|
|
******************************************************************************/
|
|
|
|
void LEUART_Tx(LEUART_TypeDef *leuart, uint8_t data)
|
|
|
|
{
|
|
|
|
/* Check that transmit buffer is empty */
|
|
|
|
while (!(leuart->STATUS & LEUART_STATUS_TXBL))
|
|
|
|
;
|
|
|
|
|
|
|
|
/* LF register about to be modified require sync. busy check */
|
|
|
|
LEUART_Sync(leuart, LEUART_SYNCBUSY_TXDATA);
|
|
|
|
|
|
|
|
leuart->TXDATA = (uint32_t)data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************//**
|
|
|
|
* @brief
|
|
|
|
* Transmit one 8-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] leuart
|
|
|
|
* Pointer to LEUART 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 EFM32 reference manual (set to 0 if not used).
|
|
|
|
******************************************************************************/
|
|
|
|
void LEUART_TxExt(LEUART_TypeDef *leuart, uint16_t data)
|
|
|
|
{
|
|
|
|
/* Check that transmit buffer is empty */
|
|
|
|
while (!(leuart->STATUS & LEUART_STATUS_TXBL))
|
|
|
|
;
|
|
|
|
|
|
|
|
/* LF register about to be modified require sync. busy check */
|
|
|
|
LEUART_Sync(leuart, LEUART_SYNCBUSY_TXDATAX);
|
|
|
|
|
|
|
|
leuart->TXDATAX = (uint32_t)data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} (end addtogroup LEUART) */
|
|
|
|
/** @} (end addtogroup EM_Library) */
|