rtcdrv.c

Go to the documentation of this file.
00001 /***************************************************************************/
00018 #include <stddef.h>
00019 #include "em_device.h"
00020 #include "em_cmu.h"
00021 #include "em_emu.h"
00022 #include "em_rtc.h"
00023 #include "rtcdrv.h"
00024 
00025 static void          (*rtcCb)(void);        
00026 static uint8_t       rtcInitialized = 0;    
00027 static volatile bool rtcDelayComplete;      
00028 static uint32_t      rtcFreq;               
00030 /***************************************************************************/
00033 static void DelayCB(void)
00034 {
00035   rtcDelayComplete = true;
00036 }
00037 
00038 /***************************************************************************/
00047 void RTCDRV_Setup(CMU_Select_TypeDef lfaClockSrc, CMU_ClkDiv_TypeDef rtcPrescale)
00048 {
00049   RTC_Init_TypeDef init;
00050 
00051   rtcInitialized = 1;
00052 
00053   /* Ensure LE modules are accessible */
00054   CMU_ClockEnable(cmuClock_CORELE, true);
00055 
00056   /* Enable LFACLK in CMU (will also enable oscillator if not enabled) */
00057   CMU_ClockSelectSet(cmuClock_LFA, lfaClockSrc);
00058 
00059   /* Use the prescaler to reduce power consumption. */
00060   CMU_ClockDivSet(cmuClock_RTC, rtcPrescale);
00061 
00062   rtcFreq = CMU_ClockFreqGet(cmuClock_RTC);
00063 
00064   /* Enable clock to RTC module */
00065   CMU_ClockEnable(cmuClock_RTC, true);
00066 
00067   init.enable   = false;
00068   init.debugRun = false;
00069   init.comp0Top = false; /* Count to max before wrapping */
00070   RTC_Init(&init);
00071 
00072   /* Disable interrupt generation from RTC0 */
00073   RTC_IntDisable(_RTC_IF_MASK);
00074 
00075   /* Enable interrupts */
00076   NVIC_ClearPendingIRQ(RTC_IRQn);
00077   NVIC_EnableIRQ(RTC_IRQn);
00078 }
00079 
00080 /***************************************************************************/
00085 void RTCDRV_Delay(uint32_t msec, bool useEM2)
00086 {
00087   rtcDelayComplete = false;
00088   RTCDRV_Trigger(msec, DelayCB);
00089 
00090   while (!rtcDelayComplete)
00091   {
00092     if (useEM2)
00093     {
00094       EMU_EnterEM2(true);
00095     }
00096   }
00097 }
00098 
00099 /***************************************************************************/
00102 void RTC_IRQHandler(void)
00103 {
00104   /* Disable RTC */
00105   RTC_Enable(false);
00106 
00107   /* Clear interrupt source */
00108   RTC_IntClear(RTC_IF_COMP0);
00109 
00110   /* Disable interrupt */
00111   RTC_IntDisable(RTC_IF_COMP0);
00112 
00113   /* Trigger callback if defined */
00114   if (rtcCb)
00115   {
00116     rtcCb();
00117   }
00118 }
00119 
00120 
00121 /***************************************************************************/
00126 void RTCDRV_Trigger(uint32_t msec, void (*cb)(void))
00127 {
00128   /* Disable RTC - this will also reset the counter. */
00129   RTC_Enable(false);
00130 
00131   /* Auto init if not configured already */
00132   if (!rtcInitialized)
00133   {
00134     /* Default to LFRCO as clock source and prescale by 32. */
00135     RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32);
00136   }
00137 
00138   /* Register callback */
00139   rtcCb = cb;
00140 
00141   /* Clear interrupt source */
00142   RTC_IntClear(RTC_IF_COMP0);
00143 
00144   /* Calculate trigger value in ticks based on 32768Hz clock */
00145   RTC_CompareSet(0, (rtcFreq * msec) / 1000);
00146 
00147   /* Enable RTC */
00148   RTC_Enable(true);
00149 
00150   /* Enable interrupt on COMP0 */
00151   RTC_IntEnable(RTC_IF_COMP0);
00152 }