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 #if defined(_EFM32_GECKO_FAMILY)
00354   /* Wait for CTRL, COMP0 and COMP1 to be updated before returning, because the
00355      calling code may depend upon that the register values are updated after
00356      this function has returned. */
00357   RTC_Sync(RTC_SYNCBUSY_CTRL | RTC_SYNCBUSY_COMP0 | RTC_SYNCBUSY_COMP1);
00358 #endif
00359 }
00360 
00361 
00362 
00363 /***************************************************************************/
00367 void RTC_CounterReset(void)
00368 {
00369   /* A disable/enable sequnce will start the counter at zero */
00370   RTC_Enable(false);
00371   RTC_Enable(true);
00372 }
00373 
00374 
00377 #endif /* defined(RTC_COUNT) && (RTC_COUNT > 0) */