Implement fake and true deep sleep alarm differentiation
This commit is contained in:
parent
17585e1e07
commit
66a1583183
@ -39,11 +39,7 @@
|
|||||||
#include "supervisor/port.h"
|
#include "supervisor/port.h"
|
||||||
#include "supervisor/shared/workflow.h"
|
#include "supervisor/shared/workflow.h"
|
||||||
|
|
||||||
#define STM_WAKEUP_UNDEF 0
|
STATIC uint8_t true_deep_wake_reason;
|
||||||
#define STM_WAKEUP_GPIO 1
|
|
||||||
#define STM_WAKEUP_RTC 2
|
|
||||||
|
|
||||||
#define STM_ALARM_FLAG RTC->BKP0R
|
|
||||||
|
|
||||||
void alarm_reset(void) {
|
void alarm_reset(void) {
|
||||||
// Reset the alarm flag
|
// Reset the alarm flag
|
||||||
@ -54,6 +50,12 @@ void alarm_reset(void) {
|
|||||||
// esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
|
// esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kind of a hack, required as RTC is reset in port.c
|
||||||
|
// TODO: in the future, don't reset it at all, just override critical flags
|
||||||
|
void alarm_set_wakeup_reason(uint8_t reason) {
|
||||||
|
true_deep_wake_reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
STATIC uint8_t _get_wakeup_cause(void) {
|
STATIC uint8_t _get_wakeup_cause(void) {
|
||||||
// If in light/fake sleep, check modules
|
// If in light/fake sleep, check modules
|
||||||
if (alarm_pin_pinalarm_woke_us_up()) {
|
if (alarm_pin_pinalarm_woke_us_up()) {
|
||||||
@ -62,14 +64,9 @@ STATIC uint8_t _get_wakeup_cause(void) {
|
|||||||
if (alarm_time_timealarm_woke_us_up()) {
|
if (alarm_time_timealarm_woke_us_up()) {
|
||||||
return STM_WAKEUP_RTC;
|
return STM_WAKEUP_RTC;
|
||||||
}
|
}
|
||||||
if (RTC->BKP0R & 0x01) {
|
// Check to see if we woke from deep sleep (reason set in port_init)
|
||||||
// We've woken from deep sleep. Was it the WKUP pin or the RTC?
|
if (true_deep_wake_reason) {
|
||||||
if (RTC->ISR & RTC_FLAG_ALRBF) {
|
return true_deep_wake_reason;
|
||||||
// Alarm B is the deep sleep alarm
|
|
||||||
return STM_WAKEUP_RTC;
|
|
||||||
} else {
|
|
||||||
return STM_WAKEUP_GPIO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return STM_WAKEUP_UNDEF;
|
return STM_WAKEUP_UNDEF;
|
||||||
}
|
}
|
||||||
@ -160,6 +157,19 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
|
|||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void common_hal_alarm_pretending_deep_sleep(void) {
|
||||||
|
// Re-enable the WKUP pin (PA00) since VM cleanup resets it
|
||||||
|
// If there are no PinAlarms, EXTI won't be turned on, and this won't do anything
|
||||||
|
// TODO: replace with `prepare_for_fake_deep_sleep` if other WKUP are added.
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
|
GPIO_InitStruct.Pin = pin_mask(0);
|
||||||
|
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
|
||||||
|
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
|
||||||
|
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
port_idle_until_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
void common_hal_alarm_gc_collect(void) {
|
void common_hal_alarm_gc_collect(void) {
|
||||||
gc_collect_ptr(shared_alarm_get_wake_alarm());
|
gc_collect_ptr(shared_alarm_get_wake_alarm());
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,13 @@
|
|||||||
|
|
||||||
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
|
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
|
||||||
|
|
||||||
|
#define STM_WAKEUP_UNDEF 0
|
||||||
|
#define STM_WAKEUP_GPIO 1
|
||||||
|
#define STM_WAKEUP_RTC 2
|
||||||
|
|
||||||
|
#define STM_ALARM_FLAG RTC->BKP0R
|
||||||
|
|
||||||
|
extern void alarm_set_wakeup_reason(uint8_t reason);
|
||||||
extern void alarm_reset(void);
|
extern void alarm_reset(void);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H
|
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H
|
||||||
|
@ -36,6 +36,7 @@ STATIC bool woke_up;
|
|||||||
|
|
||||||
STATIC uint16_t alarm_pin_triggered;
|
STATIC uint16_t alarm_pin_triggered;
|
||||||
STATIC bool deep_wkup_enabled;
|
STATIC bool deep_wkup_enabled;
|
||||||
|
STATIC bool reserved_alarms[STM32_GPIO_PORT_SIZE];
|
||||||
|
|
||||||
STATIC void pin_alarm_callback(uint8_t num) {
|
STATIC void pin_alarm_callback(uint8_t num) {
|
||||||
alarm_pin_triggered |= (1 << num);
|
alarm_pin_triggered |= (1 << num);
|
||||||
@ -50,7 +51,6 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, con
|
|||||||
if (!stm_peripherals_exti_is_free(pin->number)) {
|
if (!stm_peripherals_exti_is_free(pin->number)) {
|
||||||
mp_raise_RuntimeError(translate("Pin interrupt already in use"));
|
mp_raise_RuntimeError(translate("Pin interrupt already in use"));
|
||||||
}
|
}
|
||||||
stm_peripherals_exti_reserve(pin->number);
|
|
||||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||||
GPIO_InitStruct.Pin = pin_mask(pin->number);
|
GPIO_InitStruct.Pin = pin_mask(pin->number);
|
||||||
GPIO_InitStruct.Mode = value ? GPIO_MODE_IT_RISING : GPIO_MODE_IT_FALLING;
|
GPIO_InitStruct.Mode = value ? GPIO_MODE_IT_RISING : GPIO_MODE_IT_FALLING;
|
||||||
@ -63,8 +63,7 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, con
|
|||||||
}
|
}
|
||||||
HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct);
|
HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct);
|
||||||
|
|
||||||
stm_peripherals_exti_set_callback(pin_alarm_callback,pin->number);
|
// EXTI is set up and enabled in set_alarm
|
||||||
|
|
||||||
self->pin = pin;
|
self->pin = pin;
|
||||||
self->value = value;
|
self->value = value;
|
||||||
self->pull = pull;
|
self->pull = pull;
|
||||||
@ -101,10 +100,11 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder for deep sleep
|
// If the above isn't true, we woke from deep sleep, so create a new alarm
|
||||||
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
|
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
|
||||||
alarm->base.type = &alarm_pin_pinalarm_type;
|
alarm->base.type = &alarm_pin_pinalarm_type;
|
||||||
alarm->pin = NULL;
|
// TODO: replace this if/when other WKUP pins are supported
|
||||||
|
alarm->pin = &pin_PA00;
|
||||||
return alarm;
|
return alarm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,6 +113,12 @@ void alarm_pin_pinalarm_reset(void) {
|
|||||||
alarm_pin_triggered = 0;
|
alarm_pin_triggered = 0;
|
||||||
woke_up = false;
|
woke_up = false;
|
||||||
deep_wkup_enabled = false;
|
deep_wkup_enabled = false;
|
||||||
|
for (uint8_t i = 0; i < STM32_GPIO_PORT_SIZE; i++) {
|
||||||
|
if (reserved_alarms[i]) {
|
||||||
|
stm_peripherals_exti_reset_exti(i);
|
||||||
|
reserved_alarms[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deep sleep alarms don't actually make use of EXTI, but we pretend they're the same.
|
// Deep sleep alarms don't actually make use of EXTI, but we pretend they're the same.
|
||||||
@ -124,14 +130,24 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob
|
|||||||
// Deep sleep only wakes on a rising edge from one pin, WKUP (PA00)
|
// Deep sleep only wakes on a rising edge from one pin, WKUP (PA00)
|
||||||
// All pin settings are handled automatically.
|
// All pin settings are handled automatically.
|
||||||
if (alarm->pin != &pin_PA00) {
|
if (alarm->pin != &pin_PA00) {
|
||||||
mp_raise_ValueError(translate("Only the WKUP pin can be used to wake from Deep Sleep"));
|
mp_raise_ValueError(translate("Pin cannot wake from Deep Sleep"));
|
||||||
|
}
|
||||||
|
if (alarm->value == false || alarm->pull == false) {
|
||||||
|
// Enabling WakeUp automatically sets this, but warn anyway to set expectations
|
||||||
|
mp_raise_ValueError(translate("Deep sleep pins must use a rising edge with pulldown"));
|
||||||
}
|
}
|
||||||
// We can't actually turn WakeUp on here, since enabling it disables EXTI,
|
// We can't actually turn WakeUp on here, since enabling it disables EXTI,
|
||||||
// so we put it off until right before sleeping.
|
// so we put it off until right before sleeping.
|
||||||
deep_wkup_enabled = true;
|
deep_wkup_enabled = true;
|
||||||
|
// EXTI needs to persist past the VM cleanup for fake deep sleep
|
||||||
|
stm_peripherals_exti_never_reset(alarm->pin->number);
|
||||||
}
|
}
|
||||||
|
if (!stm_peripherals_exti_reserve(alarm->pin->number)) {
|
||||||
|
mp_raise_RuntimeError(translate("Pin interrupt already in use"));
|
||||||
|
}
|
||||||
|
stm_peripherals_exti_set_callback(pin_alarm_callback,alarm->pin->number);
|
||||||
stm_peripherals_exti_enable(alarm->pin->number);
|
stm_peripherals_exti_enable(alarm->pin->number);
|
||||||
|
reserved_alarms[alarm->pin->number] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,16 +33,30 @@
|
|||||||
#include "peripherals/exti.h"
|
#include "peripherals/exti.h"
|
||||||
|
|
||||||
STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE];
|
STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE];
|
||||||
|
STATIC bool stm_exti_never_reset[STM32_GPIO_PORT_SIZE];
|
||||||
STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num);
|
STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num);
|
||||||
|
|
||||||
void exti_reset(void) {
|
void exti_reset(void) {
|
||||||
for (size_t i = 0;i < STM32_GPIO_PORT_SIZE; i++) {
|
for (size_t i = 0;i < STM32_GPIO_PORT_SIZE; i++) {
|
||||||
stm_exti_reserved[i] = false;
|
if (!stm_exti_never_reset[i]) {
|
||||||
stm_exti_callback[i] = NULL;
|
stm_exti_reserved[i] = false;
|
||||||
stm_peripherals_exti_disable(i);
|
stm_exti_callback[i] = NULL;
|
||||||
|
stm_peripherals_exti_disable(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stm_peripherals_exti_never_reset(uint8_t num) {
|
||||||
|
stm_exti_never_reset[num] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stm_peripherals_exti_reset_exti(uint8_t num) {
|
||||||
|
stm_peripherals_exti_disable(num);
|
||||||
|
stm_exti_never_reset[num] = false;
|
||||||
|
stm_exti_reserved[num] = false;
|
||||||
|
stm_exti_callback[num] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool stm_peripherals_exti_is_free(uint8_t num) {
|
bool stm_peripherals_exti_is_free(uint8_t num) {
|
||||||
return !stm_exti_reserved[num];
|
return !stm_exti_reserved[num];
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#define STM32_GPIO_PORT_SIZE 16
|
#define STM32_GPIO_PORT_SIZE 16
|
||||||
|
|
||||||
void exti_reset(void);
|
void exti_reset(void);
|
||||||
|
void stm_peripherals_exti_never_reset(uint8_t num);
|
||||||
|
void stm_peripherals_exti_reset_exti(uint8_t num);
|
||||||
bool stm_peripherals_exti_is_free(uint8_t num);
|
bool stm_peripherals_exti_is_free(uint8_t num);
|
||||||
bool stm_peripherals_exti_reserve(uint8_t num);
|
bool stm_peripherals_exti_reserve(uint8_t num);
|
||||||
void stm_peripherals_exti_enable(uint8_t num);
|
void stm_peripherals_exti_enable(uint8_t num);
|
||||||
|
@ -154,7 +154,7 @@ void stm32_peripherals_rtc_disable_wakeup_timer(void) {
|
|||||||
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
|
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stm32_peripherals_reset_alarms(void) {
|
void stm32_peripherals_rtc_reset_alarms(void) {
|
||||||
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
|
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
|
||||||
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_B);
|
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_B);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ void stm32_peripherals_rtc_set_wakeup_mode_tick(void);
|
|||||||
void stm32_peripherals_rtc_enable_wakeup_timer(void);
|
void stm32_peripherals_rtc_enable_wakeup_timer(void);
|
||||||
void stm32_peripherals_rtc_disable_wakeup_timer(void);
|
void stm32_peripherals_rtc_disable_wakeup_timer(void);
|
||||||
|
|
||||||
void stm32_peripherals_reset_alarms(void);
|
void stm32_peripherals_rtc_reset_alarms(void);
|
||||||
void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) ;
|
void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) ;
|
||||||
void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks);
|
void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks);
|
||||||
bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx);
|
bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx);
|
||||||
|
@ -53,6 +53,9 @@
|
|||||||
#if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM
|
#if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM
|
||||||
#include "peripherals/exti.h"
|
#include "peripherals/exti.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if CIRCUITPY_ALARM
|
||||||
|
#include "common-hal/alarm/__init__.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "peripherals/clocks.h"
|
#include "peripherals/clocks.h"
|
||||||
#include "peripherals/gpio.h"
|
#include "peripherals/gpio.h"
|
||||||
@ -170,8 +173,18 @@ safe_mode_t port_init(void) {
|
|||||||
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
__HAL_RCC_SYSCFG_CLK_ENABLE();
|
||||||
|
|
||||||
__HAL_RCC_PWR_CLK_ENABLE();
|
__HAL_RCC_PWR_CLK_ENABLE();
|
||||||
|
|
||||||
HAL_PWR_EnableBkUpAccess();
|
HAL_PWR_EnableBkUpAccess();
|
||||||
|
|
||||||
|
// TODO: don't reset RTC entirely and move this back to alarm
|
||||||
|
if (STM_ALARM_FLAG & 0x01) {
|
||||||
|
// We've woken from deep sleep. Was it the WKUP pin or the RTC?
|
||||||
|
if (RTC->ISR & RTC_FLAG_ALRBF) {
|
||||||
|
// Alarm B is the deep sleep alarm
|
||||||
|
alarm_set_wakeup_reason(STM_WAKEUP_RTC);
|
||||||
|
} else {
|
||||||
|
alarm_set_wakeup_reason(STM_WAKEUP_GPIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
__HAL_RCC_BACKUPRESET_FORCE();
|
__HAL_RCC_BACKUPRESET_FORCE();
|
||||||
__HAL_RCC_BACKUPRESET_RELEASE();
|
__HAL_RCC_BACKUPRESET_RELEASE();
|
||||||
|
|
||||||
@ -180,7 +193,7 @@ safe_mode_t port_init(void) {
|
|||||||
stm32_peripherals_rtc_init();
|
stm32_peripherals_rtc_init();
|
||||||
|
|
||||||
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
|
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
|
||||||
stm32_peripherals_reset_alarms();
|
stm32_peripherals_rtc_reset_alarms();
|
||||||
|
|
||||||
// Turn off SysTick
|
// Turn off SysTick
|
||||||
SysTick->CTRL = 0;
|
SysTick->CTRL = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user