Skip to content

Commit 6b2c998

Browse files
committed
Extract RTC, implement fake RTC deepsleep
1 parent f1792c8 commit 6b2c998

File tree

12 files changed

+338
-187
lines changed

12 files changed

+338
-187
lines changed

main.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ STATIC void start_mp(supervisor_allocation* heap) {
157157

158158
#if CIRCUITPY_ALARM
159159
// Record which alarm woke us up, if any. An object may be created so the heap must be functional.
160-
common_hal_alarm_save_wake_alarm();
160+
shared_alarm_save_wake_alarm();
161161
// Reset alarm module only after we retrieved the wakeup alarm.
162162
common_hal_alarm_reset();
163163
#endif
@@ -301,8 +301,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
301301
}
302302
#endif
303303

304-
// TODO: on deep sleep, make sure display is refreshed before sleeping (for e-ink).
305-
306304
cleanup_after_vm(heap);
307305

308306
if (result.return_code & PYEXEC_FORCED_EXIT) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ STATIC void _idle_until_alarm(void) {
126126
// Allow ctrl-C interrupt.
127127
if (common_hal_alarm_woken_from_sleep()) {
128128
// This saves the return of common_hal_alarm_get_wake_alarm through Shared Bindings
129-
common_hal_alarm_save_wake_alarm();
129+
shared_alarm_save_wake_alarm();
130130
return;
131131
}
132132
port_idle_until_interrupt();

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

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
void common_hal_alarm_reset(void) {
4646
// alarm_sleep_memory_reset();
4747
alarm_pin_pinalarm_reset();
48-
// alarm_time_timealarm_reset();
48+
alarm_time_timealarm_reset();
4949
// alarm_touch_touchalarm_reset();
5050
// esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
5151
}
@@ -101,7 +101,7 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) {
101101
// Set up light sleep or deep sleep alarms.
102102
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
103103
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
104-
// alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
104+
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
105105
// alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms);
106106
}
107107

@@ -111,23 +111,20 @@ STATIC void _idle_until_alarm(void) {
111111
RUN_BACKGROUND_TASKS;
112112
// Allow ctrl-C interrupt.
113113
if (common_hal_alarm_woken_from_sleep()) {
114-
common_hal_alarm_save_wake_alarm();
114+
shared_alarm_save_wake_alarm();
115115
return;
116116
}
117-
// port_idle_until_interrupt();
117+
port_idle_until_interrupt();
118118
}
119119
}
120120

121121
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
122-
// if (supervisor_workflow_active()) {
123-
// mp_raise_NotImplementedError(translate("Cannot sleep with USB connected"));
124-
// }
125-
_setup_sleep_alarms(false, n_alarms, alarms);
126-
127122
// If USB is active, only pretend to sleep. Otherwise, light sleep
128123
if (supervisor_workflow_active()) {
124+
_setup_sleep_alarms(false, n_alarms, alarms);
129125
_idle_until_alarm();
130126
} else {
127+
_setup_sleep_alarms(false, n_alarms, alarms);
131128
port_disable_tick();
132129
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
133130
port_enable_tick();
@@ -144,13 +141,17 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
144141

145142
//#define NORETURN __attribute__((noreturn))
146143
void NORETURN common_hal_alarm_enter_deep_sleep(void) {
147-
// alarm_pin_pinalarm_prepare_for_deep_sleep();
144+
alarm_pin_pinalarm_prepare_for_deep_sleep();
145+
//port_disable_tick();
148146
// alarm_touch_touchalarm_prepare_for_deep_sleep();
149-
while(1);
147+
// HAL_PWR_EnableBkUpAccess();
148+
// __HAL_RCC_BACKUPRESET_FORCE();
149+
// __HAL_RCC_BACKUPRESET_RELEASE();
150150

151-
// The ESP-IDF caches the deep sleep settings and applies them before sleep.
152-
// We don't need to worry about resetting them in the interim.
153-
// esp_deep_sleep_start();
151+
HAL_PWR_EnterSTANDBYMode();
152+
153+
// Should never hit this
154+
while(1);
154155
}
155156

156157
void common_hal_alarm_gc_collect(void) {

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
STATIC bool woke_up;
3636

3737
STATIC uint16_t alarm_pin_triggered;
38+
STATIC bool deep_wkup_enabled;
3839

3940
STATIC void pin_alarm_callback(uint8_t num) {
4041
alarm_pin_triggered |= (1 << num);
@@ -112,17 +113,32 @@ void alarm_pin_pinalarm_reset(void) {
112113
woke_up = false;
113114
}
114115

116+
// Deep sleep alarms don't actually make use of EXTI, but we pretend they're the same.
115117
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
116118
for (size_t i = 0; i < n_alarms; i++) {
117119
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) {
118120
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
119-
stm_peripherals_exti_enable(alarm->pin->number);
121+
122+
if (deep_sleep) {
123+
// Deep sleep only wakes on a rising edge from one pin, WKUP (PA00)
124+
if (alarm->pin != &pin_PA00) {
125+
mp_raise_ValueError(translate("Only the WKUP pin can be used to wake from Deep Sleep"));
126+
}
127+
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
128+
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
129+
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
130+
131+
deep_wkup_enabled = true;
132+
} else {
133+
stm_peripherals_exti_enable(alarm->pin->number);
134+
}
120135
}
121136
}
122137
}
123138

124139
void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
125140
alarm_pin_triggered = 0;
141+
deep_wkup_enabled = false;
126142
for (size_t i = 0; i < n_alarms; i++) {
127143
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) {
128144
alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]);
@@ -131,6 +147,10 @@ void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_
131147
}
132148
}
133149

150+
// If we don't have WKUP enabled, ensure it's disabled
151+
// TODO; is this really required?
134152
void alarm_pin_pinalarm_prepare_for_deep_sleep(void) {
135-
153+
if (!deep_wkup_enabled) {
154+
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
155+
}
136156
}

ports/stm/common-hal/alarm/time/TimeAlarm.c

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828

2929
#include "shared-bindings/alarm/time/TimeAlarm.h"
3030
#include "shared-bindings/time/__init__.h"
31+
#include "supervisor/port.h"
32+
#include "peripherals/rtc.h"
33+
34+
STATIC volatile bool woke_up;
3135

3236
void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) {
3337
self->monotonic_time = monotonic_time;
@@ -37,42 +41,59 @@ mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timeala
3741
return self->monotonic_time;
3842
}
3943

40-
// mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
41-
// // First, check to see if we match
42-
// for (size_t i = 0; i < n_alarms; i++) {
43-
// if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) {
44-
// return alarms[i];
45-
// }
46-
// }
47-
// alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
48-
// timer->base.type = &alarm_time_timealarm_type;
49-
// // TODO: Set monotonic_time based on the RTC state.
50-
// timer->monotonic_time = 0.0f;
51-
// return timer;
52-
// }
44+
mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
45+
// First, check to see if we match
46+
for (size_t i = 0; i < n_alarms; i++) {
47+
if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) {
48+
return alarms[i];
49+
}
50+
}
51+
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
52+
timer->base.type = &alarm_time_timealarm_type;
53+
// TODO: Set monotonic_time based on the RTC state.
54+
timer->monotonic_time = 0.0f;
55+
return timer;
56+
}
5357

5458
// This is run in the timer task. We use it to wake the main CircuitPython task.
55-
// void timer_callback(void *arg) {
56-
// (void) arg;
57-
// woke_up = true;
58-
// xTaskNotifyGive(circuitpython_task);
59-
// }
59+
STATIC void timer_callback(void) {
60+
woke_up = true;
61+
}
6062

6163
bool alarm_time_timealarm_woke_us_up(void) {
62-
// return woke_up;
63-
return false;
64+
//mp_printf(&mp_plat_print,"Woke Up:%d\n",woke_up);
65+
return woke_up;
6466
}
6567

66-
// void alarm_time_timealarm_reset(void) {
67-
// esp_timer_stop(pretend_sleep_timer);
68-
// esp_timer_delete(pretend_sleep_timer);
69-
// pretend_sleep_timer = NULL;
70-
// woke_up = false;
71-
// }
68+
void alarm_time_timealarm_reset(void) {
69+
// mp_printf(&mp_plat_print,"timealarm reset");
70+
woke_up = false;
71+
}
7272

7373
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
74-
// HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
75-
// HAL_RTCEx_SetWakeUpTimer_IT(&_hrtc, rtc_clock_frequency / 1024 / 2, RTC_WAKEUPCLOCK_RTCCLK_DIV2);
76-
// HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 1, 0U);
77-
// HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
74+
// Search through alarms for TimeAlarm instances, and check that there's only one
75+
bool timealarm_set = false;
76+
alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL;
77+
for (size_t i = 0; i < n_alarms; i++) {
78+
if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) {
79+
continue;
80+
}
81+
if (timealarm_set) {
82+
mp_raise_ValueError(translate("Only one alarm.time alarm can be set."));
83+
}
84+
timealarm = MP_OBJ_TO_PTR(alarms[i]);
85+
timealarm_set = true;
86+
}
87+
if (!timealarm_set) {
88+
return;
89+
}
90+
91+
// Compute how long to actually sleep, considering the time now.
92+
mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f;
93+
uint32_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs);
94+
uint32_t wakeup_in_ticks = wakeup_in_secs * 1024;
95+
96+
// Use alarm B, since port reserves A
97+
stm32_peripherals_rtc_assign_alarm_callback(PERIPHERALS_ALARM_B,timer_callback);
98+
stm32_peripherals_rtc_set_alarm(PERIPHERALS_ALARM_B,wakeup_in_ticks);
7899
}

ports/stm/common-hal/alarm/time/TimeAlarm.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ typedef struct {
3232
mp_float_t monotonic_time; // values compatible with time.monotonic_time()
3333
} alarm_time_timealarm_obj_t;
3434

35-
// // Find the alarm object that caused us to wake up or create an equivalent one.
36-
// mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
37-
// // Check for the wake up alarm from pretend deep sleep.
35+
// Find the alarm object that caused us to wake up or create an equivalent one.
36+
mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
37+
// Check for the wake up alarm from pretend deep sleep.
3838
bool alarm_time_timealarm_woke_us_up(void);
39-
// void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
40-
// void alarm_time_timealarm_reset(void);
39+
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
40+
void alarm_time_timealarm_reset(void);

ports/stm/peripherals/exti.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232

3333
#include "peripherals/exti.h"
3434

35-
3635
STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE];
3736
STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num);
3837

0 commit comments

Comments
 (0)