diff --git a/include/rtc.h b/include/rtc.h index 7d6aae0..02e66f4 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -2,6 +2,11 @@ #include +#define SECS_PER_DAY (24 * 60 * 60) + int rtc_init(struct tm *time); int rtc_get_time(struct tm *time); time_t rtc_time(void); + +int alarm_enable(uint32_t timeout); +int alarm_disable(void); diff --git a/source/platform/stm32f0/alarm.c b/source/platform/stm32f0/alarm.c index 9c2f62b..8ef09d4 100644 --- a/source/platform/stm32f0/alarm.c +++ b/source/platform/stm32f0/alarm.c @@ -2,6 +2,22 @@ #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; @@ -16,63 +32,114 @@ static inline uint32_t rtc_to_sec(uint32_t rtc) static inline uint32_t sec_to_rtc(uint32_t sec) { uint32_t rtc; - uint32_t hour, min; + uint8_t hour; + uint8_t min; + + sec %= SECS_PER_DAY; hour = sec / 3600; - min = (sec % 3600) / 60; - sec = sec % 60; + rtc = u8_to_bcd(hour) << 16; + + sec -= hour * 3600; + min = sec / 60; + rtc |= u8_to_bcd(min) << 8; - rtc = ((hour / 10) << 20) | ((hour % 10) << 16); - rtc |= ((min / 10) << 12) | ((min % 10) << 8); - rtc |= ((sec / 10) << 4) | (sec % 10); + sec -= min * 60; + rtc |= u8_to_bcd(sec); return rtc; } -void rtc_alarm_isr(void) +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; - exti_reset_request(EXTI17); + gpio_toggle(GPIOC, GPIO8); + pwr_disable_backup_domain_write_protect(); rtc_unlock(); /* Disable the alarm. */ RTC_CR &= ~RTC_CR_ALRAE; - while (!(RTC_ISR & RTC_ISR_ALRAWF)); RTC_ISR &= ~RTC_ISR_ALRAF; + exti_reset_request(EXTI17); - /* Set the alarm time. */ - alarm_sec = rtc_to_sec(RTC_TR) + 10; - RTC_ALRMAR = sec_to_rtc(alarm_sec); - RTC_ALRMAR |= 0xc0000000; + if (!reset) { + reset = 1; + gpio_set(GPIOA, GPIO1); - /* Enable the alarm. */ - EXTI_IMR |= EXTI17; - exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING); - RTC_CR |= RTC_CR_ALRAE; + /* 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_init(void) +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) + 10; - RTC_ALRMAR = sec_to_rtc(alarm_sec); - RTC_ALRMAR |= 0xc0000000; + alarm_sec = rtc_to_sec(RTC_TR); + (volatile void)RTC_DR; + RTC_ALRMAR = sec_to_rtc(alarm_sec + timeout) | 0xc0000000; - RTC_CR |= RTC_CR_ALRAIE | RTC_CR_BYPSHAD; + RTC_CR |= RTC_CR_ALRAE; + rtc_enable_alarm_interrupt(); - nvic_enable_irq(NVIC_RTC_IRQ); - EXTI_IMR |= EXTI17; - exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING); + rtc_lock(); + pwr_enable_backup_domain_write_protect(); + + return 0; +} + +int alarm_disable(void) +{ + uint32_t alarm_sec; + + 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; } diff --git a/source/platform/stm32f1/alarm.c b/source/platform/stm32f1/alarm.c index bc76bd7..36c42b4 100644 --- a/source/platform/stm32f1/alarm.c +++ b/source/platform/stm32f1/alarm.c @@ -1,29 +1,56 @@ #include #include +#include #include +#include + +static int reset = 0; + void rtc_alarm_isr(void) { - exti_reset_request(EXTI17); - if (rtc_check_flag(RTC_ALR)) { rtc_clear_flag(RTC_ALR); - rtc_set_alarm_time(rtc_get_counter_val() + 10); + rtc_disable_alarm(); + exti_reset_request(EXTI17); + + if (!reset) { + reset = 1; + gpio_set(GPIOA, GPIO1); - EXTI_IMR |= EXTI17; - exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING); + rtc_set_alarm_time(rtc_get_counter_val() + 5); + rtc_enable_alarm(); + } else { + reset = 0; + gpio_set(GPIOA, GPIO1); + alarm_disable(); + } } } -int alarm_init(void) +int alarm_enable(uint32_t timeout) { rtc_enable_alarm(); - rtc_set_alarm_time(rtc_get_counter_val() + 10); + rtc_set_alarm_time(rtc_get_counter_val() + timeout); - nvic_enable_irq(NVIC_RTC_ALARM_IRQ); - EXTI_IMR |= EXTI17; + exti_enable_request(EXTI17); exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING); + nvic_enable_irq(NVIC_RTC_ALARM_IRQ); + nvic_set_priority(NVIC_RTC_ALARM_IRQ, 1); + + rtc_interrupt_enable(RTC_ALR); + + return 0; +} + +int alarm_disable(void) +{ + exti_disable_request(EXTI17); + nvic_disable_irq(NVIC_RTC_ALARM_IRQ); + rtc_interrupt_disable(RTC_ALR); + rtc_disable_alarm(); + return 0; }