Enable RTC and deep sleep (stop mode)
This commit is contained in:
parent
6fc7e27c0b
commit
d313860804
159
src/main.c
159
src/main.c
|
@ -3,6 +3,9 @@
|
|||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/dma.h>
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
#include <libopencm3/stm32/rtc.h>
|
||||
#include <libopencm3/stm32/pwr.h>
|
||||
#include <libopencm3/stm32/exti.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
|
||||
|
@ -33,6 +36,19 @@ volatile int wait_frame = 1;
|
|||
#define ADC_NUM_CHANNELS 3
|
||||
volatile uint16_t adc_values[ADC_NUM_CHANNELS];
|
||||
|
||||
static void unlock_rtc_access(void)
|
||||
{
|
||||
pwr_disable_backup_domain_write_protect();
|
||||
RTC_WPR = 0xCA;
|
||||
RTC_WPR = 0x53;
|
||||
}
|
||||
|
||||
static void lock_rtc_access(void)
|
||||
{
|
||||
RTC_WPR = 0xFF;
|
||||
pwr_enable_backup_domain_write_protect();
|
||||
}
|
||||
|
||||
static void init_gpio(void)
|
||||
{
|
||||
// Set up UART TX on PB6 for debugging
|
||||
|
@ -79,6 +95,39 @@ static void init_clock(void)
|
|||
rcc_periph_clock_enable(RCC_DMA);
|
||||
}
|
||||
|
||||
static void init_rtc(void)
|
||||
{
|
||||
// RTC clock setup
|
||||
// see libopencm3-examples::examples/stm32/l1/stm32l-discovery/button-irq-printf-lowpower/main.c
|
||||
|
||||
/* turn on power block to enable unlocking */
|
||||
rcc_periph_clock_enable(RCC_PWR);
|
||||
pwr_disable_backup_domain_write_protect();
|
||||
|
||||
/* reset rtc */
|
||||
RCC_BDCR |= RCC_BDCR_BDRST;
|
||||
RCC_BDCR &= ~RCC_BDCR_BDRST;
|
||||
|
||||
// use LSI for RTC
|
||||
rcc_osc_on(RCC_LSI);
|
||||
rcc_wait_for_osc_ready(RCC_LSI);
|
||||
|
||||
/* Select the LSI as rtc clock */
|
||||
RCC_BDCR |= RCC_BDCR_RTCSEL_LSI;
|
||||
|
||||
/* ?! Stdperiph examples don't turn this on until _afterwards_ which
|
||||
* simply doesn't work. It must be on at least to be able to
|
||||
* configure it */
|
||||
RCC_BDCR |= RCC_BDCR_RTCEN;
|
||||
|
||||
pwr_enable_backup_domain_write_protect();
|
||||
|
||||
nvic_enable_irq(NVIC_RTC_IRQ);
|
||||
|
||||
exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING);
|
||||
exti_enable_request(EXTI17);
|
||||
}
|
||||
|
||||
static void init_timer(void)
|
||||
{
|
||||
// *** TIM1 ***
|
||||
|
@ -183,6 +232,83 @@ static void init_adc(void)
|
|||
|
||||
}
|
||||
|
||||
static void deepsleep(uint32_t duration_secs)
|
||||
{
|
||||
uint32_t tmp = 0;
|
||||
|
||||
// unlock RTC registers
|
||||
unlock_rtc_access();
|
||||
|
||||
// enter initialization mode
|
||||
RTC_ISR |= RTC_ISR_INIT;
|
||||
|
||||
// wait until initialization mode has been entered
|
||||
while((RTC_ISR & RTC_ISR_INITF) != RTC_ISR_INITF) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
RTC_TR = 0; // 00:00:00
|
||||
RTC_DR = // friday, 01.01.16
|
||||
(1 << RTC_DR_YT_SHIFT) |
|
||||
(6 << RTC_DR_YU_SHIFT) |
|
||||
(5 << RTC_DR_WDU_SHIFT) |
|
||||
(0 << RTC_DR_MT_SHIFT) |
|
||||
(1 << RTC_DR_MU_SHIFT) |
|
||||
(0 << RTC_DR_DT_SHIFT) |
|
||||
(1 << RTC_DR_DU_SHIFT);
|
||||
|
||||
// disable Alarm A
|
||||
RTC_CR &= ~RTC_CR_ALRAE;
|
||||
|
||||
// wait until register is writeable
|
||||
while((RTC_ISR & RTC_ISR_ALRAWF) != RTC_ISR_ALRAWF) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
tmp |= (duration_secs % 10) << RTC_ALRMXR_SU_SHIFT;
|
||||
duration_secs /= 10;
|
||||
|
||||
tmp |= (duration_secs % 6) << RTC_ALRMXR_ST_SHIFT;
|
||||
duration_secs /= 6;
|
||||
|
||||
tmp |= (duration_secs % 10) << RTC_ALRMXR_MNU_SHIFT;
|
||||
duration_secs /= 10;
|
||||
|
||||
tmp |= (duration_secs % 6) << RTC_ALRMXR_MNT_SHIFT;
|
||||
duration_secs /= 6;
|
||||
|
||||
tmp |= (duration_secs % 10) << RTC_ALRMXR_HU_SHIFT;
|
||||
duration_secs /= 10;
|
||||
|
||||
tmp |= (duration_secs % 2) << RTC_ALRMXR_HT_SHIFT;
|
||||
// FIXME: >1d is not supported
|
||||
|
||||
tmp |= RTC_ALRMXR_MSK4; // ignore day/date
|
||||
|
||||
// set alarm register
|
||||
RTC_ALRMAR = tmp;
|
||||
|
||||
// clear Alarm A flag
|
||||
RTC_ISR &= ~RTC_ISR_ALRAF;
|
||||
|
||||
// enable RTC alarm interrupt for wakeup
|
||||
RTC_CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE;
|
||||
|
||||
// leave initialization mode
|
||||
RTC_ISR &= ~RTC_ISR_INIT;
|
||||
|
||||
// lock registers again (using invalid key)
|
||||
lock_rtc_access();
|
||||
|
||||
// enter deep sleep mode
|
||||
SCB_SCR |= SCB_SCR_SLEEPDEEP;
|
||||
PWR_CR |= PWR_CR_LPDS; // voltage regulator low-power mode
|
||||
pwr_set_stop_mode();
|
||||
__WFI();
|
||||
SCB_SCR &= ~SCB_SCR_SLEEPDEEP; // no deepsleep except in this function
|
||||
init_clock();
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Set up timer to fire freq times per second */
|
||||
static void init_systick(int freq)
|
||||
|
@ -256,6 +382,7 @@ int main(void)
|
|||
fxp_t CURRENT_OFFSET = fxp_from_float(0.049);
|
||||
|
||||
init_clock();
|
||||
init_rtc();
|
||||
init_gpio();
|
||||
init_adc();
|
||||
init_timer();
|
||||
|
@ -514,6 +641,14 @@ int main(void)
|
|||
nextState = ConvMPP;
|
||||
}
|
||||
|
||||
if(time_in_state > 10000) {
|
||||
lcd_set_cursor_pos(0, 0);
|
||||
lcd_send_string("Sleep mode ");
|
||||
while(lcd_process() == 0); // send everything immediately
|
||||
deepsleep(10);
|
||||
time_in_state = 9500; // run the voltage test again
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -598,6 +733,25 @@ int main(void)
|
|||
sentSomething = 1;
|
||||
}
|
||||
|
||||
if((timebase_ms % 500) == 300) {
|
||||
debug_send_string("RTC seconds: ");
|
||||
|
||||
fxp_format_int((RTC_TR >> RTC_TR_SU_SHIFT) & RTC_TR_SU_MASK, msg);
|
||||
debug_send_string(msg);
|
||||
|
||||
debug_send_string(" - ALRAF: ");
|
||||
|
||||
fxp_format_int(RTC_ISR & RTC_ISR_ALRAF, msg);
|
||||
debug_send_string(msg);
|
||||
|
||||
debug_send_string(" - EXTI17: ");
|
||||
|
||||
fxp_format_int(exti_get_flag_status(EXTI17), msg);
|
||||
debug_send_string(msg);
|
||||
|
||||
sentSomething = 1;
|
||||
}
|
||||
|
||||
if(sentSomething) {
|
||||
debug_send_string("\r\n");
|
||||
sentSomething = 0;
|
||||
|
@ -633,6 +787,11 @@ void tim3_isr(void)
|
|||
}
|
||||
}
|
||||
|
||||
void rtc_isr(void)
|
||||
{
|
||||
exti_reset_request(EXTI17);
|
||||
}
|
||||
|
||||
void hard_fault_handler(void)
|
||||
{
|
||||
while (1);
|
||||
|
|
Loading…
Reference in a new issue