Si-Labs EFM32 back up domain and BUrtc library
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 17:51:58 by 1.7.2