ms2s,STM32 Private
Fork of WakeUp by
Device/WakeUp_STM_RTC.cpp@23:026ce8177010, 2016-10-12 (annotated)
- Committer:
- lzbpli
- Date:
- Wed Oct 12 09:20:07 2016 +0000
- Revision:
- 23:026ce8177010
- Parent:
- 20:68f2ee917691
ms2s
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Sissors | 9:29bdf5fed21a | 1 | #ifdef TARGET_STM |
Sissors | 9:29bdf5fed21a | 2 | |
Sissors | 9:29bdf5fed21a | 3 | #include "WakeUp.h" |
Sissors | 9:29bdf5fed21a | 4 | #include "rtc_api.h" |
Sissors | 9:29bdf5fed21a | 5 | |
Sissors | 9:29bdf5fed21a | 6 | #define BYTE2BCD(byte) ((byte % 10) | ((byte / 10) << 4)) |
Sissors | 9:29bdf5fed21a | 7 | |
Sissors | 9:29bdf5fed21a | 8 | //Most things are pretty similar between the different STM targets. |
Sissors | 9:29bdf5fed21a | 9 | //Only the IRQ number the alarm is connected to differs. Any errors |
Sissors | 9:29bdf5fed21a | 10 | //with RTC_IRQn/RTC_Alarm_IRQn in them are related to this |
Sissors | 15:b2a710aca356 | 11 | #if defined(TARGET_M4) || defined(TARGET_M3) |
Sissors | 9:29bdf5fed21a | 12 | #define RTC_IRQ RTC_Alarm_IRQn |
Sissors | 9:29bdf5fed21a | 13 | #else |
Sissors | 9:29bdf5fed21a | 14 | #define RTC_IRQ RTC_IRQn |
Sissors | 9:29bdf5fed21a | 15 | #endif |
Sissors | 9:29bdf5fed21a | 16 | |
Sissors | 20:68f2ee917691 | 17 | // Some things to handle Disco L476VG (and similar ones) |
Sissors | 20:68f2ee917691 | 18 | #if defined(TARGET_STM32L4) |
Sissors | 20:68f2ee917691 | 19 | #define IMR IMR1 |
Sissors | 20:68f2ee917691 | 20 | #define EMR EMR1 |
Sissors | 20:68f2ee917691 | 21 | #define RTSR RTSR1 |
Sissors | 20:68f2ee917691 | 22 | #define FTSR FTSR2 |
Sissors | 20:68f2ee917691 | 23 | #define PR PR1 |
Sissors | 20:68f2ee917691 | 24 | #endif |
Sissors | 20:68f2ee917691 | 25 | |
Sissors | 17:49d9e3a3e904 | 26 | //Disabling the Backup Powerdomain does not seem to work nicely anymore if you want to use other RTC functions afterwards. |
Sissors | 17:49d9e3a3e904 | 27 | //For now I have disabled it in code, if you find WakeUp increases your powerconsumption, try enabling it again (code is still there, just commented) |
Sissors | 17:49d9e3a3e904 | 28 | |
Sissors | 9:29bdf5fed21a | 29 | FunctionPointer WakeUp::callback; |
Sissors | 9:29bdf5fed21a | 30 | |
lzbpli | 23:026ce8177010 | 31 | void WakeUp::set_ms(uint32_t s) |
Sissors | 9:29bdf5fed21a | 32 | { |
Sissors | 9:29bdf5fed21a | 33 | if (!rtc_isenabled()) { //Make sure RTC is running |
Sissors | 9:29bdf5fed21a | 34 | rtc_init(); |
Sissors | 9:29bdf5fed21a | 35 | wait_us(250); //The f401 seems to want a delay after init |
Sissors | 9:29bdf5fed21a | 36 | } |
Sissors | 9:29bdf5fed21a | 37 | |
Sissors | 17:49d9e3a3e904 | 38 | //PWR->CR |= PWR_CR_DBP; //Enable power domain |
Sissors | 9:29bdf5fed21a | 39 | RTC->WPR = 0xCA; //Disable RTC write protection |
Sissors | 9:29bdf5fed21a | 40 | RTC->WPR = 0x53; |
Sissors | 9:29bdf5fed21a | 41 | |
Sissors | 9:29bdf5fed21a | 42 | //Alarm must be disabled to change anything |
Sissors | 9:29bdf5fed21a | 43 | RTC->CR &= ~RTC_CR_ALRAE; |
Sissors | 9:29bdf5fed21a | 44 | while(!(RTC->ISR & RTC_ISR_ALRAWF)); |
Sissors | 9:29bdf5fed21a | 45 | |
lzbpli | 23:026ce8177010 | 46 | if (s == 0) { //Just disable alarm |
Sissors | 17:49d9e3a3e904 | 47 | //PWR->CR &= ~PWR_CR_DBP; //Disable power domain |
Sissors | 9:29bdf5fed21a | 48 | RTC->WPR = 0xFF; //Enable RTC write protection |
Sissors | 9:29bdf5fed21a | 49 | return; |
Sissors | 9:29bdf5fed21a | 50 | } |
Sissors | 9:29bdf5fed21a | 51 | |
Sissors | 9:29bdf5fed21a | 52 | //RTC prescaler + calculate how many sub-seconds should be added |
Sissors | 9:29bdf5fed21a | 53 | uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1; |
lzbpli | 23:026ce8177010 | 54 | uint32_t subsecsadd = s* prescaler; |
Sissors | 9:29bdf5fed21a | 55 | |
lzbpli | 23:026ce8177010 | 56 | if ((s < 1) && (subsecsadd < 2)) |
Sissors | 9:29bdf5fed21a | 57 | subsecsadd = 2; //At least 2 subsecs delay to be sure interrupt is called |
Sissors | 9:29bdf5fed21a | 58 | |
Sissors | 9:29bdf5fed21a | 59 | __disable_irq(); //At this point we don't want IRQs anymore |
Sissors | 9:29bdf5fed21a | 60 | |
Sissors | 9:29bdf5fed21a | 61 | //Get current time |
Sissors | 9:29bdf5fed21a | 62 | uint32_t subsecs = RTC->SSR; |
Sissors | 9:29bdf5fed21a | 63 | time_t secs = rtc_read(); |
Sissors | 9:29bdf5fed21a | 64 | |
Sissors | 9:29bdf5fed21a | 65 | //Calculate alarm values |
Sissors | 9:29bdf5fed21a | 66 | //Subseconds is countdown, so substract the 'added' sub-seconds and prevent underflow |
Sissors | 9:29bdf5fed21a | 67 | if (subsecs < subsecsadd) { |
Sissors | 9:29bdf5fed21a | 68 | subsecs += prescaler; |
Sissors | 9:29bdf5fed21a | 69 | secs++; |
Sissors | 9:29bdf5fed21a | 70 | } |
Sissors | 9:29bdf5fed21a | 71 | subsecs -= subsecsadd; |
Sissors | 9:29bdf5fed21a | 72 | |
Sissors | 9:29bdf5fed21a | 73 | //Set seconds correctly |
lzbpli | 23:026ce8177010 | 74 | secs += s; |
Sissors | 9:29bdf5fed21a | 75 | struct tm *timeinfo = localtime(&secs); |
Sissors | 9:29bdf5fed21a | 76 | |
Sissors | 9:29bdf5fed21a | 77 | //Enable rising edge EXTI interrupt of the RTC |
Sissors | 20:68f2ee917691 | 78 | EXTI->IMR |= RTC_EXTI_LINE_ALARM_EVENT; |
Sissors | 20:68f2ee917691 | 79 | EXTI->EMR &= ~RTC_EXTI_LINE_ALARM_EVENT; |
Sissors | 20:68f2ee917691 | 80 | EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT; |
Sissors | 20:68f2ee917691 | 81 | EXTI->FTSR &= ~RTC_EXTI_LINE_ALARM_EVENT; |
Sissors | 9:29bdf5fed21a | 82 | |
Sissors | 9:29bdf5fed21a | 83 | //Calculate alarm register values |
Sissors | 9:29bdf5fed21a | 84 | uint32_t alarmreg = 0; |
Sissors | 9:29bdf5fed21a | 85 | alarmreg |= BYTE2BCD(timeinfo->tm_sec) << 0; |
Sissors | 9:29bdf5fed21a | 86 | alarmreg |= BYTE2BCD(timeinfo->tm_min) << 8; |
Sissors | 9:29bdf5fed21a | 87 | alarmreg |= BYTE2BCD(timeinfo->tm_hour) << 16; |
Sissors | 9:29bdf5fed21a | 88 | alarmreg |= BYTE2BCD(timeinfo->tm_mday) << 24; |
Sissors | 9:29bdf5fed21a | 89 | |
Sissors | 9:29bdf5fed21a | 90 | //Enable RTC interrupt |
Sissors | 9:29bdf5fed21a | 91 | RTC->ALRMAR = alarmreg; |
Sissors | 9:29bdf5fed21a | 92 | RTC->ALRMASSR = subsecs | RTC_ALRMASSR_MASKSS; //Mask no subseconds |
Sissors | 9:29bdf5fed21a | 93 | RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; //Enable Alarm |
Sissors | 9:29bdf5fed21a | 94 | |
Sissors | 9:29bdf5fed21a | 95 | RTC->WPR = 0xFF; //Enable RTC write protection |
Sissors | 17:49d9e3a3e904 | 96 | //PWR->CR &= ~PWR_CR_DBP; //Disable power domain |
Sissors | 9:29bdf5fed21a | 97 | |
Sissors | 9:29bdf5fed21a | 98 | __enable_irq(); //Alarm is set, so irqs can be enabled again |
Sissors | 9:29bdf5fed21a | 99 | |
Sissors | 9:29bdf5fed21a | 100 | //Enable everything else |
Sissors | 9:29bdf5fed21a | 101 | NVIC_SetVector(RTC_IRQ, (uint32_t)WakeUp::irq_handler); |
Sissors | 9:29bdf5fed21a | 102 | NVIC_EnableIRQ(RTC_IRQ); |
Sissors | 9:29bdf5fed21a | 103 | } |
Sissors | 9:29bdf5fed21a | 104 | |
Sissors | 9:29bdf5fed21a | 105 | |
Sissors | 9:29bdf5fed21a | 106 | void WakeUp::irq_handler(void) |
Sissors | 9:29bdf5fed21a | 107 | { |
Sissors | 9:29bdf5fed21a | 108 | //Clear RTC + EXTI interrupt flags |
Sissors | 17:49d9e3a3e904 | 109 | //PWR->CR |= PWR_CR_DBP; //Enable power domain |
Sissors | 9:29bdf5fed21a | 110 | RTC->ISR &= ~RTC_ISR_ALRAF; |
Sissors | 17:49d9e3a3e904 | 111 | RTC->WPR = 0xCA; //Disable RTC write protection |
Sissors | 17:49d9e3a3e904 | 112 | RTC->WPR = 0x53; |
Sissors | 17:49d9e3a3e904 | 113 | RTC->CR &= ~RTC_CR_ALRAE; |
Sissors | 17:49d9e3a3e904 | 114 | RTC->WPR = 0xFF; //Enable RTC write protection |
Sissors | 20:68f2ee917691 | 115 | EXTI->PR = RTC_EXTI_LINE_ALARM_EVENT; |
Sissors | 17:49d9e3a3e904 | 116 | //PWR->CR &= ~PWR_CR_DBP; //Disable power domain |
Sissors | 9:29bdf5fed21a | 117 | callback.call(); |
Sissors | 9:29bdf5fed21a | 118 | } |
Sissors | 9:29bdf5fed21a | 119 | |
Sissors | 9:29bdf5fed21a | 120 | void WakeUp::calibrate(void) |
Sissors | 9:29bdf5fed21a | 121 | { |
Sissors | 9:29bdf5fed21a | 122 | //RTC, we assume it is accurate enough without calibration |
Sissors | 9:29bdf5fed21a | 123 | } |
Sissors | 9:29bdf5fed21a | 124 | |
Sissors | 9:29bdf5fed21a | 125 | |
Sissors | 9:29bdf5fed21a | 126 | #endif |