em_rtc.c

Go to the documentation of this file.
00001 /***************************************************************************/
00034 #include "em_rtc.h"
00035 #if defined(RTC_COUNT) && (RTC_COUNT > 0)
00036 
00037 #include "em_assert.h"
00038 #include "em_bitband.h"
00039 
00040 /***************************************************************************/
00045 /***************************************************************************/
00051 /*******************************************************************************
00052  *******************************   DEFINES   ***********************************
00053  ******************************************************************************/
00054 
00058 #define RTC_COMP_REG_VALID(reg)    (((reg) <= 1))
00059 
00063 /*******************************************************************************
00064  **************************   LOCAL FUNCTIONS   ********************************
00065  ******************************************************************************/
00066 
00069 #if defined(_EFM32_GECKO_FAMILY)
00070 /***************************************************************************/
00085 __STATIC_INLINE void RTC_Sync(uint32_t mask)
00086 {
00087   /* Avoid deadlock if modifying the same register twice when freeze mode is */
00088   /* activated. */
00089   if (RTC->FREEZE & RTC_FREEZE_REGFREEZE)
00090     return;
00091 
00092   /* Wait for any pending previous write operation to have been completed */
00093   /* in low frequency domain. This is only required for the Gecko Family */
00094   while (RTC->SYNCBUSY & mask)
00095     ;
00096 }
00097 #endif
00098 
00101 /*******************************************************************************
00102  **************************   GLOBAL FUNCTIONS   *******************************
00103  ******************************************************************************/
00104 
00105 /***************************************************************************/
00115 uint32_t RTC_CompareGet(unsigned int comp)
00116 {
00117   uint32_t ret;
00118 
00119   EFM_ASSERT(RTC_COMP_REG_VALID(comp));
00120 
00121   /* Initialize selected compare value */
00122   switch (comp)
00123   {
00124   case 0:
00125     ret = RTC->COMP0;
00126     break;
00127 
00128   case 1:
00129     ret = RTC->COMP1;
00130     break;
00131 
00132   default:
00133     /* Unknown compare register selected */
00134     ret = 0;
00135     break;
00136   }
00137 
00138   return ret;
00139 }
00140 
00141 
00142 /***************************************************************************/
00159 void RTC_CompareSet(unsigned int comp, uint32_t value)
00160 {
00161   volatile uint32_t *compReg;
00162 #if defined(_EFM32_GECKO_FAMILY)
00163   uint32_t          syncbusy;
00164 #endif
00165 
00166   EFM_ASSERT(RTC_COMP_REG_VALID(comp) &&
00167              ((value & ~(_RTC_COMP0_COMP0_MASK >> _RTC_COMP0_COMP0_SHIFT)) == 0));
00168 
00169   /* Initialize selected compare value */
00170   switch (comp)
00171   {
00172   case 0:
00173     compReg = &(RTC->COMP0);
00174 #if defined(_EFM32_GECKO_FAMILY)
00175     syncbusy = RTC_SYNCBUSY_COMP0;
00176 #endif
00177     break;
00178 
00179   case 1:
00180     compReg = &(RTC->COMP1);
00181 #if defined(_EFM32_GECKO_FAMILY)
00182     syncbusy = RTC_SYNCBUSY_COMP1;
00183 #endif
00184     break;
00185 
00186   default:
00187     /* Unknown compare register selected, abort */
00188     return;
00189   }
00190 #if defined(_EFM32_GECKO_FAMILY)
00191   /* LF register about to be modified require sync. busy check */
00192   RTC_Sync(syncbusy);
00193 #endif
00194 
00195   *compReg = value;
00196 }
00197 
00198 
00199 /***************************************************************************/
00214 void RTC_Enable(bool enable)
00215 {
00216 #if defined(_EFM32_GECKO_FAMILY)
00217   /* LF register about to be modified require sync. busy check */
00218   RTC_Sync(RTC_SYNCBUSY_CTRL);
00219 #endif
00220 
00221   BITBAND_Peripheral(&(RTC->CTRL), _RTC_CTRL_EN_SHIFT, (unsigned int) enable);
00222 
00223 #if defined(_EFM32_GECKO_FAMILY)
00224   /* Wait for CTRL to be updated before returning, because calling code may
00225      depend upon that the CTRL register is updated after this function has
00226      returned. */
00227   RTC_Sync(RTC_SYNCBUSY_CTRL);
00228 #endif
00229 }
00230 
00231 
00232 /***************************************************************************/
00258 void RTC_FreezeEnable(bool enable)
00259 {
00260   if (enable)
00261   {
00262 #if defined(_EFM32_GECKO_FAMILY)
00263     /* Wait for any ongoing LF synchronization to complete. This is just to */
00264     /* protect against the rare case when a user                            */
00265     /* - modifies a register requiring LF sync                              */
00266     /* - then enables freeze before LF sync completed                       */
00267     /* - then modifies the same register again                              */
00268     /* since modifying a register while it is in sync progress should be    */
00269     /* avoided.                                                             */
00270     while (RTC->SYNCBUSY)
00271       ;
00272 #endif
00273     RTC->FREEZE = RTC_FREEZE_REGFREEZE;
00274   }
00275   else
00276   {
00277     RTC->FREEZE = 0;
00278   }
00279 }
00280 
00281 
00282 /***************************************************************************/
00302 void RTC_Init(const RTC_Init_TypeDef *init)
00303 {
00304   uint32_t tmp;
00305 
00306   if (init->enable)
00307   {
00308     tmp = RTC_CTRL_EN;
00309   }
00310   else
00311   {
00312     tmp = 0;
00313   }
00314 
00315   /* Configure DEBUGRUN flag, sets whether or not counter should be
00316    * updated when debugger is active */
00317   if (init->debugRun)
00318   {
00319     tmp |= RTC_CTRL_DEBUGRUN;
00320   }
00321 
00322   /* Configure COMP0TOP, this will use the COMP0 compare value as an
00323    * overflow value, instead of default 24-bit 0x00ffffff */
00324   if (init->comp0Top)
00325   {
00326     tmp |= RTC_CTRL_COMP0TOP;
00327   }
00328 
00329 #if defined(_EFM32_GECKO_FAMILY)
00330   /* LF register about to be modified require sync. busy check */
00331   RTC_Sync(RTC_SYNCBUSY_CTRL);
00332 #endif
00333 
00334   RTC->CTRL = tmp;
00335 }
00336 
00337 
00338 
00339 /***************************************************************************/
00343 void RTC_Reset(void)
00344 {
00345   /* Restore all essential RTC register to default config */
00346   RTC->FREEZE = _RTC_FREEZE_RESETVALUE;
00347   RTC->CTRL   = _RTC_CTRL_RESETVALUE;
00348   RTC->COMP0  = _RTC_COMP0_RESETVALUE;
00349   RTC->COMP1  = _RTC_COMP1_RESETVALUE;
00350   RTC->IEN    = _RTC_IEN_RESETVALUE;
00351   RTC->IFC    = _RTC_IFC_RESETVALUE;
00352 }
00353 
00354 
00355 
00356 /***************************************************************************/
00360 void RTC_CounterReset(void)
00361 {
00362   /* A disable/enable sequnce will start the counter at zero */
00363   RTC_Enable(false);
00364   RTC_Enable(true);
00365 }
00366 
00367 
00370 #endif /* defined(RTC_COUNT) && (RTC_COUNT > 0) */