diff options
-rw-r--r-- | board/zinger/board.h | 8 | ||||
-rw-r--r-- | board/zinger/ec.irqlist | 1 | ||||
-rw-r--r-- | board/zinger/hardware.c | 44 | ||||
-rw-r--r-- | board/zinger/runtime.c | 86 | ||||
-rw-r--r-- | chip/stm32/clock-stm32f0.c | 39 |
5 files changed, 129 insertions, 49 deletions
diff --git a/board/zinger/board.h b/board/zinger/board.h index e26d5a5e96..639991be33 100644 --- a/board/zinger/board.h +++ b/board/zinger/board.h @@ -74,6 +74,14 @@ int flash_write_rw(int offset, int size, const char *data); uint8_t *flash_hash_rw(void); int is_ro_mode(void); +/* RTC functions */ +void rtc_init(void); +void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us, + uint32_t *rtc, uint32_t *rtcss); +void reset_rtc_alarm(uint32_t *rtc, uint32_t *rtcss); +int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss, + uint32_t rtc1, uint32_t rtc1ss); + /* Reboot the CPU */ void cpu_reset(void); diff --git a/board/zinger/ec.irqlist b/board/zinger/ec.irqlist index 5c710893c4..f158d2e079 100644 --- a/board/zinger/ec.irqlist +++ b/board/zinger/ec.irqlist @@ -11,3 +11,4 @@ ENABLE_IRQ(STM32_IRQ_EXTI4_15) ENABLE_IRQ(STM32_IRQ_ADC_COMP) ENABLE_IRQ(STM32_IRQ_TIM2) +ENABLE_IRQ(STM32_IRQ_RTC_WAKEUP) diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c index 1358220ee3..1b22ec64c4 100644 --- a/board/zinger/hardware.c +++ b/board/zinger/hardware.c @@ -15,35 +15,23 @@ #include "util.h" #include "watchdog.h" -static void clock_init(void) +static void system_init(void) { - /* - * put 1 Wait-State for flash access to ensure proper reads at 48Mhz - * and enable prefetch buffer. - */ - STM32_FLASH_ACR = STM32_FLASH_ACR_LATENCY | STM32_FLASH_ACR_PRFTEN; - - /* Ensure that HSI8 is ON */ - if (!(STM32_RCC_CR & (1 << 1))) { - /* Enable HSI */ - STM32_RCC_CR |= 1 << 0; - /* Wait for HSI to be ready */ - while (!(STM32_RCC_CR & (1 << 1))) - ; - } - /* PLLSRC = HSI, PLLMUL = x12 (x HSI/2) = 48Mhz */ - STM32_RCC_CFGR = 0x00288000; - /* Enable PLL */ - STM32_RCC_CR |= 1 << 24; - /* Wait for PLL to be ready */ - while (!(STM32_RCC_CR & (1 << 25))) - ; + /* Enable access to RCC CSR register and RTC backup registers */ + STM32_PWR_CR |= 1 << 8; - /* switch SYSCLK to PLL */ - STM32_RCC_CFGR = 0x00288002; - /* wait until the PLL is the clock source */ - while ((STM32_RCC_CFGR & 0xc) != 0x8) + /* switch on LSI */ + STM32_RCC_CSR |= 1 << 0; + /* Wait for LSI to be ready */ + while (!(STM32_RCC_CSR & (1 << 1))) ; + /* re-configure RTC if needed */ + if ((STM32_RCC_BDCR & 0x00018300) != 0x00008200) { + /* the RTC settings are bad, we need to reset it */ + STM32_RCC_BDCR |= 0x00010000; + /* Enable RTC and use LSI as clock source */ + STM32_RCC_BDCR = (STM32_RCC_BDCR & ~0x00018300) | 0x00008200; + } } static void power_init(void) @@ -165,10 +153,12 @@ static void irq_init(void) asm("cpsie i"); } +extern void runtime_init(void); void hardware_init(void) { power_init(); - clock_init(); + system_init(); + runtime_init(); /* sets clock */ pins_init(); uart_init(); timers_init(); diff --git a/board/zinger/runtime.c b/board/zinger/runtime.c index deaa87d6ab..e7fb421f49 100644 --- a/board/zinger/runtime.c +++ b/board/zinger/runtime.c @@ -4,6 +4,7 @@ */ /* tiny substitute of the runtime layer */ +#include "clock.h" #include "common.h" #include "cpu.h" #include "debug.h" @@ -23,6 +24,11 @@ timestamp_t get_time(void) return t; } +void force_time(timestamp_t ts) +{ + STM32_TIM32_CNT(2) = ts.le.lo; +} + void udelay(unsigned us) { unsigned t0 = STM32_TIM32_CNT(2); @@ -60,9 +66,57 @@ void tim2_interrupt(void) } DECLARE_IRQ(STM32_IRQ_TIM2, tim2_interrupt, 1); +static void config_hispeed_clock(void) +{ + /* Ensure that HSI8 is ON */ + if (!(STM32_RCC_CR & (1 << 1))) { + /* Enable HSI */ + STM32_RCC_CR |= 1 << 0; + /* Wait for HSI to be ready */ + while (!(STM32_RCC_CR & (1 << 1))) + ; + } + /* PLLSRC = HSI, PLLMUL = x12 (x HSI/2) = 48Mhz */ + STM32_RCC_CFGR = 0x00288000; + /* Enable PLL */ + STM32_RCC_CR |= 1 << 24; + /* Wait for PLL to be ready */ + while (!(STM32_RCC_CR & (1 << 25))) + ; + + /* switch SYSCLK to PLL */ + STM32_RCC_CFGR = 0x00288002; + /* wait until the PLL is the clock source */ + while ((STM32_RCC_CFGR & 0xc) != 0x8) + ; +} + +void runtime_init(void) +{ + /* put 1 Wait-State for flash access to ensure proper reads at 48Mhz */ + STM32_FLASH_ACR = 0x1001; /* 1 WS / Prefetch enabled */ + + config_hispeed_clock(); + + rtc_init(); +} + +/* + * minimum delay to enter stop mode + * STOP_MODE_LATENCY: max time to wake up from STOP mode with regulator in low + * power mode is 5 us + PLL locking time is 200us. + * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. if we set the alarm + * in the past, it will never wake up and cause a watchdog. + */ +#define STOP_MODE_LATENCY 300 /* us */ +#define SET_RTC_MATCH_DELAY 200 /* us */ + uint32_t task_wait_event(int timeout_us) { uint32_t evt; + timestamp_t t0; + uint32_t rtc0, rtc0ss, rtc1, rtc1ss; + int rtc_diff; asm volatile("cpsid i"); /* the event already happened */ @@ -75,16 +129,38 @@ uint32_t task_wait_event(int timeout_us) } /* set timeout on timer */ - if (timeout_us > 0) { + if (timeout_us < 0) { + asm volatile ("wfi"); + } else if (timeout_us <= (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY)) { STM32_TIM32_CCR1(2) = STM32_TIM32_CNT(2) + timeout_us; STM32_TIM_SR(2) = 0; /* clear match flag */ STM32_TIM_DIER(2) = 2; /* match interrupt */ - } - /* sleep until next interrupt */ - asm volatile("wfi"); + asm volatile("wfi"); + + STM32_TIM_DIER(2) = 0; /* disable match interrupt */ + } else { + t0 = get_time(); + + /* set deep sleep bit */ + CPU_SCB_SYSCTRL |= 0x4; + + set_rtc_alarm(0, timeout_us - STOP_MODE_LATENCY, + &rtc0, &rtc0ss); + + asm volatile("wfi"); + + CPU_SCB_SYSCTRL &= ~0x4; + + config_hispeed_clock(); + + /* fast forward timer according to RTC counter */ + reset_rtc_alarm(&rtc1, &rtc1ss); + rtc_diff = get_rtc_diff(rtc0, rtc0ss, rtc1, rtc1ss); + t0.val = t0.val + rtc_diff; + force_time(t0); + } - STM32_TIM_DIER(2) = 0; /* disable match interrupt */ asm volatile("cpsie i ; isb"); /* note: interrupt that woke us up will run here */ diff --git a/chip/stm32/clock-stm32f0.c b/chip/stm32/clock-stm32f0.c index b43a442f02..76583eaab0 100644 --- a/chip/stm32/clock-stm32f0.c +++ b/chip/stm32/clock-stm32f0.c @@ -108,8 +108,8 @@ static inline uint32_t sec_to_rtc(uint32_t sec) } /* Return time diff between two rtc readings */ -static inline int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss, - uint32_t rtc1, uint32_t rtc1ss) +int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss, + uint32_t rtc1, uint32_t rtc1ss) { int32_t diff; @@ -381,22 +381,8 @@ void clock_enable_module(enum module_id module, int enable) { } -void clock_init(void) +void rtc_init(void) { - /* - * The initial state : - * SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2 - * PLL unlocked, RTC enabled on LSE - */ - - /* - * put 1 Wait-State for flash access to ensure proper reads at 48Mhz - * and enable prefetch buffer. - */ - STM32_FLASH_ACR = STM32_FLASH_ACR_LATENCY | STM32_FLASH_ACR_PRFTEN; - - config_hispeed_clock(); - rtc_unlock_regs(); /* Enter RTC initialize mode */ @@ -420,6 +406,25 @@ void clock_init(void) rtc_lock_regs(); } +void clock_init(void) +{ + /* + * The initial state : + * SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2 + * PLL unlocked, RTC enabled on LSE + */ + + /* + * put 1 Wait-State for flash access to ensure proper reads at 48Mhz + * and enable prefetch buffer. + */ + STM32_FLASH_ACR = STM32_FLASH_ACR_LATENCY | STM32_FLASH_ACR_PRFTEN; + + config_hispeed_clock(); + + rtc_init(); +} + /*****************************************************************************/ /* Console commands */ |