Skip to content

Save wake alarm info in static storage, simplifying recording of alarm #7154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 27 additions & 26 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ static void reset_devices(void) {
#endif
}

STATIC void start_mp(supervisor_allocation *heap, bool first_run) {
STATIC void start_mp(supervisor_allocation *heap) {
supervisor_workflow_reset();

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

mp_obj_list_init((mp_obj_list_t *)mp_sys_argv, 0);

#if CIRCUITPY_ALARM
// Record which alarm woke us up, if any. An object may be created so the heap must be functional.
// There is no alarm if this is not the first time code.py or the REPL has been run.
shared_alarm_save_wake_alarm(first_run ? common_hal_alarm_create_wake_alarm() : mp_const_none);
// Reset alarm module only after we retrieved the wakeup alarm.
alarm_reset();
#endif
}

STATIC void stop_mp(void) {
Expand Down Expand Up @@ -373,7 +365,7 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) {
}
}

STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_reset) {
STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) {
bool serial_connected_at_start = serial_connected();
bool printed_safe_mode_message = false;
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0
Expand Down Expand Up @@ -409,8 +401,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool first_run, bool *simulate_re

supervisor_allocation *heap = allocate_remaining_memory();

// Prepare the VM state. Includes an alarm check/reset for sleep.
start_mp(heap, first_run);
// Prepare the VM state.
start_mp(heap);

#if CIRCUITPY_USB
usb_setup_with_vm();
Expand Down Expand Up @@ -755,8 +747,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {

supervisor_allocation *heap = allocate_remaining_memory();

// true means this is the first set of VM's after a hard reset.
start_mp(heap, true);
start_mp(heap);

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

STATIC int run_repl(bool first_run) {
STATIC int run_repl(void) {
int exit_code = PYEXEC_FORCED_EXIT;
stack_resize();
filesystem_flush();
supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap, first_run);
start_mp(heap);

#if CIRCUITPY_USB
usb_setup_with_vm();
Expand Down Expand Up @@ -968,6 +959,15 @@ int __attribute__((used)) main(void) {
safe_mode = NO_CIRCUITPY;
}

#if CIRCUITPY_ALARM
// Record which alarm woke us up, if any.
// common_hal_alarm_record_wake_alarm() should return a static, non-heap object
shared_alarm_save_wake_alarm(common_hal_alarm_record_wake_alarm());
// Then reset the alarm system. It's not reset in reset_port(), because that's also called
// on VM teardown, which would clear any alarm setup.
alarm_reset();
#endif

// Reset everything and prep MicroPython to run boot.py.
reset_port();
// Port-independent devices, like CIRCUITPY_BLEIO_HCI.
Expand Down Expand Up @@ -1001,31 +1001,32 @@ int __attribute__((used)) main(void) {
// Boot script is finished, so now go into REPL or run code.py.
int exit_code = PYEXEC_FORCED_EXIT;
bool skip_repl = true;
bool first_run = true;
bool simulate_reset;
bool simulate_reset = true;
for (;;) {
simulate_reset = false;
if (!skip_repl) {
exit_code = run_repl(first_run);
exit_code = run_repl();
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
}
if (exit_code == PYEXEC_FORCED_EXIT) {
if (!first_run) {
if (!simulate_reset) {
serial_write_compressed(translate("soft reboot\n"));
}
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
skip_repl = run_code_py(safe_mode, first_run, &simulate_reset);
// If code.py did a fake deep sleep, pretend that we
// are running code.py for the first time after a hard
// reset. This will preserve any alarm information.
skip_repl = run_code_py(safe_mode, &simulate_reset);
} else {
skip_repl = false;
}
} else if (exit_code != 0) {
break;
}

// Either the REPL or code.py has run and finished.
// If code.py did a fake deep sleep, pretend that we are running code.py for
// the first time after a hard reset. This will preserve any alarm information.
first_run = simulate_reset;
#if CIRCUITPY_ALARM
shared_alarm_save_wake_alarm(simulate_reset ? common_hal_alarm_record_wake_alarm() : mp_const_none);
alarm_reset();
#endif
}
mp_deinit();
return 0;
Expand Down
5 changes: 1 addition & 4 deletions ports/atmel-samd/common-hal/alarm/SleepMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
#pragma once

#include "py/obj.h"

Expand All @@ -34,5 +33,3 @@ typedef struct {
} alarm_sleep_memory_obj_t;

extern void alarm_sleep_memory_reset(void);

#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
14 changes: 9 additions & 5 deletions ports/atmel-samd/common-hal/alarm/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
},
};

// Non-heap alarm object recording alarm (if any) that woke up CircuitPython after light or deep sleep.
// This object lives across VM instantiations, so none of these objects can contain references to the heap.
alarm_wake_alarm_union_t alarm_wake_alarm;

void alarm_reset(void) {
// Reset the alarm flag
alarm_pin_pinalarm_reset();
Expand All @@ -57,7 +61,7 @@ void alarm_reset(void) {
void alarm_get_wakeup_cause(void) {
// Called from rtc_init, just before SWRST of RTC. It is called
// at an early stage of main(), to save TAMPID from SWRST. Later,
// common_hal_alarm_create_wake_alarm is called to make a wakeup
// common_hal_alarm_record_wake_alarm is called to make a wakeup
// alarm from the deep sleep.

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

mp_obj_t common_hal_alarm_create_wake_alarm(void) {
mp_obj_t common_hal_alarm_record_wake_alarm(void) {
// Called from main.c on the first start up, just before alarm_reset.
// Return a copy of wakeup alarm from deep sleep / fake deep sleep.
// In case of fake sleep, status should be left in TimeAlarm/PinAlarm.
Expand All @@ -76,13 +80,13 @@ mp_obj_t common_hal_alarm_create_wake_alarm(void) {
if (alarm_pin_pinalarm_woke_this_cycle()) {
TAMPID = RTC->MODE0.TAMPID.reg;
RTC->MODE0.TAMPID.reg = TAMPID; // clear register
return alarm_pin_pinalarm_create_wakeup_alarm(TAMPID);
return alarm_pin_pinalarm_record_wake_alarm(TAMPID);
}
if (alarm_time_timealarm_woke_this_cycle() || (true_deep && TAMPID == 0)) {
return alarm_time_timealarm_create_wakeup_alarm();
return alarm_time_timealarm_record_wake_alarm();
}
if (true_deep) {
return alarm_pin_pinalarm_create_wakeup_alarm(TAMPID);
return alarm_pin_pinalarm_record_wake_alarm(TAMPID);
}
return mp_const_none;
}
Expand Down
16 changes: 11 additions & 5 deletions ports/atmel-samd/common-hal/alarm/__init__.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
#pragma once

#include "common-hal/alarm/SleepMemory.h"
#include "common-hal/alarm/pin/PinAlarm.h"
#include "common-hal/alarm/time/TimeAlarm.h"

extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;

Expand All @@ -53,8 +54,13 @@ typedef enum {
SAMD_WAKEUP_RTC
} samd_sleep_source_t;

typedef union {
alarm_pin_pinalarm_obj_t pin_alarm;
alarm_time_timealarm_obj_t time_alarm;
} alarm_wake_alarm_union_t;

extern alarm_wake_alarm_union_t alarm_wake_alarm;

extern void alarm_set_wakeup_reason(samd_sleep_source_t reason);
void alarm_get_wakeup_cause(void);
extern void alarm_get_wakeup_cause(void);
extern void alarm_reset(void);

#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
7 changes: 3 additions & 4 deletions ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
#include "hal/include/hal_gpio.h"
// #include <stdio.h>

#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "common-hal/alarm/__init__.h"

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

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

for (samd_tamper_pin_t *t = TAMPER_PINS; t->n >= 0; t++) {
if (TAMPID & (1 << t->n)) {
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t);
alarm->base.type = &alarm_pin_pinalarm_type;
alarm->pin = t->pin;
return alarm;
Expand Down
9 changes: 4 additions & 5 deletions ports/atmel-samd/common-hal/alarm/pin/PinAlarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
#pragma once

#include "py/obj.h"
#include "py/objtuple.h"

#include "shared-bindings/microcontroller/Pin.h"

typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
Expand All @@ -39,13 +40,11 @@ typedef struct {
} alarm_pin_pinalarm_obj_t;

mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(uint32_t TAMPID);
mp_obj_t alarm_pin_pinalarm_record_wake_alarm(uint32_t TAMPID);

void pin_alarm_callback(uint8_t num);
void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_deinit_alarms(size_t n_alarms, const mp_obj_t *alarms);
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
bool alarm_pin_pinalarm_woke_this_cycle(void);

#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
13 changes: 7 additions & 6 deletions ports/atmel-samd/common-hal/alarm/time/TimeAlarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
#include "py/runtime.h"
#include "hpl/pm/hpl_pm_base.h"

#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/time/__init__.h"
#include "common-hal/alarm/__init__.h"
#include "supervisor/port.h"

STATIC volatile bool woke_up = false;
Expand Down Expand Up @@ -58,13 +58,14 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
return mp_const_none;
}

mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) {
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t);
timer->base.type = &alarm_time_timealarm_type;
mp_obj_t alarm_time_timealarm_record_wake_alarm(void) {
alarm_time_timealarm_obj_t *const alarm = &alarm_wake_alarm.time_alarm;

alarm->base.type = &alarm_time_timealarm_type;
// TODO: Set monotonic_time based on the RTC state.
// Or don't, most of the other ports don't have this either.
timer->monotonic_time = 0.0f;
return timer;
alarm->monotonic_time = 0.0f;
return alarm;
}

void time_alarm_callback(void) {
Expand Down
7 changes: 2 additions & 5 deletions ports/atmel-samd/common-hal/alarm/time/TimeAlarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
#pragma once

#include "py/obj.h"

Expand All @@ -35,12 +34,10 @@ typedef struct {
} alarm_time_timealarm_obj_t;

mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void);
mp_obj_t alarm_time_timealarm_record_wake_alarm(void);
void time_alarm_callback(void);
bool alarm_time_timealarm_woke_this_cycle(void);
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_time_timealarm_reset(void);

void alarm_time_timealarm_prepare_for_deep_sleep(void);

#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
5 changes: 1 addition & 4 deletions ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
#pragma once

typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t *pin;
} alarm_touch_touchalarm_obj_t;

#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
5 changes: 1 addition & 4 deletions ports/espressif/common-hal/alarm/SleepMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
* THE SOFTWARE.
*/

#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H
#pragma once

#include "py/obj.h"

Expand All @@ -49,5 +48,3 @@ typedef struct {
} alarm_sleep_memory_obj_t;

extern void alarm_sleep_memory_reset(void);

#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H
Loading