You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
2.5 KiB
143 lines
2.5 KiB
#include <libopencm3/cm3/nvic.h>
|
|
#include <libopencm3/stm32/exti.h>
|
|
#include <libopencm3/stm32/rtc.h>
|
|
|
|
#include <libopencm3/stm32/rcc.h>
|
|
#include <libopencm3/stm32/gpio.h>
|
|
#include <libopencm3/stm32/pwr.h>
|
|
|
|
#include <rtc.h>
|
|
|
|
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;
|
|
}
|
|
|