IoT-MBBR (masterthesis)
Masterthesis upgrading a Moving Bed BioReactor with extra sensors and cloud connectivity.
delay.c File Reference

Delay functionality. More...

#include <stdint.h>
#include <stdbool.h>
#include "em_device.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "em_rtc.h"
#include "delay.h"
#include "debug_dbprint.h"

Go to the source code of this file.

Macros

#define ULFRCOFREQ   1000
 
#define ULFRCOFREQ_MS   1.000
 
#define LFXOFREQ   32768
 
#define LFXOFREQ_MS   32.768
 

Functions

static void initRTC (void)
 RTC initialization. More...
 
void delay (uint32_t msDelay)
 Wait for a certain amount of milliseconds in EM2/3. More...
 
void sleep (uint32_t sSleep)
 Sleep for a certain amount of seconds in EM2/3. More...
 
bool RTC_checkWakeup (void)
 Method to check if the wakeup was caused by the RTC. More...
 
void RTC_clearWakeup (void)
 Method to clear RTC_sleep_wakeup. More...
 
uint32_t RTC_getPassedSleeptime (void)
 Method to get the time spend sleeping (in seconds) in the case of GPIO wake-up. More...
 
void RTC_IRQHandler (void)
 Interrupt Service Routine for the RTC. More...
 

Variables

static volatile bool RTC_sleep_wakeup = false
 
bool sleeping = false
 
bool RTC_initialized = false
 

Detailed Description

Delay functionality.

Version
3.4
Author
Brecht Van Eeckhoudt

Versions

  • v1.0: Moved delay functionality from util.c to this file.
  • v1.1: Changed global variables to be static (~hidden) and added dbprint \ n \ r fixes.
  • v1.2: Removed EM1 delay method (see note in delayRTCC_EM2).
  • v1.3: Cleaned up includes, added option to select SysTick/EM2 delay functionality and moved all of the logic in one delay method. Renamed sleep method.
  • v1.4: Changed names of static variables, made initRTCcomp static.
  • v1.5: Updated documentation.
  • v1.6: Changed RTCcomp names to RTC.
  • v1.7: Moved IRQ handler of RTC to this file.
  • v1.8: Added ULFRCO logic.
  • v1.9: Updated code with new DEFINE checks.
  • v2.0: Added functionality to enable/disable the clocks only when necessary.
  • v2.1: Added functionality to check if a wakeup was caused by the RTC.
  • v2.2: Removed some clock disabling statements.
  • v2.3: Changed error numbering.
  • v2.4: Moved definitions from header to source file.
  • v2.5: Added functionality to the time spend sleeping.
  • v3.0: Disabled peripheral clock before entering an error function, added functionality to exit methods after error call and updated version number.
  • v3.1: Removed static before some local variables (not necessary).
  • v3.2: Moved msTicks variable and systick handler in #if check.
  • v3.3: Added include for the boolean type in the header file, changed dbwarnInt to dbinfoInt, added the ability to enable/disable the sleep-announcing.
  • v3.4: Added logic to initialize delay/sleep when calling the methods using 0 as the delay time.

Todo:
Future improvements:
  • Enable/disable clock functionality? (see comments using //)

License

Copyright (C) 2020 - Brecht Van Eeckhoudt

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

A copy of the GNU General Public License can be found in the LICENSE file along with this source code.


Some methods use code obtained from examples from Silicon Labs' GitHub. These sections are licensed under the Silabs License Agreement. See the file "Silabs_License_Agreement.txt" for details. Before using this software for any purpose, you must agree to the terms of that agreement.

Definition in file delay.c.

Macro Definition Documentation

◆ LFXOFREQ

#define LFXOFREQ   32768

Definition at line 87 of file delay.c.

◆ LFXOFREQ_MS

#define LFXOFREQ_MS   32.768

Definition at line 88 of file delay.c.

◆ ULFRCOFREQ

#define ULFRCOFREQ   1000

Definition at line 85 of file delay.c.

◆ ULFRCOFREQ_MS

#define ULFRCOFREQ_MS   1.000

Definition at line 86 of file delay.c.

Function Documentation

◆ delay()

void delay ( uint32_t  msDelay)

Wait for a certain amount of milliseconds in EM2/3.

This method can be called with the argument 0 to force initialization.
This method also initializes SysTick/RTC if necessary.

Parameters
[in]msDelayThe delay time in milliseconds.

Definition at line 124 of file delay.c.

125 {
126 
127 #if SYSTICKDELAY == 1 /* SysTick delay selected */
128 
129  /* Initialize SysTick if not already the case */
130  if (!SysTick_initialized)
131  {
132  /* Initialize and start SysTick
133  * Number of ticks between interrupt = cmuClock_CORE/1000 */
134  if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1);
135 
136 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
137  dbinfo("SysTick initialized");
138 #endif /* DEBUG_DBPRINT */
139 
140  SysTick_initialized = true;
141  }
142  else
143  {
144  /* Only execute if we're not initializing */
145  if (msDelay > 0)
146  {
147  /* Enable SysTick interrupt and counter by setting their bits. */
148  SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
149  }
150  }
151 
152  /* Only execute if we're not initializing */
153  if (msDelay > 0)
154  {
155  /* Wait a certain amount of ticks */
156  uint32_t curTicks = msTicks;
157  while ((msTicks - curTicks) < msDelay);
158 
159  /* Disable SysTick interrupt and counter (needs to be done before entering EM2/3) by clearing their bits. */
160  SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk & ~SysTick_CTRL_ENABLE_Msk;
161  }
162 
163 #else /* EM2/3 RTC delay selected */
164 
165 
166  /* Initialize RTC if not already the case */
167  if (!RTC_initialized) initRTC();
168  else
169  {
170  /* Only execute if we're not initializing */
171  if (msDelay > 0)
172  {
173  /* Enable necessary oscillator and clocks */
174 
175 #if ULFRCO == 1 /* ULFRCO selected */
176 
177  /* No specific code here */
178 
179 #else /* LFXO selected */
180 
181  /* Enable the low-frequency crystal oscillator for the RTC */
182  //CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
183 
184 #endif /* ULFRCO/LFXO selection */
185 
186  /* Enable the clock to the interface of the low energy modules
187  * cmuClock_CORELE = cmuClock_HFLE (deprecated) */
188  //CMU_ClockEnable(cmuClock_HFLE, true);
189 
190  /* Turn on the RTC clock */
191  CMU_ClockEnable(cmuClock_RTC, true);
192  }
193  }
194 
195  /* Only execute if we're not initializing */
196  if (msDelay > 0)
197  {
198 
199  /* Set RTC compare value for RTC compare register 0 depending on ULFRCO/LFXO selection */
200 
201 #if ULFRCO == 1 /* ULFRCO selected */
202 
203  if ((ULFRCOFREQ_MS * msDelay) <= 0x00ffffff) RTC_CompareSet(0, (ULFRCOFREQ_MS * msDelay));
204  else
205  {
206 
207 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
208  dbcrit("Delay too long, can't fit in the field!");
209 #endif /* DEBUG_DBPRINT */
210 
211  /* Turn off the RTC clock */
212  CMU_ClockEnable(cmuClock_RTC, false);
213 
214 // error(14);
215 
216  /* Exit function */
217  return;
218  }
219 
220 #else /* LFXO selected */
221 
222  if ((LFXOFREQ_MS * msDelay) <= 0x00ffffff) RTC_CompareSet(0, (LFXOFREQ_MS * msDelay));
223  else
224  {
225 
226 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
227  dbcrit("Delay too long, can't fit in the field!");
228 #endif /* DEBUG_DBPRINT */
229 
230  /* Turn off the RTC clock */
231  CMU_ClockEnable(cmuClock_RTC, false);
232 
233 // error(15);
234 
235  /* Exit function */
236  return;
237  }
238 
239 #endif /* ULFRCO/LFXO selection */
240 
241 
242  /* Start the RTC */
243  RTC_Enable(true);
244 
245  /* Enter EM2/3 depending on ULFRCO/LFXO selection */
246 
247 #if ULFRCO == 1 /* ULFRCO selected */
248  /* In EM3, high and low frequency clocks are disabled. No oscillator (except the ULFRCO) is running.
249  * Furthermore, all unwanted oscillators are disabled in EM3. This means that nothing needs to be
250  * manually disabled before the statement EMU_EnterEM3(true); */
251  EMU_EnterEM3(true); /* "true" - Save and restore oscillators, clocks and voltage scaling */
252 #else /* LFXO selected */
253  EMU_EnterEM2(true); /* "true" - Save and restore oscillators, clocks and voltage scaling */
254 #endif /* ULFRCO/LFXO selection */
255 
256 
257  /* Disable used oscillator and clocks after wake-up */
258 
259 #if ULFRCO == 1 /* ULFRCO selected */
260 
261  /* No specific code here */
262 
263 #else /* LFXO selected */
264 
265  /* Disable the low-frequency crystal oscillator for the RTC */
266  //CMU_OscillatorEnable(cmuOsc_LFXO, false, true);
267 
268 #endif /* ULFRCO/LFXO selection */
269 
270  /* Disable the clock to the interface of the low energy modules
271  * cmuClock_CORELE = cmuClock_HFLE (deprecated) */
272  //CMU_ClockEnable(cmuClock_HFLE, false);
273 
274  /* Turn off the RTC clock */
275  CMU_ClockEnable(cmuClock_RTC, false);
276  }
277 
278 #endif /* SysTick/RTC selection */
279 
280 }
static void initRTC(void)
RTC initialization.
Definition: delay.c:481
bool RTC_initialized
Definition: delay.c:102
void dbinfo(char *message)
Print an info string (char array) to USARTx and go to the next line.
Definition: dbprint.c:505
#define LFXOFREQ_MS
Definition: delay.c:88
#define ULFRCOFREQ_MS
Definition: delay.c:86
void dbcrit(char *message)
Print a critical error string (char array) in red to USARTx and go to the next line.
Definition: dbprint.c:541
unsigned int uint32_t
Typedef defining 32 bit unsigned int type. The developer should modify this to suit the platform bein...
Definition: vl53l1_types.h:78

◆ initRTC()

static void initRTC ( void  )
static

RTC initialization.

Note
This is a static method because it's only internally used in this file and called by other methods if necessary.

Definition at line 481 of file delay.c.

482 {
483 
484 #if ULFRCO == 1 /* ULFRCO selected */
485 
486  /* Enable the ultra low-frequency RC oscillator for the RTC */
487  //CMU_OscillatorEnable(cmuOsc_ULFRCO, true, true); /* The ULFRCO is always on */
488 
489  /* Enable the clock to the interface of the low energy modules
490  * cmuClock_CORELE = cmuClock_HFLE (deprecated) */
491  CMU_ClockEnable(cmuClock_HFLE, true);
492 
493  /* Route the ULFRCO clock to the RTC */
494  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO);
495 
496 #else /* LFXO selected */
497 
498  /* Enable the low-frequency crystal oscillator for the RTC */
499  CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
500 
501  /* Enable the clock to the interface of the low energy modules
502  * cmuClock_CORELE = cmuClock_HFLE (deprecated) */
503  CMU_ClockEnable(cmuClock_HFLE, true);
504 
505  /* Route the LFXO clock to the RTC */
506  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO);
507 
508 #endif /* ULFRCO/LFXO selection */
509 
510  /* Turn on the RTC clock */
511  CMU_ClockEnable(cmuClock_RTC, true);
512 
513  /* Allow channel 0 to cause an interrupt */
514  RTC_IntEnable(RTC_IEN_COMP0);
515  RTC_IntClear(RTC_IFC_COMP0); /* This statement was in the ULFRCO but not in the LFXO example. It's kept here just in case. */
516  NVIC_ClearPendingIRQ(RTC_IRQn);
517  NVIC_EnableIRQ(RTC_IRQn);
518 
519  /* Configure the RTC settings */
520  RTC_Init_TypeDef rtc = RTC_INIT_DEFAULT;
521  rtc.enable = false; /* Don't start counting when initialization is done */
522 
523  /* Initialize RTC with pre-defined settings */
524  RTC_Init(&rtc);
525 
526 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
527 #if ULFRCO == 1 /* ULFRCO selected */
528  dbinfo("RTC initialized with ULFRCO");
529 #else /* LFXO selected */
530  dbinfo("RTC initialized with LFXO");
531 #endif /* ULFRCO/LFXO selection */
532 #endif /* DEBUG_DBPRINT */
533 
534  RTC_initialized = true;
535 }
bool RTC_initialized
Definition: delay.c:102
void dbinfo(char *message)
Print an info string (char array) to USARTx and go to the next line.
Definition: dbprint.c:505

◆ RTC_checkWakeup()

bool RTC_checkWakeup ( void  )

Method to check if the wakeup was caused by the RTC.

Returns
The value of RTC_sleep_wakeup.

Definition at line 432 of file delay.c.

433 {
434  return (RTC_sleep_wakeup);
435 }
static volatile bool RTC_sleep_wakeup
Definition: delay.c:94

◆ RTC_clearWakeup()

void RTC_clearWakeup ( void  )

Method to clear RTC_sleep_wakeup.

Definition at line 442 of file delay.c.

443 {
444  RTC_sleep_wakeup = false;
445 }
static volatile bool RTC_sleep_wakeup
Definition: delay.c:94

◆ RTC_getPassedSleeptime()

uint32_t RTC_getPassedSleeptime ( void  )

Method to get the time spend sleeping (in seconds) in the case of GPIO wake-up.

Returns
The time spend sleeping in seconds.

Definition at line 456 of file delay.c.

457 {
458  uint32_t sSleep = RTC_CounterGet();
459 
460  /* Disable the counter */
461  RTC_Enable(false);
462 
463 #if ULFRCO == 1 /* ULFRCO selected */
464  sSleep /= ULFRCOFREQ;
465 #else /* LFXO selected */
466  sSleep /= LFXOFREQ;
467 #endif /* ULFRCO/LFXO selection */
468 
469  return (sSleep);
470 }
#define ULFRCOFREQ
Definition: delay.c:85
#define LFXOFREQ
Definition: delay.c:87
unsigned int uint32_t
Typedef defining 32 bit unsigned int type. The developer should modify this to suit the platform bein...
Definition: vl53l1_types.h:78

◆ RTC_IRQHandler()

void RTC_IRQHandler ( void  )

Interrupt Service Routine for the RTC.

Note
The weak definition for this method is located in system_efm32hg.h.

Definition at line 557 of file delay.c.

558 {
559  /* Disable the counter */
560  RTC_Enable(false);
561 
562  /* Clear the interrupt source */
563  RTC_IntClear(RTC_IFC_COMP0);
564 
565  /* If the wakeup was caused by "sleeping" (not a delay), act accordingly */
566  if (sleeping) RTC_sleep_wakeup = true;
567 }
static volatile bool RTC_sleep_wakeup
Definition: delay.c:94
bool sleeping
Definition: delay.c:101

◆ sleep()

void sleep ( uint32_t  sSleep)

Sleep for a certain amount of seconds in EM2/3.

This method also initializes the RTC if necessary.

Parameters
[in]sSleepThe sleep time in seconds.

Definition at line 293 of file delay.c.

294 {
295  /* Initialize RTC if not already the case */
296  if (!RTC_initialized) initRTC();
297  else
298  {
299  /* Only execute if we're not initializing */
300  if (sSleep > 0)
301  {
302 
303  /* Enable necessary oscillator and clocks */
304 
305 #if ULFRCO == 1 /* ULFRCO selected */
306 
307  /* No specific code here */
308 
309 #else /* LFXO selected */
310 
311  /* Enable the low-frequency crystal oscillator for the RTC */
312  //CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
313 
314 #endif /* ULFRCO/LFXO selection */
315 
316  /* Enable the clock to the interface of the low energy modules
317  * cmuClock_CORELE = cmuClock_HFLE (deprecated) */
318  //CMU_ClockEnable(cmuClock_HFLE, true);
319 
320  /* Turn on the RTC clock */
321  CMU_ClockEnable(cmuClock_RTC, true);
322  }
323  }
324 
325  /* Only execute if we're not initializing */
326  if (sSleep > 0)
327  {
328 
329 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
330 #if ANNOUNCE_SLEEPING == 1 /* Announce sleeping enabled */
331 #if ULFRCO == 1 /* ULFRCO selected */
332  dbinfoInt("Sleeping in EM3 for ", sSleep, " s\n\r\n\r");
333 #else /* LFXO selected */
334  dbinfoInt("Sleeping in EM2 for ", sSleep, " s\n\r\n\r");
335 #endif /* ULFRCO/LFXO selection */
336 #endif /* Announce sleeping */
337 #endif /* DEBUG_DBPRINT */
338 
339  /* Set RTC compare value for RTC compare register 0 depending on ULFRCO/LFXO selection */
340 
341 #if ULFRCO == 1 /* ULFRCO selected */
342 
343  if ((ULFRCOFREQ * sSleep) <= 0x00ffffff) RTC_CompareSet(0, (ULFRCOFREQ * sSleep));
344  else
345  {
346 
347 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
348  dbcrit("Delay too long, can't fit in the field!");
349 #endif /* DEBUG_DBPRINT */
350 
351  /* Turn off the RTC clock */
352  CMU_ClockEnable(cmuClock_RTC, false);
353 
354 // error(16);
355 
356  /* Exit function */
357  return;
358  }
359 
360 #else /* LFXO selected */
361 
362  if ((LFXOFREQ * sSleep) <= 0x00ffffff) RTC_CompareSet(0, (LFXOFREQ * sSleep));
363  else
364  {
365 
366 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
367  dbcrit("Delay too long, can't fit in the field!");
368 #endif /* DEBUG_DBPRINT */
369 
370  /* Turn off the RTC clock */
371  CMU_ClockEnable(cmuClock_RTC, false);
372 
373 // error(17);
374 
375  /* Exit function */
376  return;
377  }
378 
379 #endif /* ULFRCO/LFXO selection */
380 
381  /* Indicate that we're using the sleep method */
382  sleeping = true;
383 
384 
385  /* Start the RTC */
386  RTC_Enable(true);
387 
388  /* Enter EM2/3 depending on ULFRCO/LFXO selection */
389 
390 #if ULFRCO == 1 /* ULFRCO selected */
391  /* In EM3, high and low frequency clocks are disabled. No oscillator (except the ULFRCO) is running.
392  * Furthermore, all unwanted oscillators are disabled in EM3. This means that nothing needs to be
393  * manually disabled before the statement EMU_EnterEM3(true); */
394  EMU_EnterEM3(true); /* "true" - Save and restore oscillators, clocks and voltage scaling */
395 #else /* LFXO selected */
396  EMU_EnterEM2(true); /* "true" - Save and restore oscillators, clocks and voltage scaling */
397 #endif /* ULFRCO/LFXO selection */
398 
399  /* Indicate that we're no longer sleeping */
400  sleeping = false;
401 
402  /* Disable used oscillator and clocks after wake-up */
403 
404 #if ULFRCO == 1 /* ULFRCO selected */
405 
406  /* No specific code here */
407 
408 #else /* LFXO selected */
409 
410  /* Disable the low-frequency crystal oscillator for the RTC */
411  //CMU_OscillatorEnable(cmuOsc_LFXO, false, true);
412 
413 #endif /* ULFRCO/LFXO selection */
414 
415  /* Disable the clock to the interface of the low energy modules
416  * cmuClock_CORELE = cmuClock_HFLE (deprecated) */
417  //CMU_ClockEnable(cmuClock_HFLE, false);
418 
419  /* Turn off the RTC clock */
420  CMU_ClockEnable(cmuClock_RTC, false);
421  }
422 }
#define ULFRCOFREQ
Definition: delay.c:85
void dbinfoInt(char *message1, int32_t value, char *message2)
Print an info value surrounded by two strings (char array) to USARTx.
Definition: dbprint.c:569
static void initRTC(void)
RTC initialization.
Definition: delay.c:481
bool RTC_initialized
Definition: delay.c:102
void dbcrit(char *message)
Print a critical error string (char array) in red to USARTx and go to the next line.
Definition: dbprint.c:541
#define LFXOFREQ
Definition: delay.c:87
bool sleeping
Definition: delay.c:101

Variable Documentation

◆ RTC_initialized

bool RTC_initialized = false

Definition at line 102 of file delay.c.

◆ RTC_sleep_wakeup

volatile bool RTC_sleep_wakeup = false
static

Definition at line 94 of file delay.c.

◆ sleeping

bool sleeping = false

Definition at line 101 of file delay.c.