EFM32 Pearl Gecko Software Documentation  efm32pg1-doc-4.2.1
em_rtc.c
Go to the documentation of this file.
1 /***************************************************************************/
33 #include "em_rtc.h"
34 #if defined(RTC_COUNT) && (RTC_COUNT > 0)
35 
36 #include "em_assert.h"
37 #include "em_bus.h"
38 
39 /***************************************************************************/
44 /***************************************************************************/
50 /*******************************************************************************
51  ******************************* DEFINES ***********************************
52  ******************************************************************************/
53 
57 #define RTC_COMP_REG_VALID(reg) (((reg) <= 1))
58 
62 /*******************************************************************************
63  ************************** LOCAL FUNCTIONS ********************************
64  ******************************************************************************/
65 
68 #if defined(_EFM32_GECKO_FAMILY)
69 /***************************************************************************/
84 __STATIC_INLINE void regSync(uint32_t mask)
85 {
86  /* Avoid deadlock if modifying the same register twice when freeze mode is */
87  /* activated. */
88  if (RTC->FREEZE & RTC_FREEZE_REGFREEZE)
89  return;
90 
91  /* Wait for any pending previous write operation to have been completed */
92  /* in low frequency domain. This is only required for the Gecko Family */
93  while (RTC->SYNCBUSY & mask)
94  ;
95 }
96 #endif
97 
100 /*******************************************************************************
101  ************************** GLOBAL FUNCTIONS *******************************
102  ******************************************************************************/
103 
104 /***************************************************************************/
114 uint32_t RTC_CompareGet(unsigned int comp)
115 {
116  uint32_t ret;
117 
118  EFM_ASSERT(RTC_COMP_REG_VALID(comp));
119 
120  /* Initialize selected compare value */
121  switch (comp)
122  {
123  case 0:
124  ret = RTC->COMP0;
125  break;
126 
127  case 1:
128  ret = RTC->COMP1;
129  break;
130 
131  default:
132  /* Unknown compare register selected */
133  ret = 0;
134  break;
135  }
136 
137  return ret;
138 }
139 
140 
141 /***************************************************************************/
158 void RTC_CompareSet(unsigned int comp, uint32_t value)
159 {
160  volatile uint32_t *compReg;
161 #if defined(_EFM32_GECKO_FAMILY)
162  uint32_t syncbusy;
163 #endif
164 
165  EFM_ASSERT(RTC_COMP_REG_VALID(comp)
166  && ((value & ~(_RTC_COMP0_COMP0_MASK
167  >> _RTC_COMP0_COMP0_SHIFT)) == 0));
168 
169  /* Initialize selected compare value */
170  switch (comp)
171  {
172  case 0:
173  compReg = &(RTC->COMP0);
174 #if defined(_EFM32_GECKO_FAMILY)
175  syncbusy = RTC_SYNCBUSY_COMP0;
176 #endif
177  break;
178 
179  case 1:
180  compReg = &(RTC->COMP1);
181 #if defined(_EFM32_GECKO_FAMILY)
182  syncbusy = RTC_SYNCBUSY_COMP1;
183 #endif
184  break;
185 
186  default:
187  /* Unknown compare register selected, abort */
188  return;
189  }
190 #if defined(_EFM32_GECKO_FAMILY)
191  /* LF register about to be modified require sync. busy check */
192  regSync(syncbusy);
193 #endif
194 
195  *compReg = value;
196 }
197 
198 
199 /***************************************************************************/
214 void RTC_Enable(bool enable)
215 {
216 #if defined(_EFM32_GECKO_FAMILY)
217  /* LF register about to be modified require sync. busy check */
218  regSync(RTC_SYNCBUSY_CTRL);
219 #endif
220 
221  BUS_RegBitWrite(&(RTC->CTRL), _RTC_CTRL_EN_SHIFT, enable);
222 
223 #if defined(_EFM32_GECKO_FAMILY)
224  /* Wait for CTRL to be updated before returning, because calling code may
225  depend upon that the CTRL register is updated after this function has
226  returned. */
227  regSync(RTC_SYNCBUSY_CTRL);
228 #endif
229 }
230 
231 
232 /***************************************************************************/
258 void RTC_FreezeEnable(bool enable)
259 {
260  if (enable)
261  {
262 #if defined(_EFM32_GECKO_FAMILY)
263  /* Wait for any ongoing LF synchronization to complete. This is just to */
264  /* protect against the rare case when a user */
265  /* - modifies a register requiring LF sync */
266  /* - then enables freeze before LF sync completed */
267  /* - then modifies the same register again */
268  /* since modifying a register while it is in sync progress should be */
269  /* avoided. */
270  while (RTC->SYNCBUSY)
271  ;
272 #endif
273  RTC->FREEZE = RTC_FREEZE_REGFREEZE;
274  }
275  else
276  {
277  RTC->FREEZE = 0;
278  }
279 }
280 
281 
282 /***************************************************************************/
302 void RTC_Init(const RTC_Init_TypeDef *init)
303 {
304  uint32_t tmp;
305 
306  if (init->enable)
307  {
308  tmp = RTC_CTRL_EN;
309  }
310  else
311  {
312  tmp = 0;
313  }
314 
315  /* Configure DEBUGRUN flag, sets whether or not counter should be
316  * updated when debugger is active */
317  if (init->debugRun)
318  {
319  tmp |= RTC_CTRL_DEBUGRUN;
320  }
321 
322  /* Configure COMP0TOP, this will use the COMP0 compare value as an
323  * overflow value, instead of default 24-bit 0x00ffffff */
324  if (init->comp0Top)
325  {
326  tmp |= RTC_CTRL_COMP0TOP;
327  }
328 
329 #if defined(_EFM32_GECKO_FAMILY)
330  /* LF register about to be modified require sync. busy check */
331  regSync(RTC_SYNCBUSY_CTRL);
332 #endif
333 
334  RTC->CTRL = tmp;
335 }
336 
337 
338 
339 /***************************************************************************/
343 void RTC_Reset(void)
344 {
345  /* Restore all essential RTC register to default config */
346  RTC->FREEZE = _RTC_FREEZE_RESETVALUE;
347  RTC->CTRL = _RTC_CTRL_RESETVALUE;
348  RTC->COMP0 = _RTC_COMP0_RESETVALUE;
349  RTC->COMP1 = _RTC_COMP1_RESETVALUE;
350  RTC->IEN = _RTC_IEN_RESETVALUE;
351  RTC->IFC = _RTC_IFC_RESETVALUE;
352 
353 #if defined(_EFM32_GECKO_FAMILY)
354  /* Wait for CTRL, COMP0 and COMP1 to be updated before returning, because the
355  calling code may depend upon that the register values are updated after
356  this function has returned. */
357  regSync(RTC_SYNCBUSY_CTRL | RTC_SYNCBUSY_COMP0 | RTC_SYNCBUSY_COMP1);
358 #endif
359 }
360 
361 
362 
363 /***************************************************************************/
367 void RTC_CounterReset(void)
368 {
369  /* A disable/enable sequnce will start the counter at zero */
370  RTC_Enable(false);
371  RTC_Enable(true);
372 }
373 
374 
377 #endif /* defined(RTC_COUNT) && (RTC_COUNT > 0) */
Emlib peripheral API "assert" implementation.
RAM and peripheral bit-field set and clear API.
Real Time Counter (RTC) peripheral API.
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr, unsigned int bit, unsigned int val)
Perform a single-bit write operation on a peripheral register.
Definition: em_bus.h:146