Skip to content

Commit 952812c

Browse files
authored
Merge pull request #7154 from dhalbert/alarm-lifetime
Save wake alarm info in static storage, simplifying recording of alarm
2 parents 11a9f8d + ded134c commit 952812c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+240
-197
lines changed

main.c

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static void reset_devices(void) {
132132
#endif
133133
}
134134

135-
STATIC void start_mp(supervisor_allocation *heap, bool first_run) {
135+
STATIC void start_mp(supervisor_allocation *heap) {
136136
supervisor_workflow_reset();
137137

138138
// Stack limit should be less than real stack size, so we have a chance
@@ -176,14 +176,6 @@ STATIC void start_mp(supervisor_allocation *heap, bool first_run) {
176176
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
177177

178178
mp_obj_list_init((mp_obj_list_t *)mp_sys_argv, 0);
179-
180-
#if CIRCUITPY_ALARM
181-
// Record which alarm woke us up, if any. An object may be created so the heap must be functional.
182-
// There is no alarm if this is not the first time code.py or the REPL has been run.
183-
shared_alarm_save_wake_alarm(first_run ? common_hal_alarm_create_wake_alarm() : mp_const_none);
184-
// Reset alarm module only after we retrieved the wakeup alarm.
185-
alarm_reset();
186-
#endif
187179
}
188180

189181
STATIC void stop_mp(void) {
@@ -373,7 +365,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
373365
}
374366
}
375367

376-
STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_reset) {
368+
STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
377369
bool serial_connected_at_start = serial_connected();
378370
bool printed_safe_mode_message = false;
379371
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
@@ -409,8 +401,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re
409401

410402
supervisor_allocation *heap = allocate_remaining_memory();
411403

412-
// Prepare the VM state. Includes an alarm check/reset for sleep.
413-
start_mp(heap, first_run);
404+
// Prepare the VM state.
405+
start_mp(heap);
414406

415407
#if CIRCUITPY_USB
416408
usb_setup_with_vm();
@@ -755,8 +747,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
755747

756748
supervisor_allocation *heap = allocate_remaining_memory();
757749

758-
// true means this is the first set of VM's after a hard reset.
759-
start_mp(heap, true);
750+
start_mp(heap);
760751

761752
#if CIRCUITPY_USB
762753
// Set up default USB values after boot.py VM starts but before running boot.py.
@@ -853,12 +844,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
853844
#endif
854845
}
855846

856-
STATIC int run_repl(bool first_run) {
847+
STATIC int run_repl(void) {
857848
int exit_code = PYEXEC_FORCED_EXIT;
858849
stack_resize();
859850
filesystem_flush();
860851
supervisor_allocation *heap = allocate_remaining_memory();
861-
start_mp(heap, first_run);
852+
start_mp(heap);
862853

863854
#if CIRCUITPY_USB
864855
usb_setup_with_vm();
@@ -968,6 +959,15 @@ int __attribute__((used)) main(void) {
968959
safe_mode = NO_CIRCUITPY;
969960
}
970961

962+
#if CIRCUITPY_ALARM
963+
// Record which alarm woke us up, if any.
964+
// common_hal_alarm_record_wake_alarm() should return a static, non-heap object
965+
shared_alarm_save_wake_alarm(common_hal_alarm_record_wake_alarm());
966+
// Then reset the alarm system. It's not reset in reset_port(), because that's also called
967+
// on VM teardown, which would clear any alarm setup.
968+
alarm_reset();
969+
#endif
970+
971971
// Reset everything and prep MicroPython to run boot.py.
972972
reset_port();
973973
// Port-independent devices, like CIRCUITPY_BLEIO_HCI.
@@ -1001,31 +1001,32 @@ int __attribute__((used)) main(void) {
10011001
// Boot script is finished, so now go into REPL or run code.py.
10021002
int exit_code = PYEXEC_FORCED_EXIT;
10031003
bool skip_repl = true;
1004-
bool first_run = true;
1005-
bool simulate_reset;
1004+
bool simulate_reset = true;
10061005
for (;;) {
1007-
simulate_reset = false;
10081006
if (!skip_repl) {
1009-
exit_code = run_repl(first_run);
1007+
exit_code = run_repl();
10101008
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
10111009
}
10121010
if (exit_code == PYEXEC_FORCED_EXIT) {
1013-
if (!first_run) {
1011+
if (!simulate_reset) {
10141012
serial_write_compressed(translate("soft reboot\n"));
10151013
}
10161014
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
1017-
skip_repl = run_code_py(safe_mode, first_run, &simulate_reset);
1015+
// If code.py did a fake deep sleep, pretend that we
1016+
// are running code.py for the first time after a hard
1017+
// reset. This will preserve any alarm information.
1018+
skip_repl = run_code_py(safe_mode, &simulate_reset);
10181019
} else {
10191020
skip_repl = false;
10201021
}
10211022
} else if (exit_code != 0) {
10221023
break;
10231024
}
10241025

1025-
// Either the REPL or code.py has run and finished.
1026-
// If code.py did a fake deep sleep, pretend that we are running code.py for
1027-
// the first time after a hard reset. This will preserve any alarm information.
1028-
first_run = simulate_reset;
1026+
#if CIRCUITPY_ALARM
1027+
shared_alarm_save_wake_alarm(simulate_reset ? common_hal_alarm_record_wake_alarm() : mp_const_none);
1028+
alarm_reset();
1029+
#endif
10291030
}
10301031
mp_deinit();
10311032
return 0;

ports/atmel-samd/common-hal/alarm/SleepMemory.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
28-
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
27+
#pragma once
2928

3029
#include "py/obj.h"
3130

@@ -34,5 +33,3 @@ typedef struct {
3433
} alarm_sleep_memory_obj_t;
3534

3635
extern void alarm_sleep_memory_reset(void);
37-
38-
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H

ports/atmel-samd/common-hal/alarm/__init__.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
4848
},
4949
};
5050

51+
// Non-heap alarm object recording alarm (if any) that woke up CircuitPython after light or deep sleep.
52+
// This object lives across VM instantiations, so none of these objects can contain references to the heap.
53+
alarm_wake_alarm_union_t alarm_wake_alarm;
54+
5155
void alarm_reset(void) {
5256
// Reset the alarm flag
5357
alarm_pin_pinalarm_reset();
@@ -57,7 +61,7 @@ void alarm_reset(void) {
5761
void alarm_get_wakeup_cause(void) {
5862
// Called from rtc_init, just before SWRST of RTC. It is called
5963
// at an early stage of main(), to save TAMPID from SWRST. Later,
60-
// common_hal_alarm_create_wake_alarm is called to make a wakeup
64+
// common_hal_alarm_record_wake_alarm is called to make a wakeup
6165
// alarm from the deep sleep.
6266

6367
TAMPID = RTC->MODE0.TAMPID.reg;
@@ -67,7 +71,7 @@ bool common_hal_alarm_woken_from_sleep(void) {
6771
return alarm_pin_pinalarm_woke_this_cycle() || alarm_time_timealarm_woke_this_cycle();
6872
}
6973

70-
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
74+
mp_obj_t common_hal_alarm_record_wake_alarm(void) {
7175
// Called from main.c on the first start up, just before alarm_reset.
7276
// Return a copy of wakeup alarm from deep sleep / fake deep sleep.
7377
// In case of fake sleep, status should be left in TimeAlarm/PinAlarm.
@@ -76,13 +80,13 @@ mp_obj_t common_hal_alarm_create_wake_alarm(void) {
7680
if (alarm_pin_pinalarm_woke_this_cycle()) {
7781
TAMPID = RTC->MODE0.TAMPID.reg;
7882
RTC->MODE0.TAMPID.reg = TAMPID; // clear register
79-
return alarm_pin_pinalarm_create_wakeup_alarm(TAMPID);
83+
return alarm_pin_pinalarm_record_wake_alarm(TAMPID);
8084
}
8185
if (alarm_time_timealarm_woke_this_cycle() || (true_deep && TAMPID == 0)) {
82-
return alarm_time_timealarm_create_wakeup_alarm();
86+
return alarm_time_timealarm_record_wake_alarm();
8387
}
8488
if (true_deep) {
85-
return alarm_pin_pinalarm_create_wakeup_alarm(TAMPID);
89+
return alarm_pin_pinalarm_record_wake_alarm(TAMPID);
8690
}
8791
return mp_const_none;
8892
}

ports/atmel-samd/common-hal/alarm/__init__.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
28-
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
27+
#pragma once
2928

3029
#include "common-hal/alarm/SleepMemory.h"
30+
#include "common-hal/alarm/pin/PinAlarm.h"
31+
#include "common-hal/alarm/time/TimeAlarm.h"
3132

3233
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
3334

@@ -53,8 +54,13 @@ typedef enum {
5354
SAMD_WAKEUP_RTC
5455
} samd_sleep_source_t;
5556

57+
typedef union {
58+
alarm_pin_pinalarm_obj_t pin_alarm;
59+
alarm_time_timealarm_obj_t time_alarm;
60+
} alarm_wake_alarm_union_t;
61+
62+
extern alarm_wake_alarm_union_t alarm_wake_alarm;
63+
5664
extern void alarm_set_wakeup_reason(samd_sleep_source_t reason);
57-
void alarm_get_wakeup_cause(void);
65+
extern void alarm_get_wakeup_cause(void);
5866
extern void alarm_reset(void);
59-
60-
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H

ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
#include "hal/include/hal_gpio.h"
3232
// #include <stdio.h>
3333

34+
#include "shared-bindings/alarm/__init__.h"
3435
#include "shared-bindings/alarm/pin/PinAlarm.h"
3536
#include "shared-bindings/microcontroller/__init__.h"
36-
#include "shared-bindings/microcontroller/Pin.h"
3737
#include "common-hal/alarm/__init__.h"
3838

3939
// This variable stores whether a PinAlarm woke in light sleep or fake deep sleep
@@ -128,12 +128,11 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t
128128
return mp_const_none;
129129
}
130130

131-
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(uint32_t TAMPID) {
132-
// Create tamper alarm that caused wakeup from deep sleep
131+
mp_obj_t alarm_pin_pinalarm_record_wake_alarm(uint32_t TAMPID) {
132+
alarm_pin_pinalarm_obj_t *const alarm = &alarm_wake_alarm.pin_alarm;
133133

134134
for (samd_tamper_pin_t *t = TAMPER_PINS; t->n >= 0; t++) {
135135
if (TAMPID & (1 << t->n)) {
136-
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
137136
alarm->base.type = &alarm_pin_pinalarm_type;
138137
alarm->pin = t->pin;
139138
return alarm;

ports/atmel-samd/common-hal/alarm/pin/PinAlarm.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
28-
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
27+
#pragma once
2928

3029
#include "py/obj.h"
3130
#include "py/objtuple.h"
3231

32+
#include "shared-bindings/microcontroller/Pin.h"
33+
3334
typedef struct {
3435
mp_obj_base_t base;
3536
const mcu_pin_obj_t *pin;
@@ -39,13 +40,11 @@ typedef struct {
3940
} alarm_pin_pinalarm_obj_t;
4041

4142
mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
42-
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(uint32_t TAMPID);
43+
mp_obj_t alarm_pin_pinalarm_record_wake_alarm(uint32_t TAMPID);
4344

4445
void pin_alarm_callback(uint8_t num);
4546
void alarm_pin_pinalarm_reset(void);
4647
void alarm_pin_pinalarm_deinit_alarms(size_t n_alarms, const mp_obj_t *alarms);
4748
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
4849
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
4950
bool alarm_pin_pinalarm_woke_this_cycle(void);
50-
51-
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H

ports/atmel-samd/common-hal/alarm/time/TimeAlarm.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
#include "py/runtime.h"
2828
#include "hpl/pm/hpl_pm_base.h"
2929

30+
#include "shared-bindings/alarm/__init__.h"
3031
#include "shared-bindings/alarm/time/TimeAlarm.h"
3132
#include "shared-bindings/time/__init__.h"
32-
#include "common-hal/alarm/__init__.h"
3333
#include "supervisor/port.h"
3434

3535
STATIC volatile bool woke_up = false;
@@ -58,13 +58,14 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
5858
return mp_const_none;
5959
}
6060

61-
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) {
62-
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
63-
timer->base.type = &alarm_time_timealarm_type;
61+
mp_obj_t alarm_time_timealarm_record_wake_alarm(void) {
62+
alarm_time_timealarm_obj_t *const alarm = &alarm_wake_alarm.time_alarm;
63+
64+
alarm->base.type = &alarm_time_timealarm_type;
6465
// TODO: Set monotonic_time based on the RTC state.
6566
// Or don't, most of the other ports don't have this either.
66-
timer->monotonic_time = 0.0f;
67-
return timer;
67+
alarm->monotonic_time = 0.0f;
68+
return alarm;
6869
}
6970

7071
void time_alarm_callback(void) {

ports/atmel-samd/common-hal/alarm/time/TimeAlarm.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
28-
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
27+
#pragma once
2928

3029
#include "py/obj.h"
3130

@@ -35,12 +34,10 @@ typedef struct {
3534
} alarm_time_timealarm_obj_t;
3635

3736
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
38-
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void);
37+
mp_obj_t alarm_time_timealarm_record_wake_alarm(void);
3938
void time_alarm_callback(void);
4039
bool alarm_time_timealarm_woke_this_cycle(void);
4140
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
4241
void alarm_time_timealarm_reset(void);
4342

4443
void alarm_time_timealarm_prepare_for_deep_sleep(void);
45-
46-
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H

ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,9 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
28-
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
27+
#pragma once
2928

3029
typedef struct {
3130
mp_obj_base_t base;
3231
const mcu_pin_obj_t *pin;
3332
} alarm_touch_touchalarm_obj_t;
34-
35-
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H

ports/espressif/common-hal/alarm/SleepMemory.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H
28-
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H
27+
#pragma once
2928

3029
#include "py/obj.h"
3130

@@ -49,5 +48,3 @@ typedef struct {
4948
} alarm_sleep_memory_obj_t;
5049

5150
extern void alarm_sleep_memory_reset(void);
52-
53-
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H

0 commit comments

Comments
 (0)