EFM32 Gecko Software Documentation  efm32g-doc-5.1.2
em_burtc.c
Go to the documentation of this file.
1 /***************************************************************************/
34 #include "em_burtc.h"
35 #if defined(BURTC_PRESENT)
36 
37 /***************************************************************************/
42 /***************************************************************************/
53 /*******************************************************************************
54  ******************************* DEFINES ***********************************
55  ******************************************************************************/
56 
57 /*******************************************************************************
58  ************************** LOCAL FUNCTIONS ********************************
59  ******************************************************************************/
60 
62 /***************************************************************************/
68 __STATIC_INLINE uint32_t divToLog2(uint32_t div)
69 {
70  uint32_t log2;
71 
72  /* Prescaler accepts an argument of 128 or less, valid values being 2^n */
73  EFM_ASSERT((div > 0) && (div <= 32768));
74 
75  /* Count leading zeroes and "reverse" result, Cortex-M3 intrinsic */
76  log2 = (31 - __CLZ(div));
77 
78  return log2;
79 }
80 
81 
82 /***************************************************************************/
90 __STATIC_INLINE void regSync(uint32_t mask)
91 {
92  /* Avoid deadlock if modifying the same register twice when freeze mode is
93  activated, or when no clock is selected for the BURTC. If no clock is
94  selected, then the sync is done once the clock source is set. */
95  if ((BURTC->FREEZE & BURTC_FREEZE_REGFREEZE)
96  || ((BURTC->CTRL & _BURTC_CTRL_CLKSEL_MASK) == BURTC_CTRL_CLKSEL_NONE))
97  {
98  return;
99  }
100  /* Wait for any pending previous write operation to have been completed */
101  /* in low frequency domain. This is only required for the Gecko Family */
102  while (BURTC->SYNCBUSY & mask)
103  ;
104 }
108 /*******************************************************************************
109  ************************** GLOBAL FUNCTIONS *******************************
110  ******************************************************************************/
111 
112 /***************************************************************************/
130 void BURTC_Init(const BURTC_Init_TypeDef *burtcInit)
131 {
132  uint32_t ctrl;
133  uint32_t presc;
134 
135  /* Check initializer structure integrity */
136  EFM_ASSERT(burtcInit != (BURTC_Init_TypeDef *) 0);
137  /* Clock divider must be between 1 and 128, really on the form 2^n */
138  EFM_ASSERT((burtcInit->clkDiv >= 1) && (burtcInit->clkDiv <= 128));
139  /* Ignored compare bits during low power operation must be less than 7 */
140  /* Note! Giant Gecko revision C errata, do NOT use LPCOMP=7 */
141  EFM_ASSERT(burtcInit->lowPowerComp <= 6);
142  /* You cannot enable the BURTC if mode is set to disabled */
143  EFM_ASSERT((burtcInit->enable == false) ||
144  ((burtcInit->enable == true)
145  && (burtcInit->mode != burtcModeDisable)));
146  /* Low power mode is only available with LFRCO or LFXO as clock source */
147  EFM_ASSERT((burtcInit->clkSel != burtcClkSelULFRCO)
148  || ((burtcInit->clkSel == burtcClkSelULFRCO)
149  && (burtcInit->lowPowerMode == burtcLPDisable)));
150 
151  /* Calculate prescaler value from clock divider input */
152  /* Note! If clock select (clkSel) is ULFRCO, a clock divisor (clkDiv) of
153  value 1 will select a 2kHz ULFRCO clock, while any other value will
154  select a 1kHz ULFRCO clock source. */
155  presc = divToLog2(burtcInit->clkDiv);
156 
157  /* Make sure all registers are updated simultaneously */
158  if (burtcInit->enable)
159  {
160  BURTC_FreezeEnable(true);
161  }
162 
163  /* Modification of LPMODE register requires sync with potential ongoing
164  * register updates in LF domain. */
165  regSync(BURTC_SYNCBUSY_LPMODE);
166 
167  /* Configure low power mode */
168  BURTC->LPMODE = (uint32_t) (burtcInit->lowPowerMode);
169 
170  /* New configuration */
171  ctrl = (BURTC_CTRL_RSTEN
172  | (burtcInit->mode)
173  | (burtcInit->debugRun << _BURTC_CTRL_DEBUGRUN_SHIFT)
174  | (burtcInit->compare0Top << _BURTC_CTRL_COMP0TOP_SHIFT)
175  | (burtcInit->lowPowerComp << _BURTC_CTRL_LPCOMP_SHIFT)
176  | (presc << _BURTC_CTRL_PRESC_SHIFT)
177  | (burtcInit->clkSel)
178  | (burtcInit->timeStamp << _BURTC_CTRL_BUMODETSEN_SHIFT));
179 
180  /* Clear interrupts */
181  BURTC_IntClear(0xFFFFFFFF);
182 
183  /* Set new configuration */
184  BURTC->CTRL = ctrl;
185 
186  /* Enable BURTC and counter */
187  if (burtcInit->enable)
188  {
189  /* To enable BURTC counter, we need to disable reset */
190  BURTC_Enable(true);
191 
192  /* Clear freeze */
193  BURTC_FreezeEnable(false);
194  }
195 }
196 
197 
198 /***************************************************************************/
205 void BURTC_CompareSet(unsigned int comp, uint32_t value)
206 {
207  (void) comp; /* Unused parameter when EFM_ASSERT is undefined. */
208 
209  EFM_ASSERT(comp == 0);
210 
211  /* Modification of COMP0 register requires sync with potential ongoing
212  * register updates in LF domain. */
213  regSync(BURTC_SYNCBUSY_COMP0);
214 
215  /* Configure compare channel 0 */
216  BURTC->COMP0 = value;
217 }
218 
219 
220 /***************************************************************************/
227 uint32_t BURTC_CompareGet(unsigned int comp)
228 {
229  (void) comp; /* Unused parameter when EFM_ASSERT is undefined. */
230 
231  EFM_ASSERT(comp == 0);
232 
233  return BURTC->COMP0;
234 }
235 
236 
237 /***************************************************************************/
240 void BURTC_CounterReset(void)
241 {
242  /* Set and clear reset bit */
243  BUS_RegBitWrite(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 1);
244  BUS_RegBitWrite(&BURTC->CTRL, _BURTC_CTRL_RSTEN_SHIFT, 0);
245 }
246 
247 
248 /***************************************************************************/
256 void BURTC_Reset(void)
257 {
258  bool buResetState;
259 
260  /* Read reset state, set reset and restore state */
261  buResetState = BUS_RegBitRead(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT);
262  BUS_RegBitWrite(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT, 1);
263  BUS_RegBitWrite(&RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT, buResetState);
264 }
265 
266 
267 /***************************************************************************/
274 uint32_t BURTC_ClockFreqGet(void)
275 {
276  uint32_t clkSel;
277  uint32_t clkDiv;
278  uint32_t frequency;
279 
280  clkSel = BURTC->CTRL & _BURTC_CTRL_CLKSEL_MASK;
281  clkDiv = (BURTC->CTRL & _BURTC_CTRL_PRESC_MASK) >> _BURTC_CTRL_PRESC_SHIFT;
282 
283  switch (clkSel)
284  {
286  case BURTC_CTRL_CLKSEL_ULFRCO:
287  if (_BURTC_CTRL_PRESC_DIV1 == clkDiv)
288  {
289  frequency = 2000; /* 2KHz when clock divisor is 1. */
290  }
291  else
292  {
293  frequency = SystemULFRCOClockGet(); /* 1KHz when divisor is different
294  from 1. */
295  }
296  break;
297 
299  case BURTC_CTRL_CLKSEL_LFRCO:
300  frequency = SystemLFRCOClockGet() / (1 << clkDiv); /* freq=32768/2^clkDiv */
301  break;
302 
304  case BURTC_CTRL_CLKSEL_LFXO:
305  frequency = SystemLFXOClockGet() / (1 << clkDiv); /* freq=32768/2^clkDiv */
306  break;
307 
308  default:
309  /* No clock selected for BURTC. */
310  frequency = 0;
311  }
312  return frequency;
313 }
314 
315 
319 #endif /* BURTC_PRESENT */
uint32_t SystemLFXOClockGet(void)
Get low frequency crystal oscillator clock frequency for target system.
uint32_t SystemLFRCOClockGet(void)
Get low frequency RC oscillator clock frequency for target system.
__STATIC_INLINE unsigned int BUS_RegBitRead(volatile const uint32_t *addr, unsigned int bit)
Perform a single-bit read operation on a peripheral register.
Definition: em_bus.h:187
#define RMU
Backup Real Time Counter (BURTC) 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:148
uint32_t SystemULFRCOClockGet(void)
Get ultra low frequency RC oscillator clock frequency for target system.