Add STM32 and NRF52 compatibility

This commit is contained in:
Lucian Copeland 2021-05-14 14:34:35 -04:00
parent 295103bb31
commit 715f7ee490
12 changed files with 110 additions and 77 deletions

View File

@ -69,15 +69,18 @@ void alarm_reset(void) {
extern uint32_t reset_reason_saved;
STATIC nrf_sleep_source_t _get_wakeup_cause(void) {
if (alarm_pin_pinalarm_woke_us_up()) {
// First check if the modules remember what last woke up
if (alarm_pin_pinalarm_woke_this_cycle()) {
return NRF_SLEEP_WAKEUP_GPIO;
}
if (alarm_time_timealarm_woke_us_up()) {
if (alarm_time_timealarm_woke_this_cycle()) {
return NRF_SLEEP_WAKEUP_TIMER;
}
if (alarm_touch_touchalarm_woke_us_up()) {
if (alarm_touch_touchalarm_woke_this_cycle()) {
return NRF_SLEEP_WAKEUP_TOUCHPAD;
}
// If waking from true deep sleep, modules will have lost their state,
// so check the deep wakeup cause manually
if (reset_reason_saved & NRF_POWER_RESETREAS_RESETPIN_MASK) {
return NRF_SLEEP_WAKEUP_RESETPIN;
} else if (reset_reason_saved & NRF_POWER_RESETREAS_OFF_MASK) {
@ -116,17 +119,19 @@ bool common_hal_alarm_woken_from_sleep(void) {
|| cause == NRF_SLEEP_WAKEUP_TOUCHPAD;
}
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none
nrf_sleep_source_t cause = _get_wakeup_cause();
switch (cause) {
case NRF_SLEEP_WAKEUP_TIMER: {
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_time_timealarm_create_wakeup_alarm();
}
case NRF_SLEEP_WAKEUP_TOUCHPAD: {
return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_touch_touchalarm_create_wakeup_alarm();
}
case NRF_SLEEP_WAKEUP_GPIO: {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_pin_pinalarm_create_wakeup_alarm();
}
default:
break;
@ -134,11 +139,6 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
return mp_const_none;
}
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
mp_obj_t obj = _get_wake_alarm(0, NULL);
return obj;
}
// Set up light sleep or deep sleep alarms.
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
@ -257,7 +257,7 @@ void system_on_idle_until_alarm(int64_t timediff_ms, uint32_t prescaler) {
}
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t wake_alarm;
mp_obj_t wake_alarm = mp_const_none;
alarm_time_timealarm_clear_wakeup_time();
_setup_sleep_alarms(false, n_alarms, alarms);
@ -271,7 +271,23 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj
if (mp_hal_is_interrupted()) {
wake_alarm = mp_const_none;
} else {
wake_alarm = _get_wake_alarm(n_alarms, alarms);
if (common_hal_alarm_woken_from_sleep()) {
nrf_sleep_source_t cause = _get_wakeup_cause();
switch (cause) {
case NRF_SLEEP_WAKEUP_TIMER: {
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
break;
}
case NRF_SLEEP_WAKEUP_GPIO: {
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
break;
}
default:
// Should not reach this, if all light sleep types are covered correctly
break;
}
shared_alarm_save_wake_alarm(wake_alarm);
}
}
alarm_reset();
return wake_alarm;

View File

@ -85,12 +85,12 @@ static void pinalarm_gpiote_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t
sleepmem_wakeup_pin = pin & 0xFF;
}
bool alarm_pin_pinalarm_woke_us_up(void) {
bool alarm_pin_pinalarm_woke_this_cycle(void) {
return sleepmem_wakeup_event == SLEEPMEM_WAKEUP_BY_PIN &&
sleepmem_wakeup_pin != WAKEUP_PIN_UNDEF;
}
mp_obj_t alarm_pin_pinalarm_get_wakeup_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) {
// First, check to see if we match any given alarms.
for (size_t i = 0; i < n_alarms; i++) {
if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
@ -101,6 +101,10 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
return alarms[i];
}
}
return mp_const_none;
}
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->base.type = &alarm_pin_pinalarm_type;
alarm->pin = NULL;

View File

@ -34,8 +34,10 @@ typedef struct {
bool pull;
} 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(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_prepare_for_deep_sleep(void);
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
bool alarm_pin_pinalarm_woke_us_up(void);
bool alarm_pin_pinalarm_woke_this_cycle(void);

View File

@ -40,13 +40,16 @@ mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timeala
return self->monotonic_time;
}
mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) {
// First, check to see if we match
mp_obj_t alarm_time_timealarm_find_triggered_alarm(size_t n_alarms, const mp_obj_t *alarms) {
for (size_t i = 0; i < n_alarms; i++) {
if (mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) {
return alarms[i];
}
}
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;
// TODO: Set monotonic_time based on the RTC state.
@ -54,7 +57,7 @@ mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *
return timer;
}
bool alarm_time_timealarm_woke_us_up(void) {
bool alarm_time_timealarm_woke_this_cycle(void) {
return sleepmem_wakeup_event == SLEEPMEM_WAKEUP_BY_TIMER;
}

View File

@ -36,10 +36,11 @@ extern volatile int rtc_woke_up_counter;
extern void port_disable_interrupt_after_ticks_ch(uint32_t channel);
extern void port_interrupt_after_ticks_ch(uint32_t channel, uint32_t ticks);
// Find the alarm object that caused us to wake up or create an equivalent one.
mp_obj_t alarm_time_timealarm_get_wakeup_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);
// Check for the wake up alarm from pretend deep sleep.
bool alarm_time_timealarm_woke_us_up(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);

View File

@ -35,7 +35,11 @@ void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *s
(void)pin;
}
mp_obj_t alarm_touch_touchalarm_get_wakeup_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) {
return mp_const_none;
}
mp_obj_t alarm_touch_touchalarm_create_wakeup_alarm(void) {
return mp_const_none;
}
@ -45,7 +49,7 @@ void alarm_touch_touchalarm_set_alarm(const bool deep_sleep, const size_t n_alar
void alarm_touch_touchalarm_prepare_for_deep_sleep(void) {
}
bool alarm_touch_touchalarm_woke_us_up(void) {
bool alarm_touch_touchalarm_woke_this_cycle(void) {
return false;
}

View File

@ -36,11 +36,12 @@ typedef struct {
} alarm_touch_touchalarm_obj_t;
// Find the alarm object that caused us to wake up or create an equivalent one.
mp_obj_t alarm_touch_touchalarm_get_wakeup_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);
// 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_prepare_for_deep_sleep(void);
bool alarm_touch_touchalarm_woke_us_up(void);
bool alarm_touch_touchalarm_woke_this_cycle(void);
void alarm_touch_touchalarm_reset(void);
#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H

View File

@ -48,10 +48,8 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = {
};
STATIC stm_sleep_source_t true_deep_wake_reason;
STATIC mp_obj_t most_recent_alarm;
void alarm_reset(void) {
most_recent_alarm = NULL;
// Reset the alarm flag
STM_ALARM_FLAG = 0x00;
alarm_pin_pinalarm_reset();
@ -66,10 +64,10 @@ void alarm_set_wakeup_reason(stm_sleep_source_t reason) {
STATIC stm_sleep_source_t _get_wakeup_cause(void) {
// If in light/fake sleep, check modules
if (alarm_pin_pinalarm_woke_us_up()) {
if (alarm_pin_pinalarm_woke_this_cycle()) {
return STM_WAKEUP_GPIO;
}
if (alarm_time_timealarm_woke_us_up()) {
if (alarm_time_timealarm_woke_this_cycle()) {
return STM_WAKEUP_RTC;
}
// Check to see if we woke from deep sleep (reason set in port_init)
@ -83,14 +81,16 @@ bool common_hal_alarm_woken_from_sleep(void) {
return _get_wakeup_cause() != STM_WAKEUP_UNDEF;
}
STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
mp_obj_t common_hal_alarm_create_wake_alarm(void) {
// If woken from deep sleep, create a copy alarm similar to what would have
// been passed in originally. Otherwise, just return none
stm_sleep_source_t cause = _get_wakeup_cause();
switch (cause) {
case STM_WAKEUP_RTC: {
return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_time_timealarm_create_wakeup_alarm();
}
case STM_WAKEUP_GPIO: {
return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms);
return alarm_pin_pinalarm_create_wakeup_alarm();
}
case STM_WAKEUP_UNDEF:
default:
@ -100,58 +100,51 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) {
return mp_const_none;
}
mp_obj_t common_hal_alarm_get_wake_alarm(void) {
// If we woke from light sleep, override with that alarm
if (most_recent_alarm != NULL) {
return most_recent_alarm;
}
return _get_wake_alarm(0, NULL);
}
// Set up light sleep or deep sleep alarms.
STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) {
alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms);
alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms);
}
STATIC void _idle_until_alarm(void) {
// Poll for alarms.
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
_setup_sleep_alarms(false, n_alarms, alarms);
mp_obj_t wake_alarm = mp_const_none;
// TODO: add more dynamic clock shutdown/restart logic
while (!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
// Detect if interrupt was alarm or ctrl-C interrupt.
if (common_hal_alarm_woken_from_sleep()) {
return;
stm_sleep_source_t cause = _get_wakeup_cause();
switch (cause) {
case STM_WAKEUP_RTC: {
wake_alarm = alarm_time_timealarm_find_triggered_alarm(n_alarms,alarms);
break;
}
case STM_WAKEUP_GPIO: {
wake_alarm = alarm_pin_pinalarm_find_triggered_alarm(n_alarms,alarms);
break;
}
default:
// Should not reach this, if all light sleep types are covered correctly
break;
}
shared_alarm_save_wake_alarm(wake_alarm);
break;
}
// HAL_PWR_EnterSLEEPMode is just a WFI anyway so don't bother
port_idle_until_interrupt();
}
}
mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) {
// If USB is active, only pretend to sleep. Otherwise, light sleep
if (supervisor_workflow_active()) {
_setup_sleep_alarms(false, n_alarms, alarms);
_idle_until_alarm();
} else {
_setup_sleep_alarms(false, n_alarms, alarms);
port_disable_tick();
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
port_enable_tick();
if (mp_hal_is_interrupted()) {
return mp_const_none; // Shouldn't be given to python code because exception handling should kick in.
}
mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms);
// TODO: make assignment to global array less roundabout
most_recent_alarm = wake_alarm;
shared_alarm_save_wake_alarm();
// Can't use alarm_reset since it resets most_recent_alarm
alarm_pin_pinalarm_reset();
alarm_time_timealarm_reset();
alarm_reset();
return wake_alarm;
}
void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) {
most_recent_alarm = NULL;
_setup_sleep_alarms(true, n_alarms, alarms);
}

View File

@ -85,11 +85,11 @@ bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) {
return self->pull;
}
bool alarm_pin_pinalarm_woke_us_up(void) {
bool alarm_pin_pinalarm_woke_this_cycle(void) {
return woke_up;
}
mp_obj_t alarm_pin_pinalarm_get_wakeup_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) {
for (size_t i = 0; i < n_alarms; i++) {
if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) {
continue;
@ -99,8 +99,10 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al
return alarms[i];
}
}
return mp_const_none;
}
// If the above isn't true, we woke from deep sleep, so create a new alarm
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->base.type = &alarm_pin_pinalarm_type;
// TODO: replace this if/when other WKUP pins are supported

View File

@ -37,10 +37,12 @@ typedef struct {
bool pull;
} 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(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_prepare_for_deep_sleep(void);
mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms);
bool alarm_pin_pinalarm_woke_us_up(void);
bool alarm_pin_pinalarm_woke_this_cycle(void);
#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H

View File

@ -44,13 +44,17 @@ mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timeala
return self->monotonic_time;
}
mp_obj_t alarm_time_timealarm_get_wakeup_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) {
// First, check to see if we match
for (size_t i = 0; i < n_alarms; i++) {
if (mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) {
return alarms[i];
}
}
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;
// TODO: Set monotonic_time based on the RTC state.
@ -63,7 +67,7 @@ STATIC void timer_callback(void) {
woke_up = true;
}
bool alarm_time_timealarm_woke_us_up(void) {
bool alarm_time_timealarm_woke_this_cycle(void) {
return woke_up;
}

View File

@ -34,10 +34,11 @@ typedef struct {
mp_float_t monotonic_time; // values compatible with time.monotonic_time()
} alarm_time_timealarm_obj_t;
// Find the alarm object that caused us to wake up or create an equivalent one.
mp_obj_t alarm_time_timealarm_get_wakeup_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);
// Check for the wake up alarm from pretend deep sleep.
bool alarm_time_timealarm_woke_us_up(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);