Skip to content

Commit 66a1583

Browse files
committed
Implement fake and true deep sleep alarm differentiation
1 parent 17585e1 commit 66a1583

File tree

8 files changed

+89
-27
lines changed

8 files changed

+89
-27
lines changed

ports/stm/common-hal/alarm/__init__.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,7 @@
3939
#include "supervisor/port.h"
4040
#include "supervisor/shared/workflow.h"
4141

42-
#define STM_WAKEUP_UNDEF 0
43-
#define STM_WAKEUP_GPIO 1
44-
#define STM_WAKEUP_RTC 2
45-
46-
#define STM_ALARM_FLAG RTC->BKP0R
42+
STATIC uint8_t true_deep_wake_reason;
4743

4844
void alarm_reset(void) {
4945
// Reset the alarm flag
@@ -54,6 +50,12 @@ void alarm_reset(void) {
5450
// esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
5551
}
5652

53+
// Kind of a hack, required as RTC is reset in port.c
54+
// TODO: in the future, don't reset it at all, just override critical flags
55+
void alarm_set_wakeup_reason(uint8_t reason) {
56+
true_deep_wake_reason = reason;
57+
}
58+
5759
STATIC uint8_t _get_wakeup_cause(void) {
5860
// If in light/fake sleep, check modules
5961
if (alarm_pin_pinalarm_woke_us_up()) {
@@ -62,14 +64,9 @@ STATIC uint8_t _get_wakeup_cause(void) {
6264
if (alarm_time_timealarm_woke_us_up()) {
6365
return STM_WAKEUP_RTC;
6466
}
65-
if (RTC->BKP0R & 0x01) {
66-
// We've woken from deep sleep. Was it the WKUP pin or the RTC?
67-
if (RTC->ISR & RTC_FLAG_ALRBF) {
68-
// Alarm B is the deep sleep alarm
69-
return STM_WAKEUP_RTC;
70-
} else {
71-
return STM_WAKEUP_GPIO;
72-
}
67+
// Check to see if we woke from deep sleep (reason set in port_init)
68+
if (true_deep_wake_reason) {
69+
return true_deep_wake_reason;
7370
}
7471
return STM_WAKEUP_UNDEF;
7572
}
@@ -160,6 +157,19 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) {
160157
while(1);
161158
}
162159

160+
void common_hal_alarm_pretending_deep_sleep(void) {
161+
// Re-enable the WKUP pin (PA00) since VM cleanup resets it
162+
// If there are no PinAlarms, EXTI won't be turned on, and this won't do anything
163+
// TODO: replace with `prepare_for_fake_deep_sleep` if other WKUP are added.
164+
GPIO_InitTypeDef GPIO_InitStruct = {0};
165+
GPIO_InitStruct.Pin = pin_mask(0);
166+
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
167+
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
168+
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
169+
170+
port_idle_until_interrupt();
171+
}
172+
163173
void common_hal_alarm_gc_collect(void) {
164174
gc_collect_ptr(shared_alarm_get_wake_alarm());
165175
}

ports/stm/common-hal/alarm/__init__.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131

3232
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
3333

34+
#define STM_WAKEUP_UNDEF 0
35+
#define STM_WAKEUP_GPIO 1
36+
#define STM_WAKEUP_RTC 2
37+
38+
#define STM_ALARM_FLAG RTC->BKP0R
39+
40+
extern void alarm_set_wakeup_reason(uint8_t reason);
3441
extern void alarm_reset(void);
3542

3643
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H

ports/stm/common-hal/alarm/pin/PinAlarm.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ STATIC bool woke_up;
3636

3737
STATIC uint16_t alarm_pin_triggered;
3838
STATIC bool deep_wkup_enabled;
39+
STATIC bool reserved_alarms[STM32_GPIO_PORT_SIZE];
3940

4041
STATIC void pin_alarm_callback(uint8_t num) {
4142
alarm_pin_triggered |= (1 << num);
@@ -50,7 +51,6 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, con
5051
if (!stm_peripherals_exti_is_free(pin->number)) {
5152
mp_raise_RuntimeError(translate("Pin interrupt already in use"));
5253
}
53-
stm_peripherals_exti_reserve(pin->number);
5454
GPIO_InitTypeDef GPIO_InitStruct = {0};
5555
GPIO_InitStruct.Pin = pin_mask(pin->number);
5656
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
6363
}
6464
HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct);
6565

66-
stm_peripherals_exti_set_callback(pin_alarm_callback,pin->number);
67-
66+
// EXTI is set up and enabled in set_alarm
6867
self->pin = pin;
6968
self->value = value;
7069
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
101100
}
102101
}
103102

104-
// Placeholder for deep sleep
103+
// If the above isn't true, we woke from deep sleep, so create a new alarm
105104
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
106105
alarm->base.type = &alarm_pin_pinalarm_type;
107-
alarm->pin = NULL;
106+
// TODO: replace this if/when other WKUP pins are supported
107+
alarm->pin = &pin_PA00;
108108
return alarm;
109109
}
110110

@@ -113,6 +113,12 @@ void alarm_pin_pinalarm_reset(void) {
113113
alarm_pin_triggered = 0;
114114
woke_up = false;
115115
deep_wkup_enabled = false;
116+
for (uint8_t i = 0; i < STM32_GPIO_PORT_SIZE; i++) {
117+
if (reserved_alarms[i]) {
118+
stm_peripherals_exti_reset_exti(i);
119+
reserved_alarms[i] = false;
120+
}
121+
}
116122
}
117123

118124
// 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
124130
// Deep sleep only wakes on a rising edge from one pin, WKUP (PA00)
125131
// All pin settings are handled automatically.
126132
if (alarm->pin != &pin_PA00) {
127-
mp_raise_ValueError(translate("Only the WKUP pin can be used to wake from Deep Sleep"));
133+
mp_raise_ValueError(translate("Pin cannot wake from Deep Sleep"));
134+
}
135+
if (alarm->value == false || alarm->pull == false) {
136+
// Enabling WakeUp automatically sets this, but warn anyway to set expectations
137+
mp_raise_ValueError(translate("Deep sleep pins must use a rising edge with pulldown"));
128138
}
129139
// We can't actually turn WakeUp on here, since enabling it disables EXTI,
130140
// so we put it off until right before sleeping.
131141
deep_wkup_enabled = true;
142+
// EXTI needs to persist past the VM cleanup for fake deep sleep
143+
stm_peripherals_exti_never_reset(alarm->pin->number);
132144
}
133-
145+
if (!stm_peripherals_exti_reserve(alarm->pin->number)) {
146+
mp_raise_RuntimeError(translate("Pin interrupt already in use"));
147+
}
148+
stm_peripherals_exti_set_callback(pin_alarm_callback,alarm->pin->number);
134149
stm_peripherals_exti_enable(alarm->pin->number);
150+
reserved_alarms[alarm->pin->number] = true;
135151
}
136152
}
137153
}

ports/stm/peripherals/exti.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,30 @@
3333
#include "peripherals/exti.h"
3434

3535
STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE];
36+
STATIC bool stm_exti_never_reset[STM32_GPIO_PORT_SIZE];
3637
STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num);
3738

3839
void exti_reset(void) {
3940
for (size_t i = 0;i < STM32_GPIO_PORT_SIZE; i++) {
40-
stm_exti_reserved[i] = false;
41-
stm_exti_callback[i] = NULL;
42-
stm_peripherals_exti_disable(i);
41+
if (!stm_exti_never_reset[i]) {
42+
stm_exti_reserved[i] = false;
43+
stm_exti_callback[i] = NULL;
44+
stm_peripherals_exti_disable(i);
45+
}
4346
}
4447
}
4548

49+
void stm_peripherals_exti_never_reset(uint8_t num) {
50+
stm_exti_never_reset[num] = true;
51+
}
52+
53+
void stm_peripherals_exti_reset_exti(uint8_t num) {
54+
stm_peripherals_exti_disable(num);
55+
stm_exti_never_reset[num] = false;
56+
stm_exti_reserved[num] = false;
57+
stm_exti_callback[num] = NULL;
58+
}
59+
4660
bool stm_peripherals_exti_is_free(uint8_t num) {
4761
return !stm_exti_reserved[num];
4862
}

ports/stm/peripherals/exti.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#define STM32_GPIO_PORT_SIZE 16
3333

3434
void exti_reset(void);
35+
void stm_peripherals_exti_never_reset(uint8_t num);
36+
void stm_peripherals_exti_reset_exti(uint8_t num);
3537
bool stm_peripherals_exti_is_free(uint8_t num);
3638
bool stm_peripherals_exti_reserve(uint8_t num);
3739
void stm_peripherals_exti_enable(uint8_t num);

ports/stm/peripherals/rtc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ void stm32_peripherals_rtc_disable_wakeup_timer(void) {
154154
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
155155
}
156156

157-
void stm32_peripherals_reset_alarms(void) {
157+
void stm32_peripherals_rtc_reset_alarms(void) {
158158
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
159159
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_B);
160160
}

ports/stm/peripherals/rtc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void stm32_peripherals_rtc_set_wakeup_mode_tick(void);
4343
void stm32_peripherals_rtc_enable_wakeup_timer(void);
4444
void stm32_peripherals_rtc_disable_wakeup_timer(void);
4545

46-
void stm32_peripherals_reset_alarms(void);
46+
void stm32_peripherals_rtc_reset_alarms(void);
4747
void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) ;
4848
void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks);
4949
bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx);

ports/stm/supervisor/port.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
#if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM
5454
#include "peripherals/exti.h"
5555
#endif
56+
#if CIRCUITPY_ALARM
57+
#include "common-hal/alarm/__init__.h"
58+
#endif
5659

5760
#include "peripherals/clocks.h"
5861
#include "peripherals/gpio.h"
@@ -170,8 +173,18 @@ safe_mode_t port_init(void) {
170173
__HAL_RCC_SYSCFG_CLK_ENABLE();
171174

172175
__HAL_RCC_PWR_CLK_ENABLE();
173-
174176
HAL_PWR_EnableBkUpAccess();
177+
178+
// TODO: don't reset RTC entirely and move this back to alarm
179+
if (STM_ALARM_FLAG & 0x01) {
180+
// We've woken from deep sleep. Was it the WKUP pin or the RTC?
181+
if (RTC->ISR & RTC_FLAG_ALRBF) {
182+
// Alarm B is the deep sleep alarm
183+
alarm_set_wakeup_reason(STM_WAKEUP_RTC);
184+
} else {
185+
alarm_set_wakeup_reason(STM_WAKEUP_GPIO);
186+
}
187+
}
175188
__HAL_RCC_BACKUPRESET_FORCE();
176189
__HAL_RCC_BACKUPRESET_RELEASE();
177190

@@ -180,7 +193,7 @@ safe_mode_t port_init(void) {
180193
stm32_peripherals_rtc_init();
181194

182195
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
183-
stm32_peripherals_reset_alarms();
196+
stm32_peripherals_rtc_reset_alarms();
184197

185198
// Turn off SysTick
186199
SysTick->CTRL = 0;

0 commit comments

Comments
 (0)