Si-Labs EFM32 back up domain and BUrtc library

Dependents:   EFM32_BUrtc-Demo

Committer:
star297
Date:
Mon May 16 23:12:27 2016 +0000
Revision:
0:7756f444d879
BUrtc initial release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
star297 0:7756f444d879 1
star297 0:7756f444d879 2 #include "mbed.h"
star297 0:7756f444d879 3 #include "BUrtc.h"
star297 0:7756f444d879 4
star297 0:7756f444d879 5 void BUrtcInit(void)
star297 0:7756f444d879 6 {
star297 0:7756f444d879 7 // Read and clear RMU->RSTCAUSE as early as possible
star297 0:7756f444d879 8 resetcause = 0;
star297 0:7756f444d879 9 resetcause = RMU->RSTCAUSE;
star297 0:7756f444d879 10 RMU_ResetCauseClear();
star297 0:7756f444d879 11 // power up back up domian
star297 0:7756f444d879 12 budSetup();
star297 0:7756f444d879 13
star297 0:7756f444d879 14 // If waking from backup mode, restore time from retention registers
star297 0:7756f444d879 15 if ( !(resetcause & RMU_RSTCAUSE_BUBODBUVIN) && (resetcause & RMU_RSTCAUSE_BUMODERST) ) {
star297 0:7756f444d879 16 // Check if retention registers were being written to when backup mode was entered
star297 0:7756f444d879 17 if ( (BURTC->STATUS & BURTC_STATUS_RAMWERR) >> _BURTC_STATUS_RAMWERR_SHIFT ) {
star297 0:7756f444d879 18 }
star297 0:7756f444d879 19 // Check if timestamp is written
star297 0:7756f444d879 20 if (! ((BURTC->STATUS & BURTC_STATUS_BUMODETS) >> _BURTC_STATUS_BUMODETS_SHIFT) ) {
star297 0:7756f444d879 21 }
star297 0:7756f444d879 22 // Restore time from backup RTC + retention memory
star297 0:7756f444d879 23 RTCrestore();
star297 0:7756f444d879 24 // Reset timestamp
star297 0:7756f444d879 25 BURTC_StatusClear();
star297 0:7756f444d879 26 }
star297 0:7756f444d879 27
star297 0:7756f444d879 28 // If normal startup, initialize BURTC
star297 0:7756f444d879 29 else {
star297 0:7756f444d879 30 // Setup BURTC
star297 0:7756f444d879 31 burtcSetup();
star297 0:7756f444d879 32 set_time(0);
star297 0:7756f444d879 33 // Reset overflow counter
star297 0:7756f444d879 34 rtcOverflowCounter = 0;
star297 0:7756f444d879 35 // Reset BUrtc counter
star297 0:7756f444d879 36 BURTC_CounterReset();
star297 0:7756f444d879 37 // Backup Reset values to BUrtc retention registers
star297 0:7756f444d879 38 BUrtcBackup();
star297 0:7756f444d879 39 // Set overflow interval based on counter width and frequency
star297 0:7756f444d879 40 overflow_interval = ((uint64_t)UINT32_MAX+1) / COUNTS_PER_SEC; // in seconds
star297 0:7756f444d879 41 overflow_interval_r = ((uint64_t)UINT32_MAX+1) % COUNTS_PER_SEC; // division remainder
star297 0:7756f444d879 42 // Compute overflow interval (integer) and remainder
star297 0:7756f444d879 43 burtcOverflowIntervalRem = ((uint64_t)UINT32_MAX+1)%COUNTS_BETWEEN_UPDATE;
star297 0:7756f444d879 44 // burtcSetComp( COUNTS_BETWEEN_UPDATE );
star297 0:7756f444d879 45 BURTC_CompareSet(0, COUNTS_BETWEEN_UPDATE );
star297 0:7756f444d879 46 }
star297 0:7756f444d879 47 // Enable BURTC interrupts
star297 0:7756f444d879 48 NVIC_ClearPendingIRQ(BURTC_IRQn);
star297 0:7756f444d879 49 NVIC_EnableIRQ(BURTC_IRQn);
star297 0:7756f444d879 50 }
star297 0:7756f444d879 51
star297 0:7756f444d879 52 void RTCset(int seconds)
star297 0:7756f444d879 53 {
star297 0:7756f444d879 54 // Set system RTC time
star297 0:7756f444d879 55 set_time(seconds);
star297 0:7756f444d879 56 // Set BUrtc to start from zero
star297 0:7756f444d879 57 BURTC_CounterReset();
star297 0:7756f444d879 58 // Set system RTC epoch offset
star297 0:7756f444d879 59 rtcStartTime = seconds;
star297 0:7756f444d879 60 // reset overflow counter
star297 0:7756f444d879 61 rtcOverflowCounter = 0;
star297 0:7756f444d879 62 // Backup new RTC value to BUrtc retention registers
star297 0:7756f444d879 63 BUrtcBackup();
star297 0:7756f444d879 64 // Compute overflow interval (integer) and remainder
star297 0:7756f444d879 65 burtcOverflowIntervalRem = ((uint64_t)UINT32_MAX+1)%COUNTS_BETWEEN_UPDATE;
star297 0:7756f444d879 66 // burtcSetComp( COUNTS_BETWEEN_UPDATE );
star297 0:7756f444d879 67 BURTC_CompareSet(0, COUNTS_BETWEEN_UPDATE );
star297 0:7756f444d879 68 }
star297 0:7756f444d879 69
star297 0:7756f444d879 70 void BURTC_IRQHandler(void)
star297 0:7756f444d879 71 {
star297 0:7756f444d879 72 uint32_t irq;
star297 0:7756f444d879 73 irq = BURTC_IntGet();
star297 0:7756f444d879 74 BURTC_IntClear(irq);
star297 0:7756f444d879 75 // Interrupt source: compare match
star297 0:7756f444d879 76 // Increment compare value and
star297 0:7756f444d879 77 // update TFT display
star297 0:7756f444d879 78 if ( irq & BURTC_IF_COMP0 ) {
star297 0:7756f444d879 79 BURTC_CompareSet(0, BURTC->COMP0 + COUNTS_BETWEEN_UPDATE );
star297 0:7756f444d879 80 }
star297 0:7756f444d879 81 // Interrupt source: counter overflow
star297 0:7756f444d879 82 // Increase overflow counter
star297 0:7756f444d879 83 // and backup calendar
star297 0:7756f444d879 84 if ( irq & BURTC_IF_OF ) {
star297 0:7756f444d879 85 rtcOverflowCounter++;
star297 0:7756f444d879 86 BUrtcBackup();
star297 0:7756f444d879 87 }
star297 0:7756f444d879 88 }
star297 0:7756f444d879 89
star297 0:7756f444d879 90 void BUrtcBackup(void)
star297 0:7756f444d879 91 {
star297 0:7756f444d879 92 // Write overflow counter to retention memory
star297 0:7756f444d879 93 BURTC_RetRegSet(0, rtcOverflowCounter);
star297 0:7756f444d879 94 // Write system RTC epoch offset to retention memory
star297 0:7756f444d879 95 BURTC_RetRegSet(1, rtcStartTime);
star297 0:7756f444d879 96 }
star297 0:7756f444d879 97
star297 0:7756f444d879 98 void RTCrestore(void)
star297 0:7756f444d879 99 {
star297 0:7756f444d879 100 int burtcStart;
star297 0:7756f444d879 101 int nextUpdate;
star297 0:7756f444d879 102 // Store BURTC->CNT for consistency in display output within this function
star297 0:7756f444d879 103 burtcCount = BURTC_CounterGet();
star297 0:7756f444d879 104 // Timestamp is BURTC value at time of main power loss
star297 0:7756f444d879 105 burtcTimestamp = BURTC_TimestampGet();
star297 0:7756f444d879 106 // Read overflow counter from retention memory
star297 0:7756f444d879 107 burtcOverflowCounter = BURTC_RetRegGet(0);
star297 0:7756f444d879 108 // Check for overflow while in backup mode
star297 0:7756f444d879 109 // Assume that overflow interval >> backup source capacity
star297 0:7756f444d879 110 // i.e. that overflow has only occured once during main power loss
star297 0:7756f444d879 111 if ( burtcCount < burtcTimestamp ) {
star297 0:7756f444d879 112 burtcOverflowCounter++;
star297 0:7756f444d879 113 }
star297 0:7756f444d879 114 // Restore epoch offset from retention memory
star297 0:7756f444d879 115 rtcStartTime = (BURTC_RetRegGet(1));
star297 0:7756f444d879 116 // Restore clock overflow counter
star297 0:7756f444d879 117 rtcOverflowCounter = burtcOverflowCounter;
star297 0:7756f444d879 118 // Calculate start point for current BURTC count cycle
star297 0:7756f444d879 119 // If (COUNTS_BETWEEN_UPDATE/burtcOverflowInterval) is not an integer,
star297 0:7756f444d879 120 // BURTC value at first update is different between each count cycle
star297 0:7756f444d879 121 burtcStart = (burtcOverflowCounter * (COUNTS_BETWEEN_UPDATE - burtcOverflowIntervalRem)) % COUNTS_BETWEEN_UPDATE;
star297 0:7756f444d879 122 // Calculate next update compare value
star297 0:7756f444d879 123 // Add 1 extra UPDATE_INTERVAL to be sure that counter doesn't
star297 0:7756f444d879 124 // pass COMP value before interrupts are enabled
star297 0:7756f444d879 125 nextUpdate = burtcStart + ((burtcCount / COUNTS_BETWEEN_UPDATE) +1 ) * COUNTS_BETWEEN_UPDATE ;
star297 0:7756f444d879 126 BURTC_CompareSet(0, nextUpdate);
star297 0:7756f444d879 127 // Add the time offset
star297 0:7756f444d879 128 trtc = rtcStartTime;
star297 0:7756f444d879 129 // Add time based on number of counter overflows
star297 0:7756f444d879 130 trtc += rtcOverflowCounter * overflow_interval;
star297 0:7756f444d879 131 // Correct if overflow interval is not an integer
star297 0:7756f444d879 132 if ( overflow_interval_r != 0 ) {
star297 0:7756f444d879 133 trtc += rtcOverflowCounter * overflow_interval_r / COUNTS_PER_SEC;
star297 0:7756f444d879 134 }
star297 0:7756f444d879 135 // Add the number of seconds for BURTC
star297 0:7756f444d879 136 trtc += int(BURTC->CNT / COUNTS_PER_SEC);
star297 0:7756f444d879 137 // Wait to line up next second BUrtc interrupt
star297 0:7756f444d879 138 while(!BURTC_IntGet()){}
star297 0:7756f444d879 139 // restore RTC time
star297 0:7756f444d879 140 set_time (trtc+1);
star297 0:7756f444d879 141 }
star297 0:7756f444d879 142
star297 0:7756f444d879 143 void burtcSetup(void)
star297 0:7756f444d879 144 {
star297 0:7756f444d879 145 BURTC_Init_TypeDef burtcInit = BURTC_INIT_DEFAULT;
star297 0:7756f444d879 146 // Select LFXO as clock source for BURTC
star297 0:7756f444d879 147 burtcInit.clkSel = burtcClkSelLFXO;
star297 0:7756f444d879 148 //Enable BURTC operation in EM0-EM4
star297 0:7756f444d879 149 burtcInit.mode = burtcModeEM4;
star297 0:7756f444d879 150 // Set prescaler to max. Resolution is not that important here
star297 0:7756f444d879 151 burtcInit.clkDiv = 128;
star297 0:7756f444d879 152 // Enable BURTC timestamp upon backup mode entry
star297 0:7756f444d879 153 burtcInit.timeStamp = true;
star297 0:7756f444d879 154 // Counter doesn't wrap around when CNT == COMP0
star297 0:7756f444d879 155 burtcInit.compare0Top = false;
star297 0:7756f444d879 156 burtcInit.enable = true;
star297 0:7756f444d879 157 // Enable interrupt on compare match
star297 0:7756f444d879 158 BURTC_IntClear(BURTC_IEN_COMP0);
star297 0:7756f444d879 159 BURTC_IntEnable(BURTC_IEN_COMP0);
star297 0:7756f444d879 160 BURTC_Init(&burtcInit);
star297 0:7756f444d879 161 }
star297 0:7756f444d879 162
star297 0:7756f444d879 163 void budSetup(void )
star297 0:7756f444d879 164 {
star297 0:7756f444d879 165 EMU_EM4Init_TypeDef em4Init = EMU_EM4INIT_DEFAULT;
star297 0:7756f444d879 166 EMU_BUPDInit_TypeDef bupdInit = EMU_BUPDINIT_DEFAULT;
star297 0:7756f444d879 167 // Unlock configuration
star297 0:7756f444d879 168 EMU_EM4Lock(false);
star297 0:7756f444d879 169 //Enable backup status pin
star297 0:7756f444d879 170 bupdInit.statusPinEnable = false;
star297 0:7756f444d879 171 // Enable backup power domain
star297 0:7756f444d879 172 bupdInit.enable = true;
star297 0:7756f444d879 173 // Normal operation: Connect main power to backup power through diode
star297 0:7756f444d879 174 bupdInit.inactivePower = emuPower_MainBU;
star297 0:7756f444d879 175 // Backup mode: No connection between backup power and main power
star297 0:7756f444d879 176 bupdInit.activePower = emuPower_None;
star297 0:7756f444d879 177 // Set backup "charging" resistor
star297 0:7756f444d879 178 bupdInit.resistor = emuRes_Res3;
star297 0:7756f444d879 179 EMU_BUPDInit(&bupdInit);
star297 0:7756f444d879 180 // Wait until backup power functionality is ready
star297 0:7756f444d879 181 EMU_BUReady();
star297 0:7756f444d879 182 // Release reset for backup domain
star297 0:7756f444d879 183 RMU_ResetControl(rmuResetBU, rmuResetModeClear);
star297 0:7756f444d879 184 // Enable BU_VIN pin
star297 0:7756f444d879 185 bupdInit.enable = true;
star297 0:7756f444d879 186 // Enable voltage regulator in backup mode
star297 0:7756f444d879 187 em4Init.vreg = true;
star297 0:7756f444d879 188 // Configure oscillators in EM4
star297 0:7756f444d879 189 em4Init.osc = emuEM4Osc_LFXO;
star297 0:7756f444d879 190 // Lock configuration in case of brown out
star297 0:7756f444d879 191 em4Init.lockConfig = true;
star297 0:7756f444d879 192 EMU_EM4Init(&em4Init);
star297 0:7756f444d879 193 }
star297 0:7756f444d879 194
star297 0:7756f444d879 195