em_burtc.c

Go to the documentation of this file.
00001 /***************************************************************************/
00034 #include "em_device.h"
00035 #if defined(BURTC_PRESENT)
00036 #include "em_burtc.h"
00037 
00038 #include "em_assert.h"
00039 #include "em_bitband.h"
00040 
00041 /***************************************************************************/
00046 /***************************************************************************/
00052 /*******************************************************************************
00053  *******************************   DEFINES   ***********************************
00054  ******************************************************************************/
00055 
00056 /*******************************************************************************
00057  **************************   LOCAL FUNCTIONS   ********************************
00058  ******************************************************************************/
00059 
00060 /***************************************************************************/
00066 __STATIC_INLINE uint32_t BURTC_DivToLog2(uint32_t div)
00067 {
00068   uint32_t log2;
00069 
00070   /* Prescaler accepts an argument of 128 or less, valid values being 2^n */
00071   EFM_ASSERT((div > 0) && (div <= 32768));
00072 
00073   /* Count leading zeroes and "reverse" result, Cortex-M3 intrinsic */
00074   log2 = (31 - __CLZ(div));
00075 
00076   return log2;
00077 }
00078 
00079 
00080 /***************************************************************************/
00088 __STATIC_INLINE void BURTC_Sync(uint32_t mask)
00089 {
00090   /* Avoid deadlock if modifying the same register twice when freeze mode is
00091      activated, or when no clock is selected for the BURTC. If no clock is
00092      selected, then the sync is done once the clock source is set. */
00093   if ((BURTC->FREEZE & BURTC_FREEZE_REGFREEZE)
00094       || ((BURTC->CTRL & _BURTC_CTRL_CLKSEL_MASK) != _BURTC_CTRL_CLKSEL_NONE))
00095   {
00096     return;
00097   }
00098   /* Wait for any pending previous write operation to have been completed */
00099   /* in low frequency domain. This is only required for the Gecko Family */
00100   while (BURTC->SYNCBUSY & mask)
00101     ;
00102 }
00103 
00104 
00105 /*******************************************************************************
00106  **************************   GLOBAL FUNCTIONS   *******************************
00107  ******************************************************************************/
00108 
00109 /***************************************************************************/
00127 void BURTC_Init(const BURTC_Init_TypeDef *burtcInit)
00128 {
00129   uint32_t ctrl;
00130   uint32_t presc;
00131 
00132   /* Check initializer structure integrity */
00133   EFM_ASSERT(burtcInit != (BURTC_Init_TypeDef *) 0);
00134   /* Clock divider must be between 1 and 128, really on the form 2^n */
00135   EFM_ASSERT((burtcInit->clkDiv >= 1) && (burtcInit->clkDiv <= 128));
00136   /* Ignored compare bits during low power operation must be less than 7 */
00137   /* Note! Giant Gecko revision C errata, do NOT use LPCOMP=7 */
00138   EFM_ASSERT(burtcInit->lowPowerComp <= 6);
00139   /* You cannot enable the BURTC if mode is set to disabled */
00140   EFM_ASSERT((burtcInit->enable == false) ||
00141              ((burtcInit->enable == true) && (burtcInit->mode != burtcModeDisable)));
00142   /* Low power mode is only available with LFRCO or LFXO as clock source */
00143   EFM_ASSERT((burtcInit->clkSel != burtcClkSelULFRCO) ||
00144              ((burtcInit->clkSel == burtcClkSelULFRCO) && (burtcInit->lowPowerMode == burtcLPDisable)));
00145 
00146   /* Calculate prescaler value from clock divider input */
00147   /* Note! If clock select (clkSel) is ULFRCO, a clock divisor (clkDiv) of
00148      value 1 will select a 2kHz ULFRCO clock, while any other value will
00149      select a 1kHz ULFRCO clock source. */
00150   presc = BURTC_DivToLog2(burtcInit->clkDiv);
00151 
00152   /* Make sure all registers are updated simultaneously */
00153   if (burtcInit->enable)
00154   {
00155     BURTC_FreezeEnable(true);
00156   }
00157 
00158   /* Modification of LPMODE register requires sync with potential ongoing
00159    * register updates in LF domain. */
00160   BURTC_Sync(BURTC_SYNCBUSY_LPMODE);
00161 
00162   /* Configure low power mode */
00163   BURTC->LPMODE = (uint32_t) (burtcInit->lowPowerMode);
00164 
00165   /* New configuration */
00166   ctrl = ((BURTC_CTRL_RSTEN) |
00167           (burtcInit->mode) |
00168           (burtcInit->debugRun << _BURTC_CTRL_DEBUGRUN_SHIFT) |
00169           (burtcInit->compare0Top << _BURTC_CTRL_COMP0TOP_SHIFT) |
00170           (burtcInit->lowPowerComp << _BURTC_CTRL_LPCOMP_SHIFT) |
00171           (presc << _BURTC_CTRL_PRESC_SHIFT) |
00172           (burtcInit->clkSel) |
00173           (burtcInit->timeStamp << _BURTC_CTRL_BUMODETSEN_SHIFT));
00174 
00175   /* Clear interrupts */
00176   BURTC_IntClear(0xFFFFFFFF);
00177 
00178   /* Set new configuration */
00179   BURTC->CTRL = ctrl;
00180 
00181   /* Enable BURTC and counter */
00182   if (burtcInit->enable)
00183   {
00184     /* To enable BURTC counter, we need to disable reset */
00185     BURTC_Enable(true);
00186 
00187     /* Clear freeze */
00188     BURTC_FreezeEnable(false);
00189   }
00190 }
00191 
00192 
00193 /***************************************************************************/
00200 void BURTC_CompareSet(unsigned int comp, uint32_t value)
00201 {
00202   (void) comp;  /* Unused parameter when EFM_ASSERT is undefined. */
00203 
00204   EFM_ASSERT(comp == 0);
00205 
00206   /* Modification of COMP0 register requires sync with potential ongoing
00207    * register updates in LF domain. */
00208   BURTC_Sync(BURTC_SYNCBUSY_COMP0);
00209 
00210   /* Configure compare channel 0 */
00211   BURTC->COMP0 = value;
00212 }
00213 
00214 
00215 /***************************************************************************/
00222 uint32_t BURTC_CompareGet(unsigned int comp)
00223 {
00224   (void) comp;  /* Unused parameter when EFM_ASSERT is undefined. */
00225 
00226   EFM_ASSERT(comp == 0);
00227 
00228   return BURTC->COMP0;
00229 }
00230 
00231 
00232 /***************************************************************************/
00235 void BURTC_CounterReset(void)
00236 {
00237   /* Set and clear reset bit */
00238   BITBAND_Peripheral(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 1);
00239   BITBAND_Peripheral(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 0);
00240 }
00241 
00242 
00243 /***************************************************************************/
00251 void BURTC_Reset(void)
00252 {
00253   bool buResetState;
00254 
00255   /* Read reset state, set reset and restore state */
00256   buResetState = BITBAND_PeripheralRead(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT);
00257   BITBAND_Peripheral(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT, 1);
00258   BITBAND_Peripheral(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT, buResetState);
00259 }
00260 
00261 
00262 /***************************************************************************/
00269 uint32_t BURTC_ClockFreqGet(void)
00270 {
00271   uint32_t clkSel;
00272   uint32_t clkDiv;
00273   uint32_t frequency;
00274 
00275   clkSel = BURTC->CTRL & _BURTC_CTRL_CLKSEL_MASK;
00276   clkDiv = (BURTC->CTRL & _BURTC_CTRL_PRESC_MASK) >> _BURTC_CTRL_PRESC_SHIFT;
00277 
00278   switch (clkSel)
00279   {
00281   case BURTC_CTRL_CLKSEL_ULFRCO:
00282     if (_BURTC_CTRL_PRESC_DIV1 == clkDiv)
00283     {
00284       frequency = 2000;     /* 2KHz when clock divisor is 1. */
00285     }
00286     else
00287     {
00288       frequency = SystemULFRCOClockGet();  /* 1KHz when divisor is different
00289                                               from 1. */
00290     }
00291     break;
00292 
00294   case BURTC_CTRL_CLKSEL_LFRCO:
00295     frequency = SystemLFRCOClockGet() / (1 << clkDiv); /* freq=32768/2^clkDiv */
00296     break;
00297 
00299   case BURTC_CTRL_CLKSEL_LFXO:
00300     frequency = SystemLFXOClockGet() / (1 << clkDiv); /* freq=32768/2^clkDiv */
00301     break;
00302 
00303   default:
00304     /* No clock selected for BURTC. */
00305     frequency = 0;
00306   }
00307   return frequency;
00308 }
00309 
00310 
00314 #endif /* BURTC_PRESENT */