Si-Labs EFM32 back up domain and BUrtc library

Dependents:   EFM32_BUrtc-Demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BUrtc.cpp Source File

BUrtc.cpp

00001 
00002 #include "mbed.h"
00003 #include "BUrtc.h"
00004 
00005 void BUrtcInit(void)
00006 {   
00007     // Read and clear RMU->RSTCAUSE as early as possible
00008     resetcause = 0;
00009     resetcause = RMU->RSTCAUSE;
00010     RMU_ResetCauseClear();
00011     // power up back up domian
00012     budSetup();
00013  
00014     // If waking from backup mode, restore time from retention registers
00015     if ( !(resetcause & RMU_RSTCAUSE_BUBODBUVIN) && (resetcause & RMU_RSTCAUSE_BUMODERST) ) {
00016         // Check if retention registers were being written to when backup mode was entered
00017         if ( (BURTC->STATUS & BURTC_STATUS_RAMWERR) >> _BURTC_STATUS_RAMWERR_SHIFT ) {
00018         }
00019         // Check if timestamp is written
00020         if (! ((BURTC->STATUS & BURTC_STATUS_BUMODETS) >> _BURTC_STATUS_BUMODETS_SHIFT) ) {
00021         }
00022         // Restore time from backup RTC + retention memory
00023         RTCrestore();
00024         // Reset timestamp
00025         BURTC_StatusClear();
00026     }
00027 
00028     // If normal startup, initialize BURTC
00029     else {
00030         // Setup BURTC
00031         burtcSetup();
00032         set_time(0);
00033         // Reset overflow counter
00034         rtcOverflowCounter = 0;
00035         // Reset BUrtc counter
00036         BURTC_CounterReset();        
00037         // Backup Reset values to BUrtc retention registers
00038         BUrtcBackup();    
00039         // Set overflow interval based on counter width and frequency
00040         overflow_interval  =  ((uint64_t)UINT32_MAX+1) / COUNTS_PER_SEC; // in seconds
00041         overflow_interval_r = ((uint64_t)UINT32_MAX+1) % COUNTS_PER_SEC; // division remainder
00042         // Compute overflow interval (integer) and remainder
00043         burtcOverflowIntervalRem = ((uint64_t)UINT32_MAX+1)%COUNTS_BETWEEN_UPDATE;
00044         // burtcSetComp( COUNTS_BETWEEN_UPDATE );
00045         BURTC_CompareSet(0, COUNTS_BETWEEN_UPDATE );                
00046     } 
00047     // Enable BURTC interrupts   
00048     NVIC_ClearPendingIRQ(BURTC_IRQn);
00049     NVIC_EnableIRQ(BURTC_IRQn);   
00050 }
00051 
00052 void RTCset(int seconds)
00053 {  
00054     // Set system RTC time
00055     set_time(seconds);
00056     // Set BUrtc to start from zero
00057     BURTC_CounterReset();
00058     // Set system RTC epoch offset
00059     rtcStartTime = seconds;
00060     // reset overflow counter
00061     rtcOverflowCounter = 0;
00062     // Backup new RTC value to BUrtc retention registers
00063     BUrtcBackup();
00064     // Compute overflow interval (integer) and remainder
00065     burtcOverflowIntervalRem = ((uint64_t)UINT32_MAX+1)%COUNTS_BETWEEN_UPDATE;
00066     // burtcSetComp( COUNTS_BETWEEN_UPDATE );
00067     BURTC_CompareSet(0, COUNTS_BETWEEN_UPDATE ); 
00068 }
00069 
00070 void BURTC_IRQHandler(void)
00071 {
00072     uint32_t irq;
00073     irq = BURTC_IntGet();
00074     BURTC_IntClear(irq);
00075     //   Interrupt source: compare match
00076     //   Increment compare value and
00077     //   update TFT display 
00078     if ( irq & BURTC_IF_COMP0 ) {
00079         BURTC_CompareSet(0, BURTC->COMP0 + COUNTS_BETWEEN_UPDATE );
00080     }
00081     //   Interrupt source: counter overflow
00082     //   Increase overflow counter
00083     //   and backup calendar
00084     if ( irq & BURTC_IF_OF ) {
00085         rtcOverflowCounter++;
00086         BUrtcBackup();
00087     }   
00088 }
00089 
00090 void BUrtcBackup(void)
00091 {
00092     // Write overflow counter to retention memory
00093     BURTC_RetRegSet(0, rtcOverflowCounter);
00094     // Write system RTC epoch offset to retention memory
00095     BURTC_RetRegSet(1, rtcStartTime);
00096 }
00097 
00098 void RTCrestore(void)  
00099 {
00100     int burtcStart;
00101     int nextUpdate;
00102     // Store BURTC->CNT for consistency in display output within this function
00103     burtcCount = BURTC_CounterGet();
00104     // Timestamp is BURTC value at time of main power loss
00105     burtcTimestamp = BURTC_TimestampGet();
00106     // Read overflow counter from retention memory
00107     burtcOverflowCounter = BURTC_RetRegGet(0);
00108     //   Check for overflow while in backup mode
00109     //   Assume that overflow interval >> backup source capacity
00110     //   i.e. that overflow has only occured once during main power loss
00111     if ( burtcCount < burtcTimestamp ) {
00112         burtcOverflowCounter++;
00113     }
00114     // Restore epoch offset from retention memory
00115     rtcStartTime = (BURTC_RetRegGet(1));
00116     // Restore clock overflow counter 
00117     rtcOverflowCounter = burtcOverflowCounter;
00118     //   Calculate start point for current BURTC count cycle
00119     //   If (COUNTS_BETWEEN_UPDATE/burtcOverflowInterval) is not an integer,
00120     //   BURTC value at first update is different between each count cycle
00121     burtcStart = (burtcOverflowCounter * (COUNTS_BETWEEN_UPDATE - burtcOverflowIntervalRem)) % COUNTS_BETWEEN_UPDATE;
00122     //  Calculate next update compare value
00123     //  Add 1 extra UPDATE_INTERVAL to be sure that counter doesn't
00124     //  pass COMP value before interrupts are enabled 
00125     nextUpdate = burtcStart + ((burtcCount / COUNTS_BETWEEN_UPDATE) +1 ) * COUNTS_BETWEEN_UPDATE ;
00126     BURTC_CompareSet(0, nextUpdate);
00127     // Add the time offset
00128     trtc = rtcStartTime;
00129     // Add time based on number of counter overflows
00130     trtc += rtcOverflowCounter * overflow_interval;
00131     // Correct if overflow interval is not an integer
00132     if ( overflow_interval_r != 0 )  {
00133         trtc += rtcOverflowCounter * overflow_interval_r / COUNTS_PER_SEC;
00134     }
00135     // Add the number of seconds for BURTC
00136     trtc += int(BURTC->CNT / COUNTS_PER_SEC);
00137     // Wait to line up next second BUrtc interrupt
00138     while(!BURTC_IntGet()){}
00139     // restore RTC time
00140     set_time (trtc+1);
00141 }
00142 
00143 void burtcSetup(void)
00144 {
00145     BURTC_Init_TypeDef burtcInit = BURTC_INIT_DEFAULT;
00146     // Select LFXO as clock source for BURTC
00147     burtcInit.clkSel = burtcClkSelLFXO;
00148     //Enable BURTC operation in EM0-EM4
00149     burtcInit.mode = burtcModeEM4;
00150     // Set prescaler to max. Resolution is not that important here
00151     burtcInit.clkDiv = 128;
00152     // Enable BURTC timestamp upon backup mode entry
00153     burtcInit.timeStamp = true;
00154     // Counter doesn't wrap around when CNT == COMP0
00155     burtcInit.compare0Top = false;
00156     burtcInit.enable = true;
00157     // Enable interrupt on compare match
00158     BURTC_IntClear(BURTC_IEN_COMP0);
00159     BURTC_IntEnable(BURTC_IEN_COMP0);
00160     BURTC_Init(&burtcInit);
00161 }
00162 
00163 void budSetup(void )
00164 {
00165     EMU_EM4Init_TypeDef em4Init = EMU_EM4INIT_DEFAULT;
00166     EMU_BUPDInit_TypeDef bupdInit = EMU_BUPDINIT_DEFAULT;
00167     // Unlock configuration
00168     EMU_EM4Lock(false);
00169     //Enable backup status pin
00170     bupdInit.statusPinEnable = false;
00171     // Enable backup power domain
00172     bupdInit.enable = true;
00173     // Normal operation: Connect main power to backup power through diode
00174     bupdInit.inactivePower = emuPower_MainBU;
00175     // Backup mode: No connection between backup power and main power
00176     bupdInit.activePower = emuPower_None;
00177     // Set backup "charging" resistor
00178     bupdInit.resistor = emuRes_Res3;
00179     EMU_BUPDInit(&bupdInit);
00180     // Wait until backup power functionality is ready
00181     EMU_BUReady();
00182     // Release reset for backup domain
00183     RMU_ResetControl(rmuResetBU, rmuResetModeClear);
00184     // Enable BU_VIN pin
00185     bupdInit.enable = true;
00186     // Enable voltage regulator in backup mode
00187     em4Init.vreg = true;
00188     // Configure oscillators in EM4
00189     em4Init.osc = emuEM4Osc_LFXO;
00190     // Lock configuration in case of brown out
00191     em4Init.lockConfig = true;
00192     EMU_EM4Init(&em4Init);
00193 }
00194 
00195