Merge pull request #7154 from dhalbert/alarm-lifetime

Save wake alarm info in static storage, simplifying recording of alarm
This commit is contained in:
Dan Halbert 2022-10-30 12:28:50 -04:00 committed by GitHub
commit 952812cdea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 241 additions and 198 deletions

53
main.c
View File

@ -132,7 +132,7 @@ static void reset_devices(void) {
#endif #endif
} }
STATIC void start_mp(supervisor_allocation *heap, bool first_run) { STATIC void start_mp(supervisor_allocation *heap) {
supervisor_workflow_reset(); supervisor_workflow_reset();
// Stack limit should be less than real stack size, so we have a chance // 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) {
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); 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); 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) { STATIC void stop_mp(void) {
@ -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 serial_connected_at_start = serial_connected();
bool printed_safe_mode_message = false; bool printed_safe_mode_message = false;
#if CIRCUITPY_AUTORELOAD_DELAY_MS > 0 #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
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
// Prepare the VM state. Includes an alarm check/reset for sleep. // Prepare the VM state.
start_mp(heap, first_run); start_mp(heap);
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -755,8 +747,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
// true means this is the first set of VM's after a hard reset. start_mp(heap);
start_mp(heap, true);
#if CIRCUITPY_USB #if CIRCUITPY_USB
// Set up default USB values after boot.py VM starts but before running boot.py. // 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) {
#endif #endif
} }
STATIC int run_repl(bool first_run) { STATIC int run_repl(void) {
int exit_code = PYEXEC_FORCED_EXIT; int exit_code = PYEXEC_FORCED_EXIT;
stack_resize(); stack_resize();
filesystem_flush(); filesystem_flush();
supervisor_allocation *heap = allocate_remaining_memory(); supervisor_allocation *heap = allocate_remaining_memory();
start_mp(heap, first_run); start_mp(heap);
#if CIRCUITPY_USB #if CIRCUITPY_USB
usb_setup_with_vm(); usb_setup_with_vm();
@ -968,6 +959,15 @@ int __attribute__((used)) main(void) {
safe_mode = NO_CIRCUITPY; 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 everything and prep MicroPython to run boot.py.
reset_port(); reset_port();
// Port-independent devices, like CIRCUITPY_BLEIO_HCI. // Port-independent devices, like CIRCUITPY_BLEIO_HCI.
@ -1001,20 +1001,21 @@ int __attribute__((used)) main(void) {
// Boot script is finished, so now go into REPL or run code.py. // Boot script is finished, so now go into REPL or run code.py.
int exit_code = PYEXEC_FORCED_EXIT; int exit_code = PYEXEC_FORCED_EXIT;
bool skip_repl = true; bool skip_repl = true;
bool first_run = true; bool simulate_reset = true;
bool simulate_reset;
for (;;) { for (;;) {
simulate_reset = false;
if (!skip_repl) { if (!skip_repl) {
exit_code = run_repl(first_run); exit_code = run_repl();
supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); supervisor_set_run_reason(RUN_REASON_REPL_RELOAD);
} }
if (exit_code == PYEXEC_FORCED_EXIT) { if (exit_code == PYEXEC_FORCED_EXIT) {
if (!first_run) { if (!simulate_reset) {
serial_write_compressed(translate("soft reboot\n")); serial_write_compressed(translate("soft reboot\n"));
} }
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { 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 { } else {
skip_repl = false; skip_repl = false;
} }
@ -1022,10 +1023,10 @@ int __attribute__((used)) main(void) {
break; break;
} }
// Either the REPL or code.py has run and finished. #if CIRCUITPY_ALARM
// If code.py did a fake deep sleep, pretend that we are running code.py for shared_alarm_save_wake_alarm(simulate_reset ? common_hal_alarm_record_wake_alarm() : mp_const_none);
// the first time after a hard reset. This will preserve any alarm information. alarm_reset();
first_run = simulate_reset; #endif
} }
mp_deinit(); mp_deinit();
return 0; return 0;

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H #pragma once
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H
#include "py/obj.h" #include "py/obj.h"
@ -34,5 +33,3 @@ typedef struct {
} alarm_sleep_memory_obj_t; } alarm_sleep_memory_obj_t;
extern void alarm_sleep_memory_reset(void); extern void alarm_sleep_memory_reset(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_SLEEPMEMORY_H

View File

@ -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) { void alarm_reset(void) {
// Reset the alarm flag // Reset the alarm flag
alarm_pin_pinalarm_reset(); alarm_pin_pinalarm_reset();
@ -57,7 +61,7 @@ void alarm_reset(void) {
void alarm_get_wakeup_cause(void) { void alarm_get_wakeup_cause(void) {
// Called from rtc_init, just before SWRST of RTC. It is called // Called from rtc_init, just before SWRST of RTC. It is called
// at an early stage of main(), to save TAMPID from SWRST. Later, // 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. // alarm from the deep sleep.
TAMPID = RTC->MODE0.TAMPID.reg; TAMPID = RTC->MODE0.TAMPID.reg;
@ -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(); 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. // 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. // Return a copy of wakeup alarm from deep sleep / fake deep sleep.
// In case of fake sleep, status should be left in TimeAlarm/PinAlarm. // 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) {
if (alarm_pin_pinalarm_woke_this_cycle()) { if (alarm_pin_pinalarm_woke_this_cycle()) {
TAMPID = RTC->MODE0.TAMPID.reg; TAMPID = RTC->MODE0.TAMPID.reg;
RTC->MODE0.TAMPID.reg = TAMPID; // clear register 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)) { 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) { if (true_deep) {
return alarm_pin_pinalarm_create_wakeup_alarm(TAMPID); return alarm_pin_pinalarm_record_wake_alarm(TAMPID);
} }
return mp_const_none; return mp_const_none;
} }

View File

@ -24,10 +24,11 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H #pragma once
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H
#include "common-hal/alarm/SleepMemory.h" #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; extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
@ -53,8 +54,13 @@ typedef enum {
SAMD_WAKEUP_RTC SAMD_WAKEUP_RTC
} samd_sleep_source_t; } samd_sleep_source_t;
extern void alarm_set_wakeup_reason(samd_sleep_source_t reason); typedef union {
void alarm_get_wakeup_cause(void); alarm_pin_pinalarm_obj_t pin_alarm;
extern void alarm_reset(void); alarm_time_timealarm_obj_t time_alarm;
} alarm_wake_alarm_union_t;
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM__INIT__H extern alarm_wake_alarm_union_t alarm_wake_alarm;
extern void alarm_set_wakeup_reason(samd_sleep_source_t reason);
extern void alarm_get_wakeup_cause(void);
extern void alarm_reset(void);

View File

@ -31,9 +31,9 @@
#include "hal/include/hal_gpio.h" #include "hal/include/hal_gpio.h"
// #include <stdio.h> // #include <stdio.h>
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "common-hal/alarm/__init__.h" #include "common-hal/alarm/__init__.h"
// This variable stores whether a PinAlarm woke in light sleep or fake deep sleep // 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
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(uint32_t TAMPID) { mp_obj_t alarm_pin_pinalarm_record_wake_alarm(uint32_t TAMPID) {
// Create tamper alarm that caused wakeup from deep sleep alarm_pin_pinalarm_obj_t *const alarm = &alarm_wake_alarm.pin_alarm;
for (samd_tamper_pin_t *t = TAMPER_PINS; t->n >= 0; t++) { for (samd_tamper_pin_t *t = TAMPER_PINS; t->n >= 0; t++) {
if (TAMPID & (1 << t->n)) { 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->base.type = &alarm_pin_pinalarm_type;
alarm->pin = t->pin; alarm->pin = t->pin;
return alarm; return alarm;

View File

@ -24,12 +24,13 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H #pragma once
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H
#include "py/obj.h" #include "py/obj.h"
#include "py/objtuple.h" #include "py/objtuple.h"
#include "shared-bindings/microcontroller/Pin.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
@ -39,7 +40,7 @@ typedef struct {
} alarm_pin_pinalarm_obj_t; } 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_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 pin_alarm_callback(uint8_t num);
void alarm_pin_pinalarm_reset(void); void alarm_pin_pinalarm_reset(void);
@ -47,5 +48,3 @@ 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_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_pin_pinalarm_prepare_for_deep_sleep(void); void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
bool alarm_pin_pinalarm_woke_this_cycle(void); bool alarm_pin_pinalarm_woke_this_cycle(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_PINALARM_H

View File

@ -27,9 +27,9 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "hpl/pm/hpl_pm_base.h" #include "hpl/pm/hpl_pm_base.h"
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/time/__init__.h" #include "shared-bindings/time/__init__.h"
#include "common-hal/alarm/__init__.h"
#include "supervisor/port.h" #include "supervisor/port.h"
STATIC volatile bool woke_up = false; 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
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) { mp_obj_t alarm_time_timealarm_record_wake_alarm(void) {
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t); alarm_time_timealarm_obj_t *const alarm = &alarm_wake_alarm.time_alarm;
timer->base.type = &alarm_time_timealarm_type;
alarm->base.type = &alarm_time_timealarm_type;
// TODO: Set monotonic_time based on the RTC state. // TODO: Set monotonic_time based on the RTC state.
// Or don't, most of the other ports don't have this either. // Or don't, most of the other ports don't have this either.
timer->monotonic_time = 0.0f; alarm->monotonic_time = 0.0f;
return timer; return alarm;
} }
void time_alarm_callback(void) { void time_alarm_callback(void) {

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H #pragma once
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H
#include "py/obj.h" #include "py/obj.h"
@ -35,12 +34,10 @@ typedef struct {
} alarm_time_timealarm_obj_t; } 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_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); void time_alarm_callback(void);
bool alarm_time_timealarm_woke_this_cycle(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_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_time_timealarm_reset(void); void alarm_time_timealarm_reset(void);
void alarm_time_timealarm_prepare_for_deep_sleep(void); void alarm_time_timealarm_prepare_for_deep_sleep(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TIMEALARM_H

View File

@ -24,12 +24,9 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H #pragma once
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
} alarm_touch_touchalarm_obj_t; } alarm_touch_touchalarm_obj_t;
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_ALARM_TOUCHALARM_H

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H #pragma once
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H
#include "py/obj.h" #include "py/obj.h"
@ -49,5 +48,3 @@ typedef struct {
} alarm_sleep_memory_obj_t; } alarm_sleep_memory_obj_t;
extern void alarm_sleep_memory_reset(void); extern void alarm_sleep_memory_reset(void);
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM_SLEEPMEMORY_H

View File

@ -58,6 +58,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) { void alarm_reset(void) {
alarm_sleep_memory_reset(); alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset(); alarm_pin_pinalarm_reset();
@ -90,27 +94,27 @@ bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED; return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED;
} }
mp_obj_t common_hal_alarm_create_wake_alarm(void) { mp_obj_t common_hal_alarm_record_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have // If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none // been passed in originally. Otherwise, just return none
esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(); esp_sleep_wakeup_cause_t cause = _get_wakeup_cause();
switch (cause) { switch (cause) {
case ESP_SLEEP_WAKEUP_TIMER: { case ESP_SLEEP_WAKEUP_TIMER: {
return alarm_time_timealarm_create_wakeup_alarm(); return alarm_time_timealarm_record_wake_alarm();
} }
case ESP_SLEEP_WAKEUP_GPIO: case ESP_SLEEP_WAKEUP_GPIO:
case ESP_SLEEP_WAKEUP_EXT0: case ESP_SLEEP_WAKEUP_EXT0:
case ESP_SLEEP_WAKEUP_EXT1: { case ESP_SLEEP_WAKEUP_EXT1: {
return alarm_pin_pinalarm_create_wakeup_alarm(); return alarm_pin_pinalarm_record_wake_alarm();
} }
case ESP_SLEEP_WAKEUP_TOUCHPAD: { case ESP_SLEEP_WAKEUP_TOUCHPAD: {
return alarm_touch_touchalarm_create_wakeup_alarm(); return alarm_touch_touchalarm_record_wake_alarm();
} }
case ESP_SLEEP_WAKEUP_ULP: { case ESP_SLEEP_WAKEUP_ULP: {
return alarm_coproc_coprocalarm_create_wakeup_alarm(); return alarm_coproc_coprocalarm_record_wake_alarm();
} }
case ESP_SLEEP_WAKEUP_UNDEFINED: case ESP_SLEEP_WAKEUP_UNDEFINED:

View File

@ -24,13 +24,22 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM__INIT__H #pragma once
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM__INIT__H
#include "common-hal/alarm/SleepMemory.h" #include "common-hal/alarm/SleepMemory.h"
#include "common-hal/alarm/coproc/CoprocAlarm.h"
#include "common-hal/alarm/pin/PinAlarm.h"
#include "common-hal/alarm/time/TimeAlarm.h"
#include "common-hal/alarm/touch/TouchAlarm.h"
const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; typedef union {
alarm_coproc_coprocalarm_obj_t coproc_alarm;
alarm_pin_pinalarm_obj_t pin_alarm;
alarm_time_timealarm_obj_t time_alarm;
alarm_touch_touchalarm_obj_t touch_alarm;
} alarm_wake_alarm_union_t;
extern alarm_wake_alarm_union_t alarm_wake_alarm;
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
extern void alarm_reset(void); extern void alarm_reset(void);
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ALARM__INIT__H

View File

@ -24,6 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/coproc/CoprocAlarm.h" #include "shared-bindings/alarm/coproc/CoprocAlarm.h"
#include "shared-bindings/coproc/__init__.h" #include "shared-bindings/coproc/__init__.h"
@ -47,9 +48,9 @@ mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, co
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_coproc_coprocalarm_create_wakeup_alarm(void) { mp_obj_t alarm_coproc_coprocalarm_record_wake_alarm(void) {
// Create CoprocAlarm object. alarm_coproc_coprocalarm_obj_t *const alarm = &alarm_wake_alarm.coproc_alarm;
alarm_coproc_coprocalarm_obj_t *alarm = m_new_obj(alarm_coproc_coprocalarm_obj_t);
alarm->base.type = &alarm_coproc_coprocalarm_type; alarm->base.type = &alarm_coproc_coprocalarm_type;
return alarm; return alarm;
} }
@ -111,7 +112,7 @@ mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, co
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_coproc_coprocalarm_create_wakeup_alarm(void) { mp_obj_t alarm_coproc_coprocalarm_record_wake_alarm(void) {
return mp_const_none; return mp_const_none;
} }

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_COMMON_HAL_ALARM_COPROC_COPROCALARM_H #pragma once
#define MICROPY_INCLUDED_COMMON_HAL_ALARM_COPROC_COPROCALARM_H
#include "py/obj.h" #include "py/obj.h"
#include "py/runtime.h" #include "py/runtime.h"
@ -38,11 +37,9 @@ typedef struct {
} alarm_coproc_coprocalarm_obj_t; } alarm_coproc_coprocalarm_obj_t;
mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms); mp_obj_t alarm_coproc_coprocalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_coproc_coprocalarm_create_wakeup_alarm(void); mp_obj_t alarm_coproc_coprocalarm_record_wake_alarm(void);
void alarm_coproc_coprocalarm_prepare_for_deep_sleep(void); void alarm_coproc_coprocalarm_prepare_for_deep_sleep(void);
void alarm_coproc_coprocalarm_reset(void); void alarm_coproc_coprocalarm_reset(void);
void alarm_coproc_coprocalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms); void alarm_coproc_coprocalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
bool alarm_coproc_coprocalarm_woke_this_cycle(void); bool alarm_coproc_coprocalarm_woke_this_cycle(void);
#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_COPROC_COPROCALARM_H

View File

@ -26,10 +26,10 @@
*/ */
#include "py/runtime.h" #include "py/runtime.h"
#include "supervisor/port.h" #include "supervisor/port.h"
#include "common-hal/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "esp_sleep.h" #include "esp_sleep.h"
@ -111,7 +111,7 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) { mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void) {
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
// Pin status will persist into a fake deep sleep // Pin status will persist into a fake deep sleep
@ -135,7 +135,8 @@ mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) {
} }
} }
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); alarm_pin_pinalarm_obj_t *const alarm = &alarm_wake_alarm.pin_alarm;
alarm->base.type = &alarm_pin_pinalarm_type; alarm->base.type = &alarm_pin_pinalarm_type;
alarm->pin = NULL; alarm->pin = NULL;
// Map the pin number back to a pin object. // Map the pin number back to a pin object.

View File

@ -24,9 +24,13 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#pragma once
#include "py/obj.h" #include "py/obj.h"
#include "py/objtuple.h" #include "py/objtuple.h"
#include "shared-bindings/microcontroller/Pin.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
@ -35,7 +39,7 @@ typedef struct {
} alarm_pin_pinalarm_obj_t; } 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_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void); mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void);
void alarm_pin_pinalarm_prepare_for_deep_sleep(void); void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
void alarm_pin_pinalarm_reset(void); void alarm_pin_pinalarm_reset(void);

View File

@ -31,6 +31,7 @@
#include "components/esp_timer/include/esp_timer.h" #include "components/esp_timer/include/esp_timer.h"
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/time/__init__.h" #include "shared-bindings/time/__init__.h"
@ -51,12 +52,13 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) { mp_obj_t alarm_time_timealarm_record_wake_alarm(void) {
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t); alarm_time_timealarm_obj_t *const alarm = &alarm_wake_alarm.time_alarm;
timer->base.type = &alarm_time_timealarm_type;
alarm->base.type = &alarm_time_timealarm_type;
// TODO: Set monotonic_time based on the RTC state. // TODO: Set monotonic_time based on the RTC state.
timer->monotonic_time = 0.0f; alarm->monotonic_time = 0.0f;
return timer; return alarm;
} }
esp_timer_handle_t pretend_sleep_timer; esp_timer_handle_t pretend_sleep_timer;

View File

@ -24,6 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#pragma once
#include "py/obj.h" #include "py/obj.h"
@ -33,7 +34,7 @@ typedef struct {
} alarm_time_timealarm_obj_t; } 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_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 alarm_time_timealarm_reset(void); void alarm_time_timealarm_reset(void);
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);

View File

@ -24,6 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/touch/TouchAlarm.h" #include "shared-bindings/alarm/touch/TouchAlarm.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
@ -52,9 +53,9 @@ mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, cons
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void) { mp_obj_t alarm_touch_touchalarm_record_wake_alarm(void) {
// Create TouchAlarm object. alarm_touch_touchalarm_obj_t *const alarm = &alarm_wake_alarm.touch_alarm;
alarm_touch_touchalarm_obj_t *alarm = m_new_obj(alarm_touch_touchalarm_obj_t);
alarm->base.type = &alarm_touch_touchalarm_type; alarm->base.type = &alarm_touch_touchalarm_type;
alarm->pin = NULL; alarm->pin = NULL;

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H #pragma once
#define MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
#include "py/obj.h" #include "py/obj.h"
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
@ -36,11 +35,9 @@ typedef struct {
} alarm_touch_touchalarm_obj_t; } alarm_touch_touchalarm_obj_t;
mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms); mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void); mp_obj_t alarm_touch_touchalarm_record_wake_alarm(void);
void alarm_touch_touchalarm_prepare_for_deep_sleep(void); void alarm_touch_touchalarm_prepare_for_deep_sleep(void);
void alarm_touch_touchalarm_reset(void); void alarm_touch_touchalarm_reset(void);
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms); void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
bool alarm_touch_touchalarm_woke_this_cycle(void); bool alarm_touch_touchalarm_woke_this_cycle(void);
#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H #pragma once
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H
#include "py/obj.h" #include "py/obj.h"
@ -37,5 +36,3 @@ typedef struct {
extern void set_memory_retention(void); extern void set_memory_retention(void);
extern void alarm_sleep_memory_reset(void); extern void alarm_sleep_memory_reset(void);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM_SLEEPMEMORY_H

View File

@ -56,6 +56,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) { void alarm_reset(void) {
alarm_sleep_memory_reset(); alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset(); alarm_pin_pinalarm_reset();
@ -115,19 +119,19 @@ bool common_hal_alarm_woken_from_sleep(void) {
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD; || cause == NRF_SLEEP_WAKEUP_TOUCHPAD;
} }
mp_obj_t common_hal_alarm_create_wake_alarm(void) { mp_obj_t common_hal_alarm_record_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have // If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none // been passed in originally. Otherwise, just return none
nrf_sleep_source_t cause = _get_wakeup_cause(); nrf_sleep_source_t cause = _get_wakeup_cause();
switch (cause) { switch (cause) {
case NRF_SLEEP_WAKEUP_TIMER: { case NRF_SLEEP_WAKEUP_TIMER: {
return alarm_time_timealarm_create_wakeup_alarm(); return alarm_time_timealarm_record_wake_alarm();
} }
case NRF_SLEEP_WAKEUP_TOUCHPAD: { case NRF_SLEEP_WAKEUP_TOUCHPAD: {
return alarm_touch_touchalarm_create_wakeup_alarm(); return alarm_touch_touchalarm_record_wake_alarm();
} }
case NRF_SLEEP_WAKEUP_GPIO: { case NRF_SLEEP_WAKEUP_GPIO: {
return alarm_pin_pinalarm_create_wakeup_alarm(); return alarm_pin_pinalarm_record_wake_alarm();
} }
default: default:
break; break;

View File

@ -25,10 +25,12 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H #pragma once
#define MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H
#include "common-hal/alarm/SleepMemory.h" #include "common-hal/alarm/SleepMemory.h"
#include "common-hal/alarm/pin/PinAlarm.h"
#include "common-hal/alarm/time/TimeAlarm.h"
#include "common-hal/alarm/touch/TouchAlarm.h"
typedef enum { typedef enum {
NRF_SLEEP_WAKEUP_UNDEFINED, NRF_SLEEP_WAKEUP_UNDEFINED,
@ -40,6 +42,13 @@ typedef enum {
NRF_SLEEP_WAKEUP_ZZZ NRF_SLEEP_WAKEUP_ZZZ
} nrf_sleep_source_t; } nrf_sleep_source_t;
typedef union {
alarm_pin_pinalarm_obj_t pin_alarm;
alarm_time_timealarm_obj_t time_alarm;
alarm_touch_touchalarm_obj_t touch_alarm;
} alarm_wake_alarm_union_t;
extern alarm_wake_alarm_union_t alarm_wake_alarm;
extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
enum { enum {
@ -52,5 +61,3 @@ extern uint8_t sleepmem_wakeup_event;
extern uint8_t sleepmem_wakeup_pin; extern uint8_t sleepmem_wakeup_pin;
extern void alarm_reset(void); extern void alarm_reset(void);
#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_ALARM__INIT__H

View File

@ -30,10 +30,9 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "common-hal/alarm/__init__.h"
#include "nrfx.h" #include "nrfx.h"
#include "nrf_gpio.h" #include "nrf_gpio.h"
@ -101,8 +100,9 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) { mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void) {
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); alarm_pin_pinalarm_obj_t *const alarm = &alarm_wake_alarm.pin_alarm;
alarm->base.type = &alarm_pin_pinalarm_type; alarm->base.type = &alarm_pin_pinalarm_type;
alarm->pin = NULL; alarm->pin = NULL;
// Map the pin number back to a pin object. // Map the pin number back to a pin object.

View File

@ -24,9 +24,13 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#pragma once
#include "py/obj.h" #include "py/obj.h"
#include "py/objtuple.h" #include "py/objtuple.h"
#include "shared-bindings/microcontroller/Pin.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
@ -35,7 +39,7 @@ typedef struct {
} alarm_pin_pinalarm_obj_t; } 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_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void); mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void);
void alarm_pin_pinalarm_reset(void); void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, 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);

View File

@ -28,7 +28,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include <stdio.h> #include <stdio.h>
#include "common-hal/alarm/__init__.h" #include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/time/__init__.h" #include "shared-bindings/time/__init__.h"
@ -49,12 +49,13 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) { mp_obj_t alarm_time_timealarm_record_wake_alarm(void) {
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t); alarm_time_timealarm_obj_t *const alarm = &alarm_wake_alarm.time_alarm;
timer->base.type = &alarm_time_timealarm_type;
alarm->base.type = &alarm_time_timealarm_type;
// TODO: Set monotonic_time based on the RTC state. // TODO: Set monotonic_time based on the RTC state.
timer->monotonic_time = 0.0f; alarm->monotonic_time = 0.0f;
return timer; return alarm;
} }
bool alarm_time_timealarm_woke_this_cycle(void) { bool alarm_time_timealarm_woke_this_cycle(void) {

View File

@ -24,6 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#pragma once
#include "py/obj.h" #include "py/obj.h"
@ -37,7 +38,7 @@ extern void port_disable_interrupt_after_ticks_ch(uint32_t channel);
extern void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks); extern void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks);
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms); 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);
bool alarm_time_timealarm_woke_this_cycle(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_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);

View File

@ -25,6 +25,7 @@
*/ */
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/alarm/touch/TouchAlarm.h" #include "shared-bindings/alarm/touch/TouchAlarm.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
@ -39,7 +40,7 @@ mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, cons
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void) { mp_obj_t alarm_touch_touchalarm_record_wake_alarm(void) {
return mp_const_none; return mp_const_none;
} }

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H #pragma once
#define MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
#include "py/obj.h" #include "py/obj.h"
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
@ -37,11 +36,9 @@ typedef struct {
// Find the alarm object that caused us to wake up or create an equivalent one. // Find the alarm object that caused us to wake up or create an equivalent one.
mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms); mp_obj_t alarm_touch_touchalarm_find_triggered_alarm(const size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void); mp_obj_t alarm_touch_touchalarm_record_wake_alarm(void);
// Check for the wake up alarm from pretend deep sleep. // Check for the wake up alarm from pretend deep sleep.
void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms); void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alarms, const mp_obj_t *alarms);
void alarm_touch_touchalarm_prepare_for_deep_sleep(void); void alarm_touch_touchalarm_prepare_for_deep_sleep(void);
bool alarm_touch_touchalarm_woke_this_cycle(void); bool alarm_touch_touchalarm_woke_this_cycle(void);
void alarm_touch_touchalarm_reset(void); void alarm_touch_touchalarm_reset(void);
#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H

View File

@ -64,11 +64,11 @@
#include "lib/tinyusb/src/device/usbd.h" #include "lib/tinyusb/src/device/usbd.h"
#ifdef CIRCUITPY_AUDIOBUSIO #if CIRCUITPY_AUDIOBUSIO
#include "common-hal/audiobusio/I2SOut.h" #include "common-hal/audiobusio/I2SOut.h"
#endif #endif
#ifdef CIRCUITPY_AUDIOPWMIO #if CIRCUITPY_AUDIOPWMIO
#include "common-hal/audiopwmio/PWMAudioOut.h" #include "common-hal/audiopwmio/PWMAudioOut.h"
#endif #endif

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM_SLEEPMEMORY_H #pragma once
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM_SLEEPMEMORY_H
#include "py/obj.h" #include "py/obj.h"
@ -34,5 +33,3 @@ typedef struct {
} alarm_sleep_memory_obj_t; } alarm_sleep_memory_obj_t;
extern void alarm_sleep_memory_reset(void); extern void alarm_sleep_memory_reset(void);
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM_SLEEPMEMORY_H

View File

@ -96,6 +96,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) { void alarm_reset(void) {
alarm_sleep_memory_reset(); alarm_sleep_memory_reset();
alarm_pin_pinalarm_reset(); alarm_pin_pinalarm_reset();
@ -131,17 +135,17 @@ bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != RP_SLEEP_WAKEUP_UNDEF; return _get_wakeup_cause() != RP_SLEEP_WAKEUP_UNDEF;
} }
mp_obj_t common_hal_alarm_create_wake_alarm(void) { mp_obj_t common_hal_alarm_record_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have // If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none // been passed in originally. Otherwise, just return none
uint8_t cause = _get_wakeup_cause(); uint8_t cause = _get_wakeup_cause();
switch (cause) { switch (cause) {
case RP_SLEEP_WAKEUP_RTC: { case RP_SLEEP_WAKEUP_RTC: {
return alarm_time_timealarm_create_wakeup_alarm(); return alarm_time_timealarm_record_wake_alarm();
} }
case RP_SLEEP_WAKEUP_GPIO: { case RP_SLEEP_WAKEUP_GPIO: {
return alarm_pin_pinalarm_create_wakeup_alarm(); return alarm_pin_pinalarm_record_wake_alarm();
} }
case RP_SLEEP_WAKEUP_UNDEF: case RP_SLEEP_WAKEUP_UNDEF:

View File

@ -24,10 +24,11 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM__INIT__H #pragma once
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM__INIT__H
#include "common-hal/alarm/SleepMemory.h" #include "common-hal/alarm/SleepMemory.h"
#include "common-hal/alarm/pin/PinAlarm.h"
#include "common-hal/alarm/time/TimeAlarm.h"
#include "hardware/regs/clocks.h" #include "hardware/regs/clocks.h"
@ -35,8 +36,12 @@
#define RP_SLEEP_WAKEUP_GPIO 1 #define RP_SLEEP_WAKEUP_GPIO 1
#define RP_SLEEP_WAKEUP_RTC 2 #define RP_SLEEP_WAKEUP_RTC 2
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 const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
extern void alarm_reset(void); extern void alarm_reset(void);
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM__INIT__H

View File

@ -26,10 +26,10 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/pin/PinAlarm.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "common-hal/microcontroller/__init__.h" #include "common-hal/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "pico/stdlib.h" #include "pico/stdlib.h"
#include "hardware/gpio.h" #include "hardware/gpio.h"
@ -94,10 +94,12 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) { mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void) {
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); alarm_pin_pinalarm_obj_t *const alarm = &alarm_wake_alarm.pin_alarm;
alarm->base.type = &alarm_pin_pinalarm_type; alarm->base.type = &alarm_pin_pinalarm_type;
// TODO: how to obtain the correct pin from memory? // TODO: how to obtain the correct pin from memory?
alarm->pin = NULL;
return alarm; return alarm;
} }

View File

@ -24,9 +24,13 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#pragma once
#include "py/obj.h" #include "py/obj.h"
#include "py/objtuple.h" #include "py/objtuple.h"
#include "shared-bindings/microcontroller/Pin.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
@ -36,7 +40,7 @@ typedef struct {
} alarm_pin_pinalarm_obj_t; } 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_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void); mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void);
void alarm_pin_pinalarm_reset(void); void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_light_reset(void); void alarm_pin_pinalarm_light_reset(void);

View File

@ -26,6 +26,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/time/__init__.h" #include "shared-bindings/time/__init__.h"
@ -58,12 +59,13 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) { mp_obj_t alarm_time_timealarm_record_wake_alarm(void) {
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t); alarm_time_timealarm_obj_t *const alarm = &alarm_wake_alarm.time_alarm;
timer->base.type = &alarm_time_timealarm_type;
alarm->base.type = &alarm_time_timealarm_type;
// TODO: Set monotonic_time based on the RTC state. // TODO: Set monotonic_time based on the RTC state.
timer->monotonic_time = 0.0f; alarm->monotonic_time = 0.0f;
return timer; return alarm;
} }
bool alarm_time_timealarm_woke_this_cycle(void) { bool alarm_time_timealarm_woke_this_cycle(void) {

View File

@ -24,6 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#pragma once
#include "py/obj.h" #include "py/obj.h"
@ -33,7 +34,7 @@ typedef struct {
} alarm_time_timealarm_obj_t; } 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_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 alarm_time_timealarm_reset(void); void alarm_time_timealarm_reset(void);
void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H #pragma once
#define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H
#include "py/obj.h" #include "py/obj.h"
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
@ -34,5 +33,3 @@ typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
} alarm_touch_touchalarm_obj_t; } alarm_touch_touchalarm_obj_t;
#endif // MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H #pragma once
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H
#include "py/obj.h" #include "py/obj.h"
@ -34,5 +33,3 @@ typedef struct {
} alarm_sleep_memory_obj_t; } alarm_sleep_memory_obj_t;
extern void alarm_sleep_memory_reset(void); extern void alarm_sleep_memory_reset(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H

View File

@ -47,6 +47,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;
STATIC stm_sleep_source_t true_deep_wake_reason; STATIC stm_sleep_source_t true_deep_wake_reason;
void alarm_reset(void) { void alarm_reset(void) {
@ -81,16 +85,16 @@ bool common_hal_alarm_woken_from_sleep(void) {
return alarm_get_wakeup_cause() != STM_WAKEUP_UNDEF; return alarm_get_wakeup_cause() != STM_WAKEUP_UNDEF;
} }
mp_obj_t common_hal_alarm_create_wake_alarm(void) { mp_obj_t common_hal_alarm_record_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have // If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none // been passed in originally. Otherwise, just return none
stm_sleep_source_t cause = alarm_get_wakeup_cause(); stm_sleep_source_t cause = alarm_get_wakeup_cause();
switch (cause) { switch (cause) {
case STM_WAKEUP_RTC: { case STM_WAKEUP_RTC: {
return alarm_time_timealarm_create_wakeup_alarm(); return alarm_time_timealarm_record_wake_alarm();
} }
case STM_WAKEUP_GPIO: { case STM_WAKEUP_GPIO: {
return alarm_pin_pinalarm_create_wakeup_alarm(); return alarm_pin_pinalarm_record_wake_alarm();
} }
case STM_WAKEUP_UNDEF: case STM_WAKEUP_UNDEF:
default: default:

View File

@ -24,10 +24,11 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H #pragma once
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H
#include "common-hal/alarm/SleepMemory.h" #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; extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj;
@ -37,10 +38,15 @@ typedef enum {
STM_WAKEUP_RTC STM_WAKEUP_RTC
} stm_sleep_source_t; } stm_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;
#define STM_ALARM_FLAG (RTC->BKP0R) #define STM_ALARM_FLAG (RTC->BKP0R)
extern void alarm_set_wakeup_reason(stm_sleep_source_t reason); extern void alarm_set_wakeup_reason(stm_sleep_source_t reason);
stm_sleep_source_t alarm_get_wakeup_cause(void); extern stm_sleep_source_t alarm_get_wakeup_cause(void);
extern void alarm_reset(void); extern void alarm_reset(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H

View File

@ -26,6 +26,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/pin/PinAlarm.h"
#include "peripherals/exti.h" #include "peripherals/exti.h"
@ -100,8 +101,9 @@ mp_obj_t alarm_pin_pinalarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void) { mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void) {
alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); alarm_pin_pinalarm_obj_t *const alarm = &alarm_wake_alarm.pin_alarm;
alarm->base.type = &alarm_pin_pinalarm_type; alarm->base.type = &alarm_pin_pinalarm_type;
// TODO: replace this if/when other WKUP pins are supported // TODO: replace this if/when other WKUP pins are supported
alarm->pin = &pin_PA00; alarm->pin = &pin_PA00;

View File

@ -24,12 +24,13 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H #pragma once
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H
#include "py/obj.h" #include "py/obj.h"
#include "py/objtuple.h" #include "py/objtuple.h"
#include "shared-bindings/microcontroller/Pin.h"
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
@ -38,11 +39,9 @@ typedef struct {
} alarm_pin_pinalarm_obj_t; } 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_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms);
mp_obj_t alarm_pin_pinalarm_create_wakeup_alarm(void); mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void);
void alarm_pin_pinalarm_reset(void); void alarm_pin_pinalarm_reset(void);
void alarm_pin_pinalarm_set_alarms(bool deep_sleep, 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); void alarm_pin_pinalarm_prepare_for_deep_sleep(void);
bool alarm_pin_pinalarm_woke_this_cycle(void); bool alarm_pin_pinalarm_woke_this_cycle(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H

View File

@ -26,6 +26,7 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared-bindings/alarm/__init__.h"
#include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h"
#include "shared-bindings/time/__init__.h" #include "shared-bindings/time/__init__.h"
#include "peripherals/rtc.h" #include "peripherals/rtc.h"
@ -53,12 +54,13 @@ mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj
return mp_const_none; return mp_const_none;
} }
mp_obj_t alarm_time_timealarm_create_wakeup_alarm(void) { mp_obj_t alarm_time_timealarm_record_wake_alarm(void) {
alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t); alarm_time_timealarm_obj_t *const alarm = &alarm_wake_alarm.time_alarm;
timer->base.type = &alarm_time_timealarm_type;
alarm->base.type = &alarm_time_timealarm_type;
// TODO: Set monotonic_time based on the RTC state. // TODO: Set monotonic_time based on the RTC state.
timer->monotonic_time = 0.0f; alarm->monotonic_time = 0.0f;
return timer; return alarm;
} }
// This is run in the timer task. We use it to wake the main CircuitPython task. // This is run in the timer task. We use it to wake the main CircuitPython task.

View File

@ -24,8 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TIMEALARM_H #pragma once
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TIMEALARM_H
#include "py/obj.h" #include "py/obj.h"
@ -35,12 +34,10 @@ typedef struct {
} alarm_time_timealarm_obj_t; } 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_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);
bool alarm_time_timealarm_woke_this_cycle(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_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms);
void alarm_time_timealarm_reset(void); void alarm_time_timealarm_reset(void);
void alarm_time_timealarm_prepare_for_deep_sleep(void); void alarm_time_timealarm_prepare_for_deep_sleep(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TIMEALARM_H

View File

@ -24,12 +24,9 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H #pragma once
#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
const mcu_pin_obj_t *pin; const mcu_pin_obj_t *pin;
} alarm_touch_touchalarm_obj_t; } alarm_touch_touchalarm_obj_t;
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H

View File

@ -55,7 +55,7 @@ extern void common_hal_alarm_pretending_deep_sleep(void);
extern mp_obj_t shared_alarm_get_wake_alarm(void); extern mp_obj_t shared_alarm_get_wake_alarm(void);
// Creates a new alarm object after exiting deep sleep (real or fake) // Creates a new alarm object after exiting deep sleep (real or fake)
extern mp_obj_t common_hal_alarm_create_wake_alarm(void); extern mp_obj_t common_hal_alarm_record_wake_alarm(void);
// Saves alarm to global array // Saves alarm to global array
void shared_alarm_save_wake_alarm(mp_obj_t alarm); void shared_alarm_save_wake_alarm(mp_obj_t alarm);