mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
149:156823d33999
Parent:
144:ef7eb2e8f9f7
Child:
150:02e0a0aed4ec
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_burtc.c	Fri Oct 28 11:17:30 2016 +0100
@@ -0,0 +1,314 @@
+/***************************************************************************//**
+ * @file em_burtc.c
+ * @brief Backup Real Time Counter (BURTC) 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_burtc.h"
+#if defined(BURTC_PRESENT)
+
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup BURTC
+ * @brief Backup Real Time Counter (BURTC) Peripheral API
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ *******************************   DEFINES   ***********************************
+ ******************************************************************************/
+
+/*******************************************************************************
+ **************************   LOCAL FUNCTIONS   ********************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+/***************************************************************************//**
+ * @brief Convert dividend to prescaler logarithmic value. Only works for even
+ *        numbers equal to 2^n
+ * @param[in] div Unscaled dividend,
+ * @return Base 2 logarithm of input, as used by fixed prescalers
+ ******************************************************************************/
+__STATIC_INLINE uint32_t divToLog2(uint32_t div)
+{
+  uint32_t log2;
+
+  /* Prescaler accepts an argument of 128 or less, valid values being 2^n */
+  EFM_ASSERT((div > 0) && (div <= 32768));
+
+  /* Count leading zeroes and "reverse" result, Cortex-M3 intrinsic */
+  log2 = (31 - __CLZ(div));
+
+  return log2;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Wait for ongoing sync of register(s) to low frequency domain to complete.
+ *
+ * @param[in] mask
+ *   Bitmask corresponding to SYNCBUSY register defined bits, indicating
+ *   registers that must complete any ongoing synchronization.
+ ******************************************************************************/
+__STATIC_INLINE void regSync(uint32_t mask)
+{
+  /* Avoid deadlock if modifying the same register twice when freeze mode is
+     activated, or when no clock is selected for the BURTC. If no clock is
+     selected, then the sync is done once the clock source is set. */
+  if ((BURTC->FREEZE & BURTC_FREEZE_REGFREEZE)
+      || ((BURTC->CTRL & _BURTC_CTRL_CLKSEL_MASK) != _BURTC_CTRL_CLKSEL_NONE))
+  {
+    return;
+  }
+  /* Wait for any pending previous write operation to have been completed */
+  /* in low frequency domain. This is only required for the Gecko Family */
+  while (BURTC->SYNCBUSY & mask)
+    ;
+}
+/** @endcond */
+
+
+/*******************************************************************************
+ **************************   GLOBAL FUNCTIONS   *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief Initialize BURTC
+ *
+ * @details
+ *    Configures the BURTC peripheral.
+ *
+ * @note
+ *   Before initialization, BURTC module must first be enabled by clearing the
+ *   reset bit in the RMU, i.e.
+ * @verbatim
+ *   RMU_ResetControl(rmuResetBU, rmuResetModeClear);
+ * @endverbatim
+ *   Compare channel 0 must be configured outside this function, before
+ *   initialization if enable is set to true. The counter will always be reset.
+ *
+ * @param[in] burtcInit
+ *   Pointer to BURTC initialization structure
+ ******************************************************************************/
+void BURTC_Init(const BURTC_Init_TypeDef *burtcInit)
+{
+  uint32_t ctrl;
+  uint32_t presc;
+
+  /* Check initializer structure integrity */
+  EFM_ASSERT(burtcInit != (BURTC_Init_TypeDef *) 0);
+  /* Clock divider must be between 1 and 128, really on the form 2^n */
+  EFM_ASSERT((burtcInit->clkDiv >= 1) && (burtcInit->clkDiv <= 128));
+  /* Ignored compare bits during low power operation must be less than 7 */
+  /* Note! Giant Gecko revision C errata, do NOT use LPCOMP=7 */
+  EFM_ASSERT(burtcInit->lowPowerComp <= 6);
+  /* You cannot enable the BURTC if mode is set to disabled */
+  EFM_ASSERT((burtcInit->enable == false) ||
+             ((burtcInit->enable == true)
+              && (burtcInit->mode != burtcModeDisable)));
+  /* Low power mode is only available with LFRCO or LFXO as clock source */
+  EFM_ASSERT((burtcInit->clkSel != burtcClkSelULFRCO)
+             || ((burtcInit->clkSel == burtcClkSelULFRCO)
+                  && (burtcInit->lowPowerMode == burtcLPDisable)));
+
+  /* Calculate prescaler value from clock divider input */
+  /* Note! If clock select (clkSel) is ULFRCO, a clock divisor (clkDiv) of
+     value 1 will select a 2kHz ULFRCO clock, while any other value will
+     select a 1kHz ULFRCO clock source. */
+  presc = divToLog2(burtcInit->clkDiv);
+
+  /* Make sure all registers are updated simultaneously */
+  if (burtcInit->enable)
+  {
+    BURTC_FreezeEnable(true);
+  }
+
+  /* Modification of LPMODE register requires sync with potential ongoing
+   * register updates in LF domain. */
+  regSync(BURTC_SYNCBUSY_LPMODE);
+
+  /* Configure low power mode */
+  BURTC->LPMODE = (uint32_t) (burtcInit->lowPowerMode);
+
+  /* New configuration */
+  ctrl = (BURTC_CTRL_RSTEN
+          | (burtcInit->mode)
+          | (burtcInit->debugRun << _BURTC_CTRL_DEBUGRUN_SHIFT)
+          | (burtcInit->compare0Top << _BURTC_CTRL_COMP0TOP_SHIFT)
+          | (burtcInit->lowPowerComp << _BURTC_CTRL_LPCOMP_SHIFT)
+          | (presc << _BURTC_CTRL_PRESC_SHIFT)
+          | (burtcInit->clkSel)
+          | (burtcInit->timeStamp << _BURTC_CTRL_BUMODETSEN_SHIFT));
+
+  /* Clear interrupts */
+  BURTC_IntClear(0xFFFFFFFF);
+
+  /* Set new configuration */
+  BURTC->CTRL = ctrl;
+
+  /* Enable BURTC and counter */
+  if (burtcInit->enable)
+  {
+    /* To enable BURTC counter, we need to disable reset */
+    BURTC_Enable(true);
+
+    /* Clear freeze */
+    BURTC_FreezeEnable(false);
+  }
+}
+
+
+/***************************************************************************//**
+ * @brief Set BURTC compare channel
+ *
+ * @param[in] comp Compare channel index, must be 0 for Giant / Leopard Gecko
+ *
+ * @param[in] value New compare value
+ ******************************************************************************/
+void BURTC_CompareSet(unsigned int comp, uint32_t value)
+{
+  (void) comp;  /* Unused parameter when EFM_ASSERT is undefined. */
+
+  EFM_ASSERT(comp == 0);
+
+  /* Modification of COMP0 register requires sync with potential ongoing
+   * register updates in LF domain. */
+  regSync(BURTC_SYNCBUSY_COMP0);
+
+  /* Configure compare channel 0 */
+  BURTC->COMP0 = value;
+}
+
+
+/***************************************************************************//**
+ * @brief Get BURTC compare value
+ *
+ * @param[in] comp Compare channel index value, must be 0 for Giant/Leopard.
+ *
+ * @return Currently configured value for this compare channel
+ ******************************************************************************/
+uint32_t BURTC_CompareGet(unsigned int comp)
+{
+  (void) comp;  /* Unused parameter when EFM_ASSERT is undefined. */
+
+  EFM_ASSERT(comp == 0);
+
+  return BURTC->COMP0;
+}
+
+
+/***************************************************************************//**
+ * @brief Reset counter
+ ******************************************************************************/
+void BURTC_CounterReset(void)
+{
+  /* Set and clear reset bit */
+  BUS_RegBitWrite(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 1);
+  BUS_RegBitWrite(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 0);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Restore BURTC to reset state
+ * @note
+ *   Before accessing the BURTC, BURSTEN in RMU->CTRL must be cleared.
+ *   LOCK will not be reset to default value, as this will disable access
+ *   to core BURTC registers.
+ ******************************************************************************/
+void BURTC_Reset(void)
+{
+  bool buResetState;
+
+  /* Read reset state, set reset and restore state */
+  buResetState = BUS_RegBitRead(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT);
+  BUS_RegBitWrite(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT, 1);
+  BUS_RegBitWrite(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT, buResetState);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Get clock frequency of the BURTC.
+ *
+ * @return
+ *   The current frequency in Hz.
+ ******************************************************************************/
+uint32_t BURTC_ClockFreqGet(void)
+{
+  uint32_t clkSel;
+  uint32_t clkDiv;
+  uint32_t frequency;
+
+  clkSel = BURTC->CTRL & _BURTC_CTRL_CLKSEL_MASK;
+  clkDiv = (BURTC->CTRL & _BURTC_CTRL_PRESC_MASK) >> _BURTC_CTRL_PRESC_SHIFT;
+
+  switch (clkSel)
+  {
+    /** Ultra low frequency (1 kHz) clock */
+    case BURTC_CTRL_CLKSEL_ULFRCO:
+      if (_BURTC_CTRL_PRESC_DIV1 == clkDiv)
+      {
+        frequency = 2000;     /* 2KHz when clock divisor is 1. */
+      }
+      else
+      {
+        frequency = SystemULFRCOClockGet();  /* 1KHz when divisor is different
+                                                from 1. */
+      }
+      break;
+
+    /** Low frequency RC oscillator */
+    case BURTC_CTRL_CLKSEL_LFRCO:
+      frequency = SystemLFRCOClockGet() / (1 << clkDiv); /* freq=32768/2^clkDiv */
+      break;
+
+    /** Low frequency crystal osciallator */
+    case BURTC_CTRL_CLKSEL_LFXO:
+      frequency = SystemLFXOClockGet() / (1 << clkDiv); /* freq=32768/2^clkDiv */
+      break;
+
+    default:
+      /* No clock selected for BURTC. */
+      frequency = 0;
+  }
+  return frequency;
+}
+
+
+/** @} (end addtogroup BURTC) */
+/** @} (end addtogroup EM_Library) */
+
+#endif /* BURTC_PRESENT */