stm32f0: stm32f1: alarm: implement functionality to enable and disable the alarm with a time-out for resetting the host

master
S.J.R. van Schaik 7 years ago
parent 40ba5323f3
commit 0542810d22
  1. 5
      include/rtc.h
  2. 117
      source/platform/stm32f0/alarm.c
  3. 45
      source/platform/stm32f1/alarm.c

@ -2,6 +2,11 @@
#include <time.h>
#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);

@ -2,6 +2,22 @@
#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;
@ -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;
}

@ -1,29 +1,56 @@
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rtc.h>
#include <rtc.h>
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;
}

Loading…
Cancel
Save