#include #include #include #include #include #include #include static int reset = 0; static uint8_t u8_to_bcd(uint8_t val) { uint32_t quot = (uint32_t)val / 10; uint32_t rem = val - quot * 10; return (quot << 4) | rem; } static inline uint32_t rtc_to_sec(uint32_t rtc) { uint32_t sec; sec = (rtc & 0xf) + ((rtc >> 4) & 0xf) * 10; sec += (((rtc >> 8) & 0xf) + ((rtc >> 12) & 0xf) * 10) * 60; sec += (((rtc >> 16) & 0xf) + ((rtc >> 20) & 0xf) * 10) * 3600; return sec; } static inline uint32_t sec_to_rtc(uint32_t sec) { uint32_t rtc; uint8_t hour; uint8_t min; sec %= SECS_PER_DAY; hour = sec / 3600; rtc = u8_to_bcd(hour) << 16; sec -= hour * 3600; min = sec / 60; rtc |= u8_to_bcd(min) << 8; sec -= min * 60; rtc |= u8_to_bcd(sec); return rtc; } static void rtc_enable_alarm_interrupt(void) { exti_enable_request(EXTI17); exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING); nvic_enable_irq(NVIC_RTC_IRQ); nvic_set_priority(NVIC_RTC_IRQ, 1); RTC_CR |= RTC_CR_ALRAIE; } static void rtc_disable_alarm_interrupt(void) { exti_disable_request(EXTI17); nvic_disable_irq(NVIC_RTC_IRQ); RTC_CR &= ~RTC_CR_ALRAIE; } void rtc_isr(void) { uint32_t alarm_sec; gpio_toggle(GPIOC, GPIO8); pwr_disable_backup_domain_write_protect(); rtc_unlock(); /* Disable the alarm. */ RTC_CR &= ~RTC_CR_ALRAE; RTC_ISR &= ~RTC_ISR_ALRAF; exti_reset_request(EXTI17); if (!reset) { reset = 1; gpio_set(GPIOA, GPIO1); /* Set the alarm time. */ alarm_sec = rtc_to_sec(RTC_TR); (volatile void)RTC_DR; RTC_ALRMAR = sec_to_rtc(alarm_sec + 5) | 0xc0000000; /* Enable the alarm. */ RTC_CR |= RTC_CR_ALRAE; } else { reset = 0; gpio_clear(GPIOA, GPIO1); alarm_disable(); } rtc_lock(); pwr_enable_backup_domain_write_protect(); } int alarm_enable(uint32_t timeout) { uint32_t alarm_sec; pwr_disable_backup_domain_write_protect(); rtc_unlock(); /* Set the alarm time. */ alarm_sec = rtc_to_sec(RTC_TR); (volatile void)RTC_DR; RTC_ALRMAR = sec_to_rtc(alarm_sec + timeout) | 0xc0000000; RTC_CR |= RTC_CR_ALRAE; rtc_enable_alarm_interrupt(); rtc_lock(); pwr_enable_backup_domain_write_protect(); return 0; } int alarm_disable(void) { gpio_set(GPIOC, GPIO8); pwr_disable_backup_domain_write_protect(); rtc_unlock(); RTC_CR &= ~RTC_CR_ALRAE; rtc_disable_alarm_interrupt(); rtc_lock(); pwr_enable_backup_domain_write_protect(); return 0; }