This is the code used on my video series "Hybrid Supercapacitor Car Battery" for my own hardware monitoring system. THe videos can be found on madelectronengineering.com

Dependencies:   BurstSPI Fonts INA219 mbed LPC1114_WakeInterruptIn

Fork of SharpMemoryLCD by Paul Staron

Committer:
madelectroneng
Date:
Tue Dec 26 21:30:09 2017 +0000
Revision:
2:0c49a8f32f6e
Inital setup

Who changed what in which revision?

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