From f1792c8474e15d006ba39a07e1b7cf5b03e52bac Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Tue, 2 Mar 2021 11:41:53 -0500 Subject: [PATCH 01/16] Extract EXTI, create base sleep framework --- main.c | 8 +- ports/esp32s2/common-hal/alarm/__init__.c | 17 +- ports/esp32s2/common-hal/alarm/__init__.h | 2 +- ports/esp32s2/common-hal/alarm/pin/__init__.c | 35 ---- ports/stm/Makefile | 2 + .../boards/feather_stm32f405_express/board.c | 3 + ports/stm/common-hal/alarm/SleepMemory.c | 46 +++++ ports/stm/common-hal/alarm/SleepMemory.h | 38 +++++ ports/stm/common-hal/alarm/__init__.c | 158 ++++++++++++++++++ ports/stm/common-hal/alarm/__init__.h | 36 ++++ ports/stm/common-hal/alarm/pin/PinAlarm.c | 136 +++++++++++++++ ports/stm/common-hal/alarm/pin/PinAlarm.h | 42 +++++ ports/stm/common-hal/alarm/time/TimeAlarm.c | 78 +++++++++ ports/stm/common-hal/alarm/time/TimeAlarm.h | 40 +++++ ports/stm/common-hal/alarm/touch/TouchAlarm.c | 32 ++++ ports/stm/common-hal/alarm/touch/TouchAlarm.h | 35 ++++ ports/stm/common-hal/pulseio/PulseIn.c | 116 ++++--------- ports/stm/common-hal/pulseio/PulseIn.h | 1 - ports/stm/mpconfigport.mk | 1 + ports/stm/peripherals/exti.c | 134 +++++++++++++++ ports/stm/peripherals/exti.h | 43 +++++ ports/stm/peripherals/rtc.c | 25 +++ ports/stm/peripherals/rtc.h | 25 +++ ports/stm/supervisor/port.c | 7 + shared-bindings/alarm/__init__.c | 2 +- shared-bindings/alarm/__init__.h | 8 +- shared-bindings/alarm/time/TimeAlarm.c | 1 + 27 files changed, 934 insertions(+), 137 deletions(-) delete mode 100644 ports/esp32s2/common-hal/alarm/pin/__init__.c create mode 100644 ports/stm/common-hal/alarm/SleepMemory.c create mode 100644 ports/stm/common-hal/alarm/SleepMemory.h create mode 100644 ports/stm/common-hal/alarm/__init__.c create mode 100644 ports/stm/common-hal/alarm/__init__.h create mode 100644 ports/stm/common-hal/alarm/pin/PinAlarm.c create mode 100644 ports/stm/common-hal/alarm/pin/PinAlarm.h create mode 100644 ports/stm/common-hal/alarm/time/TimeAlarm.c create mode 100644 ports/stm/common-hal/alarm/time/TimeAlarm.h create mode 100644 ports/stm/common-hal/alarm/touch/TouchAlarm.c create mode 100644 ports/stm/common-hal/alarm/touch/TouchAlarm.h create mode 100644 ports/stm/peripherals/exti.c create mode 100644 ports/stm/peripherals/exti.h create mode 100644 ports/stm/peripherals/rtc.c create mode 100644 ports/stm/peripherals/rtc.h diff --git a/main.c b/main.c index 7bfa565df4..1d0f5453f0 100755 --- a/main.c +++ b/main.c @@ -157,9 +157,9 @@ STATIC void start_mp(supervisor_allocation* heap) { #if CIRCUITPY_ALARM // Record which alarm woke us up, if any. An object may be created so the heap must be functional. - alarm_save_wake_alarm(); + common_hal_alarm_save_wake_alarm(); // Reset alarm module only after we retrieved the wakeup alarm. - alarm_reset(); + common_hal_alarm_reset(); #endif #if CIRCUITPY_NETWORK @@ -357,7 +357,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { // an alarm alerts faster than our USB delay or if we pretended to deep // sleep. #if CIRCUITPY_ALARM - if (asleep && alarm_woken_from_sleep()) { + if (asleep && common_hal_alarm_woken_from_sleep()) { serial_write_compressed(translate("Woken up by alarm.\n")); board_init(); supervisor_set_run_reason(RUN_REASON_STARTUP); @@ -409,7 +409,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { if (!supervisor_workflow_active()) { // Enter true deep sleep. When we wake up we'll be back at the // top of main(), not in this loop. - alarm_enter_deep_sleep(); + common_hal_alarm_enter_deep_sleep(); // Does not return. } else { serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n")); diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index be435e2104..c0a2a1a555 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -54,7 +54,7 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { }, }; -void alarm_reset(void) { +void common_hal_alarm_reset(void) { alarm_sleep_memory_reset(); alarm_pin_pinalarm_reset(); alarm_time_timealarm_reset(); @@ -75,10 +75,12 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { return esp_sleep_get_wakeup_cause(); } -bool alarm_woken_from_sleep(void) { +bool common_hal_alarm_woken_from_sleep(void) { return _get_wakeup_cause() != ESP_SLEEP_WAKEUP_UNDEFINED; } +// When called to populate the global dict, the module functions create new alarm objects. +// Otherwise, they scan the existing alarms for matches. STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(); switch (cause) { @@ -104,6 +106,8 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { return mp_const_none; } +// This function is used to create a new alarm object for the global dict after deep sleep, +// rather than finding an existing one during runtime. mp_obj_t common_hal_alarm_get_wake_alarm(void) { return _get_wake_alarm(0, NULL); } @@ -120,8 +124,9 @@ STATIC void _idle_until_alarm(void) { while (!mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; // Allow ctrl-C interrupt. - if (alarm_woken_from_sleep()) { - alarm_save_wake_alarm(); + if (common_hal_alarm_woken_from_sleep()) { + // This saves the return of common_hal_alarm_get_wake_alarm through Shared Bindings + common_hal_alarm_save_wake_alarm(); return; } port_idle_until_interrupt(); @@ -139,7 +144,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj } mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); - alarm_reset(); + alarm_pin_pinalarm_reset_alarms(n_alarms, alarms); return wake_alarm; } @@ -147,7 +152,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN alarm_enter_deep_sleep(void) { +void NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_touch_touchalarm_prepare_for_deep_sleep(); diff --git a/ports/esp32s2/common-hal/alarm/__init__.h b/ports/esp32s2/common-hal/alarm/__init__.h index 0823ff842e..2b46907778 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.h +++ b/ports/esp32s2/common-hal/alarm/__init__.h @@ -31,6 +31,6 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; -extern void alarm_reset(void); +extern void common_hal_alarm_reset(void); #endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM__INIT__H diff --git a/ports/esp32s2/common-hal/alarm/pin/__init__.c b/ports/esp32s2/common-hal/alarm/pin/__init__.c deleted file mode 100644 index b39693c6af..0000000000 --- a/ports/esp32s2/common-hal/alarm/pin/__init__.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "shared-bindings/alarm_io/__init__.h" - -#include "esp_sleep.h" -#include "driver/rtc_io.h" - -mp_obj_t common_hal_alarm_io_pin_state (alarm_io_obj_t *self_in) { - if (!rtc_gpio_is_valid_gpio(self_in->gpio)) { - mp_raise_ValueError(translate("io must be rtc io")); - } - - if (self_in->pull && !self_in->level) { - for (uint8_t i = 0; i<=4; i+=2) { - if (self_in->gpio == i) { - mp_raise_ValueError(translate("IOs 0, 2 & 4 do not support internal pullup in sleep")); - } - } - } - - switch(esp_sleep_enable_ext0_wakeup(self_in->gpio, self_in->level)) { - case ESP_ERR_INVALID_ARG: - mp_raise_ValueError(translate("trigger level must be 0 or 1")); - case ESP_ERR_INVALID_STATE: - mp_raise_RuntimeError(translate("wakeup conflict")); - default: - break; - } - - if (self_in->pull) { (self_in->level) ? rtc_gpio_pulldown_en(self_in->gpio) : rtc_gpio_pullup_en(self_in->gpio); } - - return self_in; -} - -void common_hal_alarm_io_disable (void) { - esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0 | ESP_SLEEP_WAKEUP_EXT1); -} diff --git a/ports/stm/Makefile b/ports/stm/Makefile index e09fe736cc..661beccfed 100755 --- a/ports/stm/Makefile +++ b/ports/stm/Makefile @@ -220,6 +220,8 @@ SRC_C += \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ peripherals/timers.c \ + peripherals/exti.c \ + peripherals/rtc.c \ peripherals/stm32$(MCU_SERIES_LOWER)/clocks.c \ peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/pins.c \ peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \ diff --git a/ports/stm/boards/feather_stm32f405_express/board.c b/ports/stm/boards/feather_stm32f405_express/board.c index f8e462f938..6652c840c6 100644 --- a/ports/stm/boards/feather_stm32f405_express/board.c +++ b/ports/stm/boards/feather_stm32f405_express/board.c @@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) { void reset_board(void) { } + +void board_deinit(void) { +} \ No newline at end of file diff --git a/ports/stm/common-hal/alarm/SleepMemory.c b/ports/stm/common-hal/alarm/SleepMemory.c new file mode 100644 index 0000000000..f1e2772abb --- /dev/null +++ b/ports/stm/common-hal/alarm/SleepMemory.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/runtime.h" +#include "common-hal/alarm/SleepMemory.h" + +void alarm_sleep_memory_reset(void) { + +} + +uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) { + return 0; +} + +bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t* values, uint32_t len) { + return false; +} + +void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t* values, uint32_t len) { + return; +} diff --git a/ports/stm/common-hal/alarm/SleepMemory.h b/ports/stm/common-hal/alarm/SleepMemory.h new file mode 100644 index 0000000000..0e9fc54904 --- /dev/null +++ b/ports/stm/common-hal/alarm/SleepMemory.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H +#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; +} alarm_sleep_memory_obj_t; + +extern void alarm_sleep_memory_reset(void); + +#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_SLEEPMEMORY_H diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c new file mode 100644 index 0000000000..70da36c294 --- /dev/null +++ b/ports/stm/common-hal/alarm/__init__.c @@ -0,0 +1,158 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/gc.h" +#include "py/obj.h" +#include "py/objtuple.h" +#include "py/runtime.h" +#include "lib/utils/interrupt_char.h" + +#include "shared-bindings/alarm/__init__.h" +#include "shared-bindings/alarm/pin/PinAlarm.h" +#include "shared-bindings/alarm/time/TimeAlarm.h" + +#include "shared-bindings/microcontroller/__init__.h" + +#include "supervisor/port.h" +#include "supervisor/shared/workflow.h" + +#define STM_WAKEUP_GPIO 1 +#define STM_WAKEUP_TIMER 2 + +void common_hal_alarm_reset(void) { + // alarm_sleep_memory_reset(); + alarm_pin_pinalarm_reset(); + // alarm_time_timealarm_reset(); + // alarm_touch_touchalarm_reset(); + // esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); +} + +STATIC uint8_t _get_wakeup_cause(void) { + if (alarm_pin_pinalarm_woke_us_up()) { + return STM_WAKEUP_GPIO; + } + if (alarm_time_timealarm_woke_us_up()) { + return STM_WAKEUP_TIMER; + } + return 0; +} + +bool common_hal_alarm_woken_from_sleep(void) { + return _get_wakeup_cause() != 0; +} + +STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { + if (alarm_pin_pinalarm_woke_us_up()) { + return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); + } + // esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(); + // switch (cause) { + // case ESP_SLEEP_WAKEUP_TIMER: { + // return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms); + // } + + // case ESP_SLEEP_WAKEUP_GPIO: + // case ESP_SLEEP_WAKEUP_EXT0: + // case ESP_SLEEP_WAKEUP_EXT1: { + // return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); + // } + + // case ESP_SLEEP_WAKEUP_TOUCHPAD: { + // return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms); + // } + + // case ESP_SLEEP_WAKEUP_UNDEFINED: + // default: + // // Not a deep sleep reset. + // break; + // } + // return mp_const_none; + return mp_const_none; +} + +mp_obj_t common_hal_alarm_get_wake_alarm(void) { + //return _get_wake_alarm(0, NULL); + return mp_const_none; +} + +// 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); + // alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms); +} + +STATIC void _idle_until_alarm(void) { + // Poll for alarms. + while (!mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + // Allow ctrl-C interrupt. + if (common_hal_alarm_woken_from_sleep()) { + common_hal_alarm_save_wake_alarm(); + return; + } + // port_idle_until_interrupt(); + } +} + +mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { + // if (supervisor_workflow_active()) { + // mp_raise_NotImplementedError(translate("Cannot sleep with USB connected")); + // } + _setup_sleep_alarms(false, n_alarms, alarms); + + // If USB is active, only pretend to sleep. Otherwise, light sleep + if (supervisor_workflow_active()) { + _idle_until_alarm(); + } else { + port_disable_tick(); + HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); + port_enable_tick(); + } + + mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); + common_hal_alarm_reset(); + return wake_alarm; +} + +void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) { + _setup_sleep_alarms(true, n_alarms, alarms); +} + +//#define NORETURN __attribute__((noreturn)) +void NORETURN common_hal_alarm_enter_deep_sleep(void) { + // alarm_pin_pinalarm_prepare_for_deep_sleep(); + // alarm_touch_touchalarm_prepare_for_deep_sleep(); + while(1); + + // The ESP-IDF caches the deep sleep settings and applies them before sleep. + // We don't need to worry about resetting them in the interim. + // esp_deep_sleep_start(); +} + +void common_hal_alarm_gc_collect(void) { + gc_collect_ptr(common_hal_alarm_get_wake_alarm()); +} diff --git a/ports/stm/common-hal/alarm/__init__.h b/ports/stm/common-hal/alarm/__init__.h new file mode 100644 index 0000000000..18defefc0b --- /dev/null +++ b/ports/stm/common-hal/alarm/__init__.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H +#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H + +#include "common-hal/alarm/SleepMemory.h" + +const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; + +extern void common_hal_alarm_reset(void); + +#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c new file mode 100644 index 0000000000..aecc3a0e22 --- /dev/null +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -0,0 +1,136 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" + +#include "shared-bindings/alarm/pin/PinAlarm.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "peripherals/exti.h" + +STATIC bool woke_up; + +STATIC uint16_t alarm_pin_triggered; + +STATIC void pin_alarm_callback(uint8_t num) { + alarm_pin_triggered |= (1 << num); + woke_up = true; + HAL_GPIO_EXTI_IRQHandler(pin_mask(num)); +} + +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { + if (!edge) { + mp_raise_NotImplementedError(translate("Only edge detection is available on this hardware")); + } + if (!stm_peripherals_exti_is_free(pin->number)) { + mp_raise_RuntimeError(translate("Pin interrupt already in use")); + } + stm_peripherals_exti_reserve(pin->number); + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = pin_mask(pin->number); + GPIO_InitStruct.Mode = value ? GPIO_MODE_IT_RISING : GPIO_MODE_IT_FALLING; + // Pull is automatically set to oppose value. + // TODO: match digitalIO API instead? + if (value) { + GPIO_InitStruct.Pull = pull ? GPIO_PULLDOWN : GPIO_NOPULL; + } else { + GPIO_InitStruct.Pull = pull ? GPIO_PULLUP : GPIO_NOPULL; + } + HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); + + stm_peripherals_exti_set_callback(pin_alarm_callback,pin->number); + + self->pin = pin; + self->value = value; + self->pull = pull; +} + +mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { + return self->pin; +} + +bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self) { + return self->value; +} + +bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self) { + return true; +} + +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) { + return woke_up; +} + +mp_obj_t alarm_pin_pinalarm_get_wakeup_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; + } + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + if (alarm_pin_triggered & (1 << alarm->pin->number)) { + return alarms[i]; + } + } + + // Placeholder for deep sleep + alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); + alarm->base.type = &alarm_pin_pinalarm_type; + alarm->pin = NULL; + return alarm; +} + +void alarm_pin_pinalarm_reset(void) { + alarm_pin_triggered = 0; + woke_up = false; +} + +void alarm_pin_pinalarm_set_alarms(bool deep_sleep, 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)) { + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + stm_peripherals_exti_enable(alarm->pin->number); + } + } +} + +void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { + alarm_pin_triggered = 0; + for (size_t i = 0; i < n_alarms; i++) { + if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + stm_peripherals_exti_disable(alarm->pin->number); + } + } +} + +void alarm_pin_pinalarm_prepare_for_deep_sleep(void) { + +} diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.h b/ports/stm/common-hal/alarm/pin/PinAlarm.h new file mode 100644 index 0000000000..b26930b103 --- /dev/null +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/objtuple.h" + +typedef struct { + mp_obj_base_t base; + mcu_pin_obj_t *pin; + bool value; + bool pull; +} alarm_pin_pinalarm_obj_t; + +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_reset_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); diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c new file mode 100644 index 0000000000..f9ceefdb40 --- /dev/null +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -0,0 +1,78 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" + +#include "shared-bindings/alarm/time/TimeAlarm.h" +#include "shared-bindings/time/__init__.h" + +void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) { + self->monotonic_time = monotonic_time; +} + +mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timealarm_obj_t *self) { + 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 +// for (size_t i = 0; i < n_alarms; i++) { +// if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { +// return alarms[i]; +// } +// } +// 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. +// timer->monotonic_time = 0.0f; +// return timer; +// } + +// This is run in the timer task. We use it to wake the main CircuitPython task. +// void timer_callback(void *arg) { +// (void) arg; +// woke_up = true; +// xTaskNotifyGive(circuitpython_task); +// } + +bool alarm_time_timealarm_woke_us_up(void) { + // return woke_up; + return false; +} + +// void alarm_time_timealarm_reset(void) { +// esp_timer_stop(pretend_sleep_timer); +// esp_timer_delete(pretend_sleep_timer); +// pretend_sleep_timer = NULL; +// woke_up = false; +// } + +void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { + // HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16); + // HAL_RTCEx_SetWakeUpTimer_IT(&_hrtc, rtc_clock_frequency / 1024 / 2, RTC_WAKEUPCLOCK_RTCCLK_DIV2); + // HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 1, 0U); + // HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn); +} diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.h b/ports/stm/common-hal/alarm/time/TimeAlarm.h new file mode 100644 index 0000000000..af786d81b0 --- /dev/null +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + 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); +// // Check for the wake up alarm from pretend deep sleep. +bool alarm_time_timealarm_woke_us_up(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); diff --git a/ports/stm/common-hal/alarm/touch/TouchAlarm.c b/ports/stm/common-hal/alarm/touch/TouchAlarm.c new file mode 100644 index 0000000000..88c73726ee --- /dev/null +++ b/ports/stm/common-hal/alarm/touch/TouchAlarm.c @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/alarm/touch/TouchAlarm.h" +#include "shared-bindings/microcontroller/__init__.h" + +void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { + mp_raise_NotImplementedError(translate("Touch alarms not available")); +} diff --git a/ports/stm/common-hal/alarm/touch/TouchAlarm.h b/ports/stm/common-hal/alarm/touch/TouchAlarm.h new file mode 100644 index 0000000000..6c89353f93 --- /dev/null +++ b/ports/stm/common-hal/alarm/touch/TouchAlarm.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H +#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; +} alarm_touch_touchalarm_obj_t; + +#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TOUCHALARM_H diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c index 015ee8536d..c030e8255b 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.c +++ b/ports/stm/common-hal/pulseio/PulseIn.c @@ -35,17 +35,17 @@ #include "shared-bindings/pulseio/PulseIn.h" #include "timers.h" +#include "peripherals/exti.h" + #include STM32_HAL_H #define STM32_GPIO_PORT_SIZE 16 -static pulseio_pulsein_obj_t* _objs[STM32_GPIO_PORT_SIZE]; +STATIC pulseio_pulsein_obj_t* callback_obj_ref[STM32_GPIO_PORT_SIZE]; STATIC TIM_HandleTypeDef tim_handle; -static uint32_t overflow_count = 0; +STATIC uint32_t overflow_count = 0; STATIC uint8_t refcount = 0; -static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num); - void pulsein_timer_event_handler(void) { // Detect TIM Update event @@ -59,7 +59,7 @@ void pulsein_timer_event_handler(void) } } -static void pulsein_exti_event_handler(uint8_t num) { +STATIC void pulsein_exti_event_handler(uint8_t num) { // Grab the current time first. uint32_t current_overflow = overflow_count; uint32_t current_count = tim_handle.Instance->CNT; @@ -67,7 +67,7 @@ static void pulsein_exti_event_handler(uint8_t num) { // Interrupt register must be cleared manually EXTI->PR = 1 << num; - pulseio_pulsein_obj_t* self = _objs[num]; + pulseio_pulsein_obj_t* self = callback_obj_ref[num]; if ( !self ) return; if (self->first_edge) { @@ -97,11 +97,11 @@ static void pulsein_exti_event_handler(uint8_t num) { void pulsein_reset(void) { // Disable all active interrupts and clear array for (uint i = 0; i < STM32_GPIO_PORT_SIZE; i++) { - if (_objs[i] != NULL) { - HAL_NVIC_DisableIRQ(_objs[i]->irq); + if (callback_obj_ref[i] != NULL) { + stm_peripherals_exti_disable(callback_obj_ref[i]->pin->number); } } - memset(_objs, 0, sizeof(_objs)); + memset(callback_obj_ref, 0, sizeof(callback_obj_ref)); HAL_TIM_Base_DeInit(&tim_handle); tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance)); @@ -112,15 +112,14 @@ void pulsein_reset(void) { void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin, uint16_t maxlen, bool idle_state) { // STM32 has one shared EXTI for each pin number, 0-15 - uint8_t p_num = pin->number; - if(_objs[p_num]) { - mp_raise_ValueError(translate("Pin number already reserved by EXTI")); + if (!stm_peripherals_exti_is_free(pin->number)) { + mp_raise_RuntimeError(translate("Pin interrupt already in use")); } - _objs[p_num] = self; // Allocate pulse buffer self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false); if (self->buffer == NULL) { + //TODO: free the EXTI here? mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), maxlen * sizeof(uint16_t)); } @@ -165,16 +164,21 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu // Add to active PulseIns refcount++; - // EXTI pins can also be read as an input + if (!stm_peripherals_exti_reserve(pin->number)) { + mp_raise_RuntimeError(translate("Pin interrupt already in use")); + } GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = pin_mask(pin->number); GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); + stm_peripherals_exti_set_callback(pulsein_exti_event_handler, pin->number); + // Store PulseIn object for use in callback + callback_obj_ref[pin->number] = self; // Interrupt starts immediately - assign_EXTI_Interrupt(self, pin->number); - HAL_NVIC_EnableIRQ(self->irq); + stm_peripherals_exti_enable(pin->number); + common_hal_mcu_pin_claim(pin); } @@ -187,7 +191,8 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) { return; } //Remove pulsein slot from shared array - _objs[self->pin->number] = NULL; + callback_obj_ref[self->pin->number] = NULL; + stm_peripherals_exti_free(self->pin->number); reset_pin_number(self->pin->port, self->pin->number); self->pin = NULL; @@ -198,7 +203,7 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) { } void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) { - HAL_NVIC_DisableIRQ(self->irq); + stm_peripherals_exti_disable(self->pin->number); self->paused = true; } @@ -232,27 +237,27 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t tri self->last_count = 0; self->last_overflow = 0; - HAL_NVIC_EnableIRQ(self->irq); + stm_peripherals_exti_enable(self->pin->number); } void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) { - HAL_NVIC_DisableIRQ(self->irq); + stm_peripherals_exti_disable(self->pin->number); self->start = 0; self->len = 0; - HAL_NVIC_EnableIRQ(self->irq); + stm_peripherals_exti_enable(self->pin->number); } uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) { - HAL_NVIC_DisableIRQ(self->irq); + stm_peripherals_exti_disable(self->pin->number); if (index < 0) { index += self->len; } if (index < 0 || index >= self->len) { - HAL_NVIC_EnableIRQ(self->irq); + stm_peripherals_exti_enable(self->pin->number); mp_raise_IndexError_varg(translate("%q index out of range"), MP_QSTR_PulseIn); } uint16_t value = self->buffer[(self->start + index) % self->maxlen]; - HAL_NVIC_EnableIRQ(self->irq); + stm_peripherals_exti_enable(self->pin->number); return value; } @@ -260,11 +265,11 @@ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) { if (self->len == 0) { mp_raise_IndexError_varg(translate("pop from empty %q"), MP_QSTR_PulseIn); } - HAL_NVIC_DisableIRQ(self->irq); + stm_peripherals_exti_disable(self->pin->number); uint16_t value = self->buffer[self->start]; self->start = (self->start + 1) % self->maxlen; self->len--; - HAL_NVIC_EnableIRQ(self->irq); + stm_peripherals_exti_enable(self->pin->number); return value; } @@ -280,62 +285,3 @@ bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) { uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) { return self->len; } - -static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num) { - if (num == 0) { - self->irq = EXTI0_IRQn; - } else if (num == 1) { - self->irq = EXTI1_IRQn; - } else if (num == 2) { - self->irq = EXTI2_IRQn; - } else if (num == 3) { - self->irq = EXTI3_IRQn; - } else if (num == 4) { - self->irq = EXTI4_IRQn; - } else if (num >= 5 && num <= 9 ) { - self->irq = EXTI9_5_IRQn; - } else if (num >= 10 && num <= 15) { - self->irq = EXTI15_10_IRQn; - } -} - -void EXTI0_IRQHandler(void) -{ - pulsein_exti_event_handler(0); -} -void EXTI1_IRQHandler(void) -{ - pulsein_exti_event_handler(1); -} -void EXTI2_IRQHandler(void) -{ - pulsein_exti_event_handler(2); -} -void EXTI3_IRQHandler(void) -{ - pulsein_exti_event_handler(3); -} -void EXTI4_IRQHandler(void) -{ - pulsein_exti_event_handler(4); -} - -void EXTI9_5_IRQHandler(void) -{ - uint32_t pending = EXTI->PR; - for (uint i = 5; i <= 9; i++) { - if(pending & (1 << i)) { - pulsein_exti_event_handler(i); - } - } -} - -void EXTI15_10_IRQHandler(void) -{ - uint32_t pending = EXTI->PR; - for (uint i = 10; i <= 15; i++) { - if(pending & (1 << i)) { - pulsein_exti_event_handler(i); - } - } -} diff --git a/ports/stm/common-hal/pulseio/PulseIn.h b/ports/stm/common-hal/pulseio/PulseIn.h index 34d0cc731a..a3454bb540 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.h +++ b/ports/stm/common-hal/pulseio/PulseIn.h @@ -35,7 +35,6 @@ typedef struct { mp_obj_base_t base; const mcu_pin_obj_t* pin; - IRQn_Type irq; bool idle_state; bool paused; volatile bool first_edge; diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index bcecaa5170..86cd3c009a 100644 --- a/ports/stm/mpconfigport.mk +++ b/ports/stm/mpconfigport.mk @@ -4,6 +4,7 @@ INTERNAL_LIBM ?= 1 USB_SERIAL_NUMBER_LENGTH ?= 24 ifeq ($(MCU_VARIANT),STM32F405xx) + CIRCUITPY_ALARM = 1 CIRCUITPY_CANIO = 1 CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_RGBMATRIX ?= 1 diff --git a/ports/stm/peripherals/exti.c b/ports/stm/peripherals/exti.c new file mode 100644 index 0000000000..c0b3a750ad --- /dev/null +++ b/ports/stm/peripherals/exti.c @@ -0,0 +1,134 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include "py/mpconfig.h" +#include "py/gc.h" +#include "py/obj.h" +#include "py/runtime.h" + +#include "peripherals/exti.h" + + +STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE]; +STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num); + +void exti_reset(void) { + for (size_t i = 0;i < STM32_GPIO_PORT_SIZE; i++) { + stm_exti_reserved[i] = false; + stm_exti_callback[i] = NULL; + stm_peripherals_exti_disable(i); + } +} + +bool stm_peripherals_exti_is_free(uint8_t num) { + return !stm_exti_reserved[num]; +} + +bool stm_peripherals_exti_reserve(uint8_t num) { + if (!stm_peripherals_exti_is_free(num)) { + return false; + } + stm_exti_reserved[num] = true; + return true; +} + +void stm_peripherals_exti_enable(uint8_t num) { + HAL_NVIC_EnableIRQ(stm_peripherals_exti_get_irq(num)); +} + +void stm_peripherals_exti_disable(uint8_t num) { + HAL_NVIC_DisableIRQ(stm_peripherals_exti_get_irq(num)); +} + +void stm_peripherals_exti_set_callback(void(*callback)(uint8_t num), uint8_t number) { + stm_exti_callback[number] = callback; +} + +void stm_peripherals_exti_free(uint8_t num) { + stm_exti_reserved[num] = true; +} + +IRQn_Type stm_peripherals_exti_get_irq(uint8_t num) { + if (num == 0) { + return EXTI0_IRQn; + } else if (num == 1) { + return EXTI1_IRQn; + } else if (num == 2) { + return EXTI2_IRQn; + } else if (num == 3) { + return EXTI3_IRQn; + } else if (num == 4) { + return EXTI4_IRQn; + } else if (num >= 5 && num <= 9 ) { + return EXTI9_5_IRQn; + } else if (num >= 10 && num <= 15) { + return EXTI15_10_IRQn; + } else { + return 0; + } +} + +void EXTI0_IRQHandler(void) +{ + stm_exti_callback[0](0); +} +void EXTI1_IRQHandler(void) +{ + stm_exti_callback[1](1); +} +void EXTI2_IRQHandler(void) +{ + stm_exti_callback[2](2); +} +void EXTI3_IRQHandler(void) +{ + stm_exti_callback[3](3); +} +void EXTI4_IRQHandler(void) +{ + stm_exti_callback[4](4); +} + +void EXTI9_5_IRQHandler(void) +{ + uint32_t pending = EXTI->PR; + for (uint i = 5; i <= 9; i++) { + if(pending & (1 << i)) { + stm_exti_callback[i](i); + } + } +} + +void EXTI15_10_IRQHandler(void) +{ + uint32_t pending = EXTI->PR; + for (uint i = 10; i <= 15; i++) { + if(pending & (1 << i)) { + stm_exti_callback[i](i); + } + } +} diff --git a/ports/stm/peripherals/exti.h b/ports/stm/peripherals/exti.h new file mode 100644 index 0000000000..15e2207c9c --- /dev/null +++ b/ports/stm/peripherals/exti.h @@ -0,0 +1,43 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__ +#define __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__ + +#include STM32_HAL_H + +#define STM32_GPIO_PORT_SIZE 16 + +void exti_reset(void); +bool stm_peripherals_exti_is_free(uint8_t num); +bool stm_peripherals_exti_reserve(uint8_t num); +void stm_peripherals_exti_enable(uint8_t num); +void stm_peripherals_exti_disable(uint8_t num); +void stm_peripherals_exti_set_callback(void(*callback)(uint8_t num), uint8_t number); +void stm_peripherals_exti_free(uint8_t num); +IRQn_Type stm_peripherals_exti_get_irq(uint8_t num); + +#endif // __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__ \ No newline at end of file diff --git a/ports/stm/peripherals/rtc.c b/ports/stm/peripherals/rtc.c new file mode 100644 index 0000000000..72336f0314 --- /dev/null +++ b/ports/stm/peripherals/rtc.c @@ -0,0 +1,25 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ \ No newline at end of file diff --git a/ports/stm/peripherals/rtc.h b/ports/stm/peripherals/rtc.h new file mode 100644 index 0000000000..72336f0314 --- /dev/null +++ b/ports/stm/peripherals/rtc.h @@ -0,0 +1,25 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ \ No newline at end of file diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 3103a07160..afbe333e38 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -50,6 +50,9 @@ #if CIRCUITPY_SDIOIO #include "common-hal/sdioio/SDCard.h" #endif +#if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM +#include "exti.h" +#endif #include "clocks.h" #include "gpio.h" @@ -247,6 +250,9 @@ void reset_port(void) { #if CIRCUITPY_PWMIO pwmout_reset(); #endif +#if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM + exti_reset(); +#endif } void reset_to_bootloader(void) { @@ -380,6 +386,7 @@ void RTC_WKUP_IRQHandler(void) { supervisor_tick(); __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&_hrtc, RTC_FLAG_WUTF); __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); + _hrtc.State = HAL_RTC_STATE_READY; } volatile bool alarmed_already = false; diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 7023c70e5d..7be629d52b 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -228,7 +228,7 @@ mp_obj_t alarm_get_wake_alarm(void) { } // Initialize .wake_alarm value. -void alarm_save_wake_alarm(void) { +void common_hal_alarm_save_wake_alarm(void) { // Equivalent of: // alarm.wake_alarm = alarm mp_map_elem_t *elem = diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index 154f91e265..12ee0f1aad 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -41,20 +41,20 @@ extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const // it will exit idle as if deep sleep was exited. extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms); // Deep sleep is entered outside of the VM so we omit the `common_hal_` prefix. -extern NORETURN void alarm_enter_deep_sleep(void); +extern NORETURN void common_hal_alarm_enter_deep_sleep(void); // Fetches value from module dict. -extern mp_obj_t alarm_get_wake_alarm(void); +extern mp_obj_t common_hal_alarm_get_wake_alarm(void); extern void common_hal_alarm_gc_collect(void); extern mp_obj_t common_hal_alarm_get_wake_alarm(void); // Used by wake-up code. -void alarm_save_wake_alarm(void); +void common_hal_alarm_save_wake_alarm(void); // True if an alarm is alerting. This is most useful for pretend deep sleep. -extern bool alarm_woken_from_sleep(void); +extern bool common_hal_alarm_woken_from_sleep(void); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H diff --git a/shared-bindings/alarm/time/TimeAlarm.c b/shared-bindings/alarm/time/TimeAlarm.c index 1c9b8d37c5..1ce805ba6b 100644 --- a/shared-bindings/alarm/time/TimeAlarm.c +++ b/shared-bindings/alarm/time/TimeAlarm.c @@ -58,6 +58,7 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) { //| STATIC mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + alarm_time_timealarm_obj_t *self = m_new_obj(alarm_time_timealarm_obj_t); self->base.type = &alarm_time_timealarm_type; From 6b2c9985ff7f7c4454550d6addcdb8e26e9a7134 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Thu, 11 Mar 2021 17:50:05 -0500 Subject: [PATCH 02/16] Extract RTC, implement fake RTC deepsleep --- main.c | 4 +- ports/esp32s2/common-hal/alarm/__init__.c | 2 +- ports/stm/common-hal/alarm/__init__.c | 29 +-- ports/stm/common-hal/alarm/pin/PinAlarm.c | 24 ++- ports/stm/common-hal/alarm/time/TimeAlarm.c | 81 +++++--- ports/stm/common-hal/alarm/time/TimeAlarm.h | 10 +- ports/stm/peripherals/exti.c | 1 - ports/stm/peripherals/rtc.c | 201 +++++++++++++++++++- ports/stm/peripherals/rtc.h | 27 ++- ports/stm/supervisor/port.c | 142 ++------------ shared-bindings/alarm/__init__.c | 2 +- shared-bindings/alarm/__init__.h | 2 +- 12 files changed, 338 insertions(+), 187 deletions(-) diff --git a/main.c b/main.c index 1d0f5453f0..c7a5afabcb 100755 --- a/main.c +++ b/main.c @@ -157,7 +157,7 @@ STATIC void start_mp(supervisor_allocation* heap) { #if CIRCUITPY_ALARM // Record which alarm woke us up, if any. An object may be created so the heap must be functional. - common_hal_alarm_save_wake_alarm(); + shared_alarm_save_wake_alarm(); // Reset alarm module only after we retrieved the wakeup alarm. common_hal_alarm_reset(); #endif @@ -301,8 +301,6 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { } #endif - // TODO: on deep sleep, make sure display is refreshed before sleeping (for e-ink). - cleanup_after_vm(heap); if (result.return_code & PYEXEC_FORCED_EXIT) { diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index c0a2a1a555..ffc6495ad4 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -126,7 +126,7 @@ STATIC void _idle_until_alarm(void) { // Allow ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { // This saves the return of common_hal_alarm_get_wake_alarm through Shared Bindings - common_hal_alarm_save_wake_alarm(); + shared_alarm_save_wake_alarm(); return; } port_idle_until_interrupt(); diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 70da36c294..96dac9323a 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -45,7 +45,7 @@ void common_hal_alarm_reset(void) { // alarm_sleep_memory_reset(); alarm_pin_pinalarm_reset(); - // alarm_time_timealarm_reset(); + alarm_time_timealarm_reset(); // alarm_touch_touchalarm_reset(); // esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } @@ -101,7 +101,7 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) { // 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); + alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms); // alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms); } @@ -111,23 +111,20 @@ STATIC void _idle_until_alarm(void) { RUN_BACKGROUND_TASKS; // Allow ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { - common_hal_alarm_save_wake_alarm(); + shared_alarm_save_wake_alarm(); return; } - // port_idle_until_interrupt(); + port_idle_until_interrupt(); } } mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { - // if (supervisor_workflow_active()) { - // mp_raise_NotImplementedError(translate("Cannot sleep with USB connected")); - // } - _setup_sleep_alarms(false, n_alarms, 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(); @@ -144,13 +141,17 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala //#define NORETURN __attribute__((noreturn)) void NORETURN common_hal_alarm_enter_deep_sleep(void) { - // alarm_pin_pinalarm_prepare_for_deep_sleep(); + alarm_pin_pinalarm_prepare_for_deep_sleep(); + //port_disable_tick(); // alarm_touch_touchalarm_prepare_for_deep_sleep(); - while(1); + // HAL_PWR_EnableBkUpAccess(); + // __HAL_RCC_BACKUPRESET_FORCE(); + // __HAL_RCC_BACKUPRESET_RELEASE(); - // The ESP-IDF caches the deep sleep settings and applies them before sleep. - // We don't need to worry about resetting them in the interim. - // esp_deep_sleep_start(); + HAL_PWR_EnterSTANDBYMode(); + + // Should never hit this + while(1); } void common_hal_alarm_gc_collect(void) { diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c index aecc3a0e22..9d6423d859 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.c +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -35,6 +35,7 @@ STATIC bool woke_up; STATIC uint16_t alarm_pin_triggered; +STATIC bool deep_wkup_enabled; STATIC void pin_alarm_callback(uint8_t num) { alarm_pin_triggered |= (1 << num); @@ -112,17 +113,32 @@ void alarm_pin_pinalarm_reset(void) { woke_up = false; } +// Deep sleep alarms don't actually make use of EXTI, but we pretend they're the same. void alarm_pin_pinalarm_set_alarms(bool deep_sleep, 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)) { alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); - stm_peripherals_exti_enable(alarm->pin->number); + + if (deep_sleep) { + // Deep sleep only wakes on a rising edge from one pin, WKUP (PA00) + if (alarm->pin != &pin_PA00) { + mp_raise_ValueError(translate("Only the WKUP pin can be used to wake from Deep Sleep")); + } + HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); + HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); + + deep_wkup_enabled = true; + } else { + stm_peripherals_exti_enable(alarm->pin->number); + } } } } void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { alarm_pin_triggered = 0; + deep_wkup_enabled = false; for (size_t i = 0; i < n_alarms; i++) { if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); @@ -131,6 +147,10 @@ void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_ } } +// If we don't have WKUP enabled, ensure it's disabled +// TODO; is this really required? void alarm_pin_pinalarm_prepare_for_deep_sleep(void) { - + if (!deep_wkup_enabled) { + HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); + } } diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c index f9ceefdb40..19d96e69c4 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.c +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -28,6 +28,10 @@ #include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/time/__init__.h" +#include "supervisor/port.h" +#include "peripherals/rtc.h" + +STATIC volatile bool woke_up; void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) { self->monotonic_time = monotonic_time; @@ -37,42 +41,59 @@ 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 -// for (size_t i = 0; i < n_alarms; i++) { -// if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { -// return alarms[i]; -// } -// } -// 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. -// timer->monotonic_time = 0.0f; -// return timer; -// } +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 + for (size_t i = 0; i < n_alarms; i++) { + if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { + return alarms[i]; + } + } + 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. + timer->monotonic_time = 0.0f; + return timer; +} // This is run in the timer task. We use it to wake the main CircuitPython task. -// void timer_callback(void *arg) { -// (void) arg; -// woke_up = true; -// xTaskNotifyGive(circuitpython_task); -// } +STATIC void timer_callback(void) { + woke_up = true; +} bool alarm_time_timealarm_woke_us_up(void) { - // return woke_up; - return false; + //mp_printf(&mp_plat_print,"Woke Up:%d\n",woke_up); + return woke_up; } -// void alarm_time_timealarm_reset(void) { -// esp_timer_stop(pretend_sleep_timer); -// esp_timer_delete(pretend_sleep_timer); -// pretend_sleep_timer = NULL; -// woke_up = false; -// } +void alarm_time_timealarm_reset(void) { + // mp_printf(&mp_plat_print,"timealarm reset"); + woke_up = false; +} void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { - // HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16); - // HAL_RTCEx_SetWakeUpTimer_IT(&_hrtc, rtc_clock_frequency / 1024 / 2, RTC_WAKEUPCLOCK_RTCCLK_DIV2); - // HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 1, 0U); - // HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn); + // Search through alarms for TimeAlarm instances, and check that there's only one + bool timealarm_set = false; + alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL; + for (size_t i = 0; i < n_alarms; i++) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { + continue; + } + if (timealarm_set) { + mp_raise_ValueError(translate("Only one alarm.time alarm can be set.")); + } + timealarm = MP_OBJ_TO_PTR(alarms[i]); + timealarm_set = true; + } + if (!timealarm_set) { + return; + } + + // Compute how long to actually sleep, considering the time now. + mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f; + uint32_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs); + uint32_t wakeup_in_ticks = wakeup_in_secs * 1024; + + // Use alarm B, since port reserves A + stm32_peripherals_rtc_assign_alarm_callback(PERIPHERALS_ALARM_B,timer_callback); + stm32_peripherals_rtc_set_alarm(PERIPHERALS_ALARM_B,wakeup_in_ticks); } diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.h b/ports/stm/common-hal/alarm/time/TimeAlarm.h index af786d81b0..d4041dc0ae 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.h +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.h @@ -32,9 +32,9 @@ 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); -// // Check for the wake up alarm from pretend deep sleep. +// 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); +// Check for the wake up alarm from pretend deep sleep. bool alarm_time_timealarm_woke_us_up(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_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); +void alarm_time_timealarm_reset(void); diff --git a/ports/stm/peripherals/exti.c b/ports/stm/peripherals/exti.c index c0b3a750ad..26e7195671 100644 --- a/ports/stm/peripherals/exti.c +++ b/ports/stm/peripherals/exti.c @@ -32,7 +32,6 @@ #include "peripherals/exti.h" - STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE]; STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num); diff --git a/ports/stm/peripherals/rtc.c b/ports/stm/peripherals/rtc.c index 72336f0314..3453ec4747 100644 --- a/ports/stm/peripherals/rtc.c +++ b/ports/stm/peripherals/rtc.c @@ -22,4 +22,203 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - */ \ No newline at end of file + */ + +#include "peripherals/rtc.h" +#include STM32_HAL_H + +#include "py/mpconfig.h" +#include "py/gc.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "lib/timeutils/timeutils.h" + +// Default period for ticks is 1/1024 second +#define TICK_DIVISOR 1024 + +STATIC RTC_HandleTypeDef hrtc; + +#if BOARD_HAS_LOW_SPEED_CRYSTAL +STATIC uint32_t rtc_clock_frequency = LSE_VALUE; +#else +STATIC uint32_t rtc_clock_frequency = LSI_VALUE; +#endif + +volatile uint32_t seconds_to_date = 0; +volatile uint32_t cached_date = 0; +volatile uint32_t seconds_to_minute = 0; +volatile uint32_t cached_hours_minutes = 0; + +volatile bool alarmed_already[2]; + +bool peripherals_wkup_on = false; + +static void (*wkup_callback)(void); +static void(*alarm_callbacks[2])(void); + +uint32_t stm32_peripherals_get_rtc_freq(void) { + return rtc_clock_frequency; +} + +void stm32_peripherals_rtc_init(void) { + // RTC oscillator selection is handled in peripherals///clocks.c + __HAL_RCC_RTC_ENABLE(); + hrtc.Instance = RTC; + hrtc.Init.HourFormat = RTC_HOURFORMAT_24; + // Divide async as little as possible so that we have rtc_clock_frequency count in subseconds. + // This ensures our timing > 1 second is correct. + hrtc.Init.AsynchPrediv = 0x0; + hrtc.Init.SynchPrediv = rtc_clock_frequency - 1; + hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; + + HAL_RTC_Init(&hrtc); + HAL_RTCEx_EnableBypassShadow(&hrtc); + HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); +} + +// This function is called often for timing so we cache the seconds elapsed computation based on the +// register value. The STM HAL always does shifts and conversion if we use it directly. +uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t* subticks) { + // Disable IRQs to ensure we read all of the RTC registers as close in time as possible. Read + // SSR twice to make sure we didn't read across a tick. + __disable_irq(); + uint32_t first_ssr = (uint32_t)(RTC->SSR); + uint32_t time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); + uint32_t date = (uint32_t)(RTC->DR & RTC_DR_RESERVED_MASK); + uint32_t ssr = (uint32_t)(RTC->SSR); + while (ssr != first_ssr) { + first_ssr = ssr; + time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); + date = (uint32_t)(RTC->DR & RTC_DR_RESERVED_MASK); + ssr = (uint32_t)(RTC->SSR); + } + __enable_irq(); + + uint32_t subseconds = rtc_clock_frequency - 1 - ssr; + + if (date != cached_date) { + uint32_t year = (uint8_t)((date & (RTC_DR_YT | RTC_DR_YU)) >> 16U); + uint8_t month = (uint8_t)((date & (RTC_DR_MT | RTC_DR_MU)) >> 8U); + uint8_t day = (uint8_t)(date & (RTC_DR_DT | RTC_DR_DU)); + // Add 2000 since the year is only the last two digits. + year = 2000 + (uint32_t)RTC_Bcd2ToByte(year); + month = (uint8_t)RTC_Bcd2ToByte(month); + day = (uint8_t)RTC_Bcd2ToByte(day); + seconds_to_date = timeutils_seconds_since_2000(year, month, day, 0, 0, 0); + cached_date = date; + } + uint32_t hours_minutes = time & (RTC_TR_HT | RTC_TR_HU | RTC_TR_MNT | RTC_TR_MNU); + if (hours_minutes != cached_hours_minutes) { + uint8_t hours = (uint8_t)((time & (RTC_TR_HT | RTC_TR_HU)) >> 16U); + uint8_t minutes = (uint8_t)((time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8U); + hours = (uint8_t)RTC_Bcd2ToByte(hours); + minutes = (uint8_t)RTC_Bcd2ToByte(minutes); + seconds_to_minute = 60 * (60 * hours + minutes); + cached_hours_minutes = hours_minutes; + } + uint8_t seconds = (uint8_t)(time & (RTC_TR_ST | RTC_TR_SU)); + seconds = (uint8_t)RTC_Bcd2ToByte(seconds); + if (subticks != NULL) { + *subticks = subseconds % 32; + } + + uint64_t raw_ticks = ((uint64_t) TICK_DIVISOR) * (seconds_to_date + seconds_to_minute + seconds) + subseconds / 32; + return raw_ticks; +} + +void stm32_peripherals_rtc_assign_wkup_callback(void(*callback)(void)) { + wkup_callback = callback; +} + +void stm32_peripherals_rtc_set_wakeup_mode_seconds(uint32_t seconds) { + //prep stuff from CubeMX + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); + + HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, (rtc_clock_frequency / 16) * seconds, RTC_WAKEUPCLOCK_RTCCLK_DIV16); +} + +void stm32_peripherals_rtc_set_wakeup_mode_tick(void) { + HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, (rtc_clock_frequency / 16) / TICK_DIVISOR, RTC_WAKEUPCLOCK_RTCCLK_DIV2); +} + +void stm32_peripherals_rtc_enable_wakeup_timer(void) { + peripherals_wkup_on = true; + HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 1, 0U); + HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn); +} + +void stm32_peripherals_rtc_disable_wakeup_timer(void) { + peripherals_wkup_on = false; + HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn); + HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); +} + +void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) { + alarm_callbacks[alarm_idx] = callback; +} + +void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks) { + uint64_t raw_ticks = stm32_peripherals_rtc_raw_ticks(NULL) + ticks; + + RTC_AlarmTypeDef alarm; + if (ticks > TICK_DIVISOR) { + timeutils_struct_time_t tm; + timeutils_seconds_since_2000_to_struct_time(raw_ticks / TICK_DIVISOR, &tm); + alarm.AlarmTime.Hours = tm.tm_hour; + alarm.AlarmTime.Minutes = tm.tm_min; + alarm.AlarmTime.Seconds = tm.tm_sec; + alarm.AlarmDateWeekDay = tm.tm_mday; + // Masking here means that the value is ignored so we set none. + alarm.AlarmMask = RTC_ALARMMASK_NONE; + } else { + // Masking here means that the value is ignored so we set them all. Only the subseconds + // value matters. + alarm.AlarmMask = RTC_ALARMMASK_ALL; + } + + alarm.AlarmTime.SubSeconds = rtc_clock_frequency - 1 - + ((raw_ticks % TICK_DIVISOR) * 32); + alarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; + alarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_SET; + // Masking here means that the bits are ignored so we set none of them. + alarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE; + alarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; + alarm.Alarm = (alarm_idx == PERIPHERALS_ALARM_A) ? RTC_ALARM_A : RTC_ALARM_B; + + HAL_RTC_SetAlarm_IT(&hrtc, &alarm, RTC_FORMAT_BIN); + alarmed_already[alarm_idx] = false; +} + +bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx) { + return alarmed_already[alarm_idx]; +} + +void RTC_WKUP_IRQHandler(void) { + if (wkup_callback) { + wkup_callback(); + } + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); + __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); + hrtc.State = HAL_RTC_STATE_READY; +} + +void RTC_Alarm_IRQHandler(void) { + HAL_RTC_AlarmIRQHandler(&hrtc); +} + +void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *_hrtc) { + if (alarm_callbacks[PERIPHERALS_ALARM_A]) { + alarm_callbacks[PERIPHERALS_ALARM_A](); + } + HAL_RTC_DeactivateAlarm(_hrtc, RTC_ALARM_A); + alarmed_already[PERIPHERALS_ALARM_A] = true; +} + +void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *_hrtc) { + if (alarm_callbacks[PERIPHERALS_ALARM_B]) { + alarm_callbacks[PERIPHERALS_ALARM_B](); + } + HAL_RTC_DeactivateAlarm(_hrtc, RTC_ALARM_B); + alarmed_already[PERIPHERALS_ALARM_B] = true; +} diff --git a/ports/stm/peripherals/rtc.h b/ports/stm/peripherals/rtc.h index 72336f0314..9800e2832b 100644 --- a/ports/stm/peripherals/rtc.h +++ b/ports/stm/peripherals/rtc.h @@ -22,4 +22,29 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. - */ \ No newline at end of file + */ + +#ifndef __MICROPY_INCLUDED_STM32_PERIPHERALS_RTC_H__ +#define __MICROPY_INCLUDED_STM32_PERIPHERALS_RTC_H__ + +#include +#include + +#define PERIPHERALS_ALARM_A 0 +#define PERIPHERALS_ALARM_B 1 + +uint32_t stm32_peripherals_get_rtc_freq(void); +void stm32_peripherals_rtc_init(void); +uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t* subticks); + +void stm32_peripherals_rtc_assign_wkup_callback(void(*callback)(void)); +void stm32_peripherals_rtc_set_wakeup_mode_seconds(uint32_t seconds); +void stm32_peripherals_rtc_set_wakeup_mode_tick(void); +void stm32_peripherals_rtc_enable_wakeup_timer(void); +void stm32_peripherals_rtc_disable_wakeup_timer(void); + +void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) ; +void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks); +bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx); + +#endif // __MICROPY_INCLUDED_STM32_PERIPHERALS_RTC_H__ diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index afbe333e38..4339a1c646 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -45,17 +45,18 @@ #include "common-hal/pwmio/PWMOut.h" #endif #if CIRCUITPY_PULSEIO || CIRCUITPY_PWMIO -#include "timers.h" +#include "peripherals/timers.h" #endif #if CIRCUITPY_SDIOIO #include "common-hal/sdioio/SDCard.h" #endif #if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM -#include "exti.h" +#include "peripherals/exti.h" #endif -#include "clocks.h" -#include "gpio.h" +#include "peripherals/clocks.h" +#include "peripherals/gpio.h" +#include "peripherals/rtc.h" #include STM32_HAL_H @@ -163,13 +164,6 @@ __attribute__((used, naked)) void Reset_Handler(void) { // Low power clock variables static volatile uint32_t systick_ms; -static RTC_HandleTypeDef _hrtc; - -#if BOARD_HAS_LOW_SPEED_CRYSTAL -static uint32_t rtc_clock_frequency = LSE_VALUE; -#else -static uint32_t rtc_clock_frequency = LSI_VALUE; -#endif safe_mode_t port_init(void) { HAL_Init(); // Turns on SysTick @@ -181,20 +175,7 @@ safe_mode_t port_init(void) { stm32_peripherals_clocks_init(); stm32_peripherals_gpio_init(); - - // RTC oscillator selection is handled in peripherals///clocks.c - __HAL_RCC_RTC_ENABLE(); - _hrtc.Instance = RTC; - _hrtc.Init.HourFormat = RTC_HOURFORMAT_24; - // Divide async as little as possible so that we have rtc_clock_frequency count in subseconds. - // This ensures our timing > 1 second is correct. - _hrtc.Init.AsynchPrediv = 0x0; - _hrtc.Init.SynchPrediv = rtc_clock_frequency - 1; - _hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; - - HAL_RTC_Init(&_hrtc); - HAL_RTCEx_EnableBypassShadow(&_hrtc); - HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); + stm32_peripherals_rtc_init(); // Turn off SysTick SysTick->CTRL = 0; @@ -223,7 +204,6 @@ uint32_t HAL_GetTick() { } } - void SysTick_Handler(void) { systick_ms += 1; // Read the CTRL register to clear the SysTick interrupt. @@ -328,119 +308,26 @@ __attribute__((used)) void HardFault_Handler(void) } } -// This function is called often for timing so we cache the seconds elapsed computation based on the -// register value. The STM HAL always does shifts and conversion if we use it directly. -volatile uint32_t seconds_to_date = 0; -volatile uint32_t cached_date = 0; -volatile uint32_t seconds_to_minute = 0; -volatile uint32_t cached_hours_minutes = 0; uint64_t port_get_raw_ticks(uint8_t* subticks) { - // Disable IRQs to ensure we read all of the RTC registers as close in time as possible. Read - // SSR twice to make sure we didn't read across a tick. - __disable_irq(); - uint32_t first_ssr = (uint32_t)(RTC->SSR); - uint32_t time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); - uint32_t date = (uint32_t)(RTC->DR & RTC_DR_RESERVED_MASK); - uint32_t ssr = (uint32_t)(RTC->SSR); - while (ssr != first_ssr) { - first_ssr = ssr; - time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); - date = (uint32_t)(RTC->DR & RTC_DR_RESERVED_MASK); - ssr = (uint32_t)(RTC->SSR); - } - __enable_irq(); - - uint32_t subseconds = rtc_clock_frequency - 1 - ssr; - - if (date != cached_date) { - uint32_t year = (uint8_t)((date & (RTC_DR_YT | RTC_DR_YU)) >> 16U); - uint8_t month = (uint8_t)((date & (RTC_DR_MT | RTC_DR_MU)) >> 8U); - uint8_t day = (uint8_t)(date & (RTC_DR_DT | RTC_DR_DU)); - // Add 2000 since the year is only the last two digits. - year = 2000 + (uint32_t)RTC_Bcd2ToByte(year); - month = (uint8_t)RTC_Bcd2ToByte(month); - day = (uint8_t)RTC_Bcd2ToByte(day); - seconds_to_date = timeutils_seconds_since_2000(year, month, day, 0, 0, 0); - cached_date = date; - } - uint32_t hours_minutes = time & (RTC_TR_HT | RTC_TR_HU | RTC_TR_MNT | RTC_TR_MNU); - if (hours_minutes != cached_hours_minutes) { - uint8_t hours = (uint8_t)((time & (RTC_TR_HT | RTC_TR_HU)) >> 16U); - uint8_t minutes = (uint8_t)((time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8U); - hours = (uint8_t)RTC_Bcd2ToByte(hours); - minutes = (uint8_t)RTC_Bcd2ToByte(minutes); - seconds_to_minute = 60 * (60 * hours + minutes); - cached_hours_minutes = hours_minutes; - } - uint8_t seconds = (uint8_t)(time & (RTC_TR_ST | RTC_TR_SU)); - seconds = (uint8_t)RTC_Bcd2ToByte(seconds); - if (subticks != NULL) { - *subticks = subseconds % 32; - } - - uint64_t raw_ticks = ((uint64_t) 1024) * (seconds_to_date + seconds_to_minute + seconds) + subseconds / 32; - return raw_ticks; -} - -void RTC_WKUP_IRQHandler(void) { - supervisor_tick(); - __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&_hrtc, RTC_FLAG_WUTF); - __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); - _hrtc.State = HAL_RTC_STATE_READY; -} - -volatile bool alarmed_already = false; -void RTC_Alarm_IRQHandler(void) { - HAL_RTC_DeactivateAlarm(&_hrtc, RTC_ALARM_A); - __HAL_RTC_ALARM_EXTI_CLEAR_FLAG(); - __HAL_RTC_ALARM_CLEAR_FLAG(&_hrtc, RTC_FLAG_ALRAF); - alarmed_already = true; + return stm32_peripherals_rtc_raw_ticks(subticks); } // Enable 1/1024 second tick. void port_enable_tick(void) { - HAL_RTCEx_SetWakeUpTimer_IT(&_hrtc, rtc_clock_frequency / 1024 / 2, RTC_WAKEUPCLOCK_RTCCLK_DIV2); - HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 1, 0U); - HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn); + stm32_peripherals_rtc_set_wakeup_mode_tick(); + stm32_peripherals_rtc_assign_wkup_callback(supervisor_tick); + stm32_peripherals_rtc_enable_wakeup_timer(); } +// TODO: what is this? can I get rid of it? extern volatile uint32_t autoreload_delay_ms; // Disable 1/1024 second tick. void port_disable_tick(void) { - HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn); - HAL_RTCEx_DeactivateWakeUpTimer(&_hrtc); + stm32_peripherals_rtc_disable_wakeup_timer(); } void port_interrupt_after_ticks(uint32_t ticks) { - uint64_t raw_ticks = port_get_raw_ticks(NULL) + ticks; - - RTC_AlarmTypeDef alarm; - if (ticks > 1024) { - timeutils_struct_time_t tm; - timeutils_seconds_since_2000_to_struct_time(raw_ticks / 1024, &tm); - alarm.AlarmTime.Hours = tm.tm_hour; - alarm.AlarmTime.Minutes = tm.tm_min; - alarm.AlarmTime.Seconds = tm.tm_sec; - alarm.AlarmDateWeekDay = tm.tm_mday; - // Masking here means that the value is ignored so we set none. - alarm.AlarmMask = RTC_ALARMMASK_NONE; - } else { - // Masking here means that the value is ignored so we set them all. Only the subseconds - // value matters. - alarm.AlarmMask = RTC_ALARMMASK_ALL; - } - - alarm.AlarmTime.SubSeconds = rtc_clock_frequency - 1 - - ((raw_ticks % 1024) * 32); - alarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; - alarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_SET; - // Masking here means that the bits are ignored so we set none of them. - alarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE; - alarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; - alarm.Alarm = RTC_ALARM_A; - - HAL_RTC_SetAlarm_IT(&_hrtc, &alarm, RTC_FORMAT_BIN); - alarmed_already = false; + stm32_peripherals_rtc_set_alarm(PERIPHERALS_ALARM_A, ticks); } void port_idle_until_interrupt(void) { @@ -449,7 +336,8 @@ void port_idle_until_interrupt(void) { __set_FPSCR(__get_FPSCR() & ~(0x9f)); (void) __get_FPSCR(); } - if (alarmed_already) { + // The alarm might have triggered before we even reach the WFI + if (stm32_peripherals_rtc_alarm_triggered(PERIPHERALS_ALARM_A)) { return; } __WFI(); diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 7be629d52b..46aa88dff4 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -228,7 +228,7 @@ mp_obj_t alarm_get_wake_alarm(void) { } // Initialize .wake_alarm value. -void common_hal_alarm_save_wake_alarm(void) { +void shared_alarm_save_wake_alarm(void) { // Equivalent of: // alarm.wake_alarm = alarm mp_map_elem_t *elem = diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index 12ee0f1aad..723880d247 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -50,7 +50,7 @@ extern void common_hal_alarm_gc_collect(void); extern mp_obj_t common_hal_alarm_get_wake_alarm(void); // Used by wake-up code. -void common_hal_alarm_save_wake_alarm(void); +void shared_alarm_save_wake_alarm(void); // True if an alarm is alerting. This is most useful for pretend deep sleep. From d8a2d69e1067c79de0daabc79c305980965e9934 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Sun, 21 Mar 2021 13:15:44 -0400 Subject: [PATCH 03/16] Working deep sleep via RTC reset, with debug pins --- ports/stm/common-hal/alarm/__init__.c | 5 ++++- ports/stm/common-hal/alarm/time/TimeAlarm.c | 2 ++ ports/stm/peripherals/rtc.c | 22 ++++++++++++++++++++- ports/stm/peripherals/rtc.h | 1 + ports/stm/supervisor/port.c | 20 +++++++++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 96dac9323a..1ee43a99cc 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -141,8 +141,11 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala //#define NORETURN __attribute__((noreturn)) void NORETURN common_hal_alarm_enter_deep_sleep(void) { + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1); + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,0); alarm_pin_pinalarm_prepare_for_deep_sleep(); - //port_disable_tick(); + port_disable_tick(); + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // alarm_touch_touchalarm_prepare_for_deep_sleep(); // HAL_PWR_EnableBkUpAccess(); // __HAL_RCC_BACKUPRESET_FORCE(); diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c index 19d96e69c4..5817feb585 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.c +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -31,6 +31,8 @@ #include "supervisor/port.h" #include "peripherals/rtc.h" +#include STM32_HAL_H + STATIC volatile bool woke_up; void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) { diff --git a/ports/stm/peripherals/rtc.c b/ports/stm/peripherals/rtc.c index 3453ec4747..70753d3b8e 100644 --- a/ports/stm/peripherals/rtc.c +++ b/ports/stm/peripherals/rtc.c @@ -54,7 +54,7 @@ volatile bool alarmed_already[2]; bool peripherals_wkup_on = false; static void (*wkup_callback)(void); -static void(*alarm_callbacks[2])(void); +static void (*alarm_callbacks[2])(void); uint32_t stm32_peripherals_get_rtc_freq(void) { return rtc_clock_frequency; @@ -154,11 +154,20 @@ void stm32_peripherals_rtc_disable_wakeup_timer(void) { HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); } +void stm32_peripherals_reset_alarms(void) { + HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A); + HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_B); +} + void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) { alarm_callbacks[alarm_idx] = callback; } void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks) { + // TEMP: ping set alarm (called by port_interrupt_after_ticks and alarm_time_timealarm_set_alarms) + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,1); + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,0); + uint64_t raw_ticks = stm32_peripherals_rtc_raw_ticks(NULL) + ticks; RTC_AlarmTypeDef alarm; @@ -187,6 +196,7 @@ void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks) { alarm.Alarm = (alarm_idx == PERIPHERALS_ALARM_A) ? RTC_ALARM_A : RTC_ALARM_B; HAL_RTC_SetAlarm_IT(&hrtc, &alarm, RTC_FORMAT_BIN); + HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); alarmed_already[alarm_idx] = false; } @@ -195,6 +205,8 @@ bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx) { } void RTC_WKUP_IRQHandler(void) { + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,1); + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,0); if (wkup_callback) { wkup_callback(); } @@ -208,6 +220,10 @@ void RTC_Alarm_IRQHandler(void) { } void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *_hrtc) { + // TEMP + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,1); + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,0); + if (alarm_callbacks[PERIPHERALS_ALARM_A]) { alarm_callbacks[PERIPHERALS_ALARM_A](); } @@ -216,6 +232,10 @@ void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *_hrtc) { } void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *_hrtc) { + //TEMP + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,1); + HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,0); + if (alarm_callbacks[PERIPHERALS_ALARM_B]) { alarm_callbacks[PERIPHERALS_ALARM_B](); } diff --git a/ports/stm/peripherals/rtc.h b/ports/stm/peripherals/rtc.h index 9800e2832b..d010a2a0c8 100644 --- a/ports/stm/peripherals/rtc.h +++ b/ports/stm/peripherals/rtc.h @@ -43,6 +43,7 @@ void stm32_peripherals_rtc_set_wakeup_mode_tick(void); void stm32_peripherals_rtc_enable_wakeup_timer(void); void stm32_peripherals_rtc_disable_wakeup_timer(void); +void stm32_peripherals_reset_alarms(void); void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) ; void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks); bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx); diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 4339a1c646..d040cee184 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -173,10 +173,16 @@ safe_mode_t port_init(void) { __HAL_RCC_PWR_CLK_ENABLE(); #endif + __HAL_RCC_BACKUPRESET_FORCE(); + __HAL_RCC_BACKUPRESET_RELEASE(); + stm32_peripherals_clocks_init(); stm32_peripherals_gpio_init(); stm32_peripherals_rtc_init(); + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); + stm32_peripherals_reset_alarms(); + // Turn off SysTick SysTick->CTRL = 0; @@ -233,6 +239,20 @@ void reset_port(void) { #if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM exti_reset(); #endif + + // TEMP: set up interrupt logging pins + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + // TEMP: ping port init + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,1); + HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,0); } void reset_to_bootloader(void) { From 529fb52309a356593025915fef3da8a66f4da313 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Sat, 27 Mar 2021 13:16:12 -0400 Subject: [PATCH 04/16] Style changes and wakeup detection --- main.c | 24 +++---- ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 5 +- .../boards/feather_stm32f405_express/board.c | 3 - ports/stm/common-hal/alarm/__init__.c | 70 ++++++++++--------- ports/stm/common-hal/alarm/pin/PinAlarm.c | 17 ++--- ports/stm/common-hal/alarm/time/TimeAlarm.c | 18 +++++ ports/stm/common-hal/alarm/time/TimeAlarm.h | 2 + ports/stm/supervisor/port.c | 6 ++ shared-bindings/alarm/__init__.c | 2 +- 9 files changed, 88 insertions(+), 59 deletions(-) diff --git a/main.c b/main.c index c7a5afabcb..68c0e025e1 100755 --- a/main.c +++ b/main.c @@ -323,12 +323,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { rgb_status_animation_t animation; prep_rgb_status_animation(&result, found_main, safe_mode, &animation); - bool asleep = false; + bool fake_sleeping = false; while (true) { RUN_BACKGROUND_TASKS; if (reload_requested) { #if CIRCUITPY_ALARM - if (asleep) { + if (fake_sleeping) { board_init(); } #endif @@ -339,7 +339,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { if (serial_connected() && serial_bytes_available()) { #if CIRCUITPY_ALARM - if (asleep) { + if (fake_sleeping) { board_init(); } #endif @@ -355,7 +355,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { // an alarm alerts faster than our USB delay or if we pretended to deep // sleep. #if CIRCUITPY_ALARM - if (asleep && common_hal_alarm_woken_from_sleep()) { + if (fake_sleeping && common_hal_alarm_woken_from_sleep()) { serial_write_compressed(translate("Woken up by alarm.\n")); board_init(); supervisor_set_run_reason(RUN_REASON_STARTUP); @@ -394,14 +394,12 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { if (result.return_code & PYEXEC_DEEP_SLEEP) { // Make sure we have been awake long enough for USB to connect (enumeration delay). int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL); - if (connecting_delay_ticks > 0) { - // Set when we've waited long enough so that we wake up from the - // port_idle_until_interrupt below and loop around to the real deep - // sleep in the else clause. - port_interrupt_after_ticks(connecting_delay_ticks); - // Deep sleep if we're not connected to a host. - } else if (!asleep) { - asleep = true; + // Until it's safe to decide whether we're real/fake sleeping, just run the RGB + // if (connecting_delay_ticks > 0) { + // port_interrupt_after_ticks(connecting_delay_ticks); + // // } else if (!fake_sleeping) { + if (connecting_delay_ticks < 0 && !fake_sleeping) { + fake_sleeping = true; new_status_color(BLACK); board_deinit(); if (!supervisor_workflow_active()) { @@ -416,7 +414,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { } #endif - if (!asleep) { + if (!fake_sleeping) { tick_rgb_status_animation(&animation); } else { // This waits until a pretend deep sleep alarm occurs. They are set diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index df8d10ef9e..237136c3d8 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -101,7 +101,7 @@ bool alarm_pin_pinalarm_woke_us_up(void) { } mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { - // First, check to see if we match any given alarms. + // For light sleep, we check if we match any existing alarms uint64_t pin_status = ((uint64_t) pin_63_32_status) << 32 | pin_31_0_status; for (size_t i = 0; i < n_alarms; i++) { if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { @@ -112,6 +112,7 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al return alarms[i]; } } + // For deep sleep, a new alarm must be created esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); size_t pin_number = 64; if (cause == ESP_SLEEP_WAKEUP_EXT0) { @@ -151,7 +152,7 @@ static uint64_t high_alarms = 0; static uint64_t low_alarms = 0; static uint64_t pull_pins = 0; -void alarm_pin_pinalarm_reset(void) { +void alarm_pin_pinalarm_reset_alarms(void) { if (gpio_interrupt_handle != NULL) { esp_intr_free(gpio_interrupt_handle); gpio_interrupt_handle = NULL; diff --git a/ports/stm/boards/feather_stm32f405_express/board.c b/ports/stm/boards/feather_stm32f405_express/board.c index 6652c840c6..f8e462f938 100644 --- a/ports/stm/boards/feather_stm32f405_express/board.c +++ b/ports/stm/boards/feather_stm32f405_express/board.c @@ -37,6 +37,3 @@ bool board_requests_safe_mode(void) { void reset_board(void) { } - -void board_deinit(void) { -} \ No newline at end of file diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 1ee43a99cc..0cefc58834 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -39,70 +39,73 @@ #include "supervisor/port.h" #include "supervisor/shared/workflow.h" +#define STM_WAKEUP_UNDEF 0 #define STM_WAKEUP_GPIO 1 -#define STM_WAKEUP_TIMER 2 +#define STM_WAKEUP_RTC 2 + +#define STM_ALARM_FLAG RTC->BKP0R void common_hal_alarm_reset(void) { + // Reset the alarm flag + STM_ALARM_FLAG = 0x00; // alarm_sleep_memory_reset(); alarm_pin_pinalarm_reset(); alarm_time_timealarm_reset(); - // alarm_touch_touchalarm_reset(); // esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } STATIC uint8_t _get_wakeup_cause(void) { + // If in light/fake sleep, check modules if (alarm_pin_pinalarm_woke_us_up()) { return STM_WAKEUP_GPIO; } if (alarm_time_timealarm_woke_us_up()) { - return STM_WAKEUP_TIMER; + return STM_WAKEUP_RTC; } - return 0; + if (RTC->BKP0R & 0x01) { + // We've woken from deep sleep. Was it the WKUP pin or the RTC? + if (RTC->ISR & RTC_FLAG_ALRBF) { + // Alarm B is the deep sleep alarm + return STM_WAKEUP_RTC; + } else { + return STM_WAKEUP_GPIO; + } + } + return STM_WAKEUP_UNDEF; } bool common_hal_alarm_woken_from_sleep(void) { - return _get_wakeup_cause() != 0; + return _get_wakeup_cause() != STM_WAKEUP_UNDEF; } STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { if (alarm_pin_pinalarm_woke_us_up()) { return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); } - // esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(); - // switch (cause) { - // case ESP_SLEEP_WAKEUP_TIMER: { - // return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms); - // } - - // case ESP_SLEEP_WAKEUP_GPIO: - // case ESP_SLEEP_WAKEUP_EXT0: - // case ESP_SLEEP_WAKEUP_EXT1: { - // return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); - // } - - // case ESP_SLEEP_WAKEUP_TOUCHPAD: { - // return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms); - // } - - // case ESP_SLEEP_WAKEUP_UNDEFINED: - // default: - // // Not a deep sleep reset. - // break; - // } - // return mp_const_none; + uint8_t cause = _get_wakeup_cause(); + switch (cause) { + case STM_WAKEUP_RTC: { + return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms); + } + case STM_WAKEUP_GPIO: { + return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); + } + case STM_WAKEUP_UNDEF: + default: + // Not a deep sleep reset. + break; + } return mp_const_none; } mp_obj_t common_hal_alarm_get_wake_alarm(void) { - //return _get_wake_alarm(0, NULL); - return mp_const_none; + 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); - // alarm_touch_touchalarm_set_alarm(deep_sleep, n_alarms, alarms); } STATIC void _idle_until_alarm(void) { @@ -144,16 +147,19 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) { HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1); HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,0); alarm_pin_pinalarm_prepare_for_deep_sleep(); + alarm_time_timealarm_prepare_for_deep_sleep(); port_disable_tick(); __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); - // alarm_touch_touchalarm_prepare_for_deep_sleep(); + + // Set a flag in the backup registers to indicate sleep wakeup + STM_ALARM_FLAG = 0x01; // HAL_PWR_EnableBkUpAccess(); // __HAL_RCC_BACKUPRESET_FORCE(); // __HAL_RCC_BACKUPRESET_RELEASE(); HAL_PWR_EnterSTANDBYMode(); - // Should never hit this + // The above shuts down RAM, so we should never hit this while(1); } diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c index 9d6423d859..3bff19b76c 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.c +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -109,6 +109,7 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al } void alarm_pin_pinalarm_reset(void) { + HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); alarm_pin_triggered = 0; woke_up = false; } @@ -118,20 +119,18 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob for (size_t i = 0; i < n_alarms; i++) { if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); - if (deep_sleep) { // Deep sleep only wakes on a rising edge from one pin, WKUP (PA00) + // All pin settings are handled automatically. if (alarm->pin != &pin_PA00) { mp_raise_ValueError(translate("Only the WKUP pin can be used to wake from Deep Sleep")); } - HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); - __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); - HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); - + // We can't actually turn WakeUp on here, since enabling it disables EXTI, + // so we put it off until right before sleeping. deep_wkup_enabled = true; - } else { - stm_peripherals_exti_enable(alarm->pin->number); } + + stm_peripherals_exti_enable(alarm->pin->number); } } } @@ -150,7 +149,9 @@ void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_ // If we don't have WKUP enabled, ensure it's disabled // TODO; is this really required? void alarm_pin_pinalarm_prepare_for_deep_sleep(void) { - if (!deep_wkup_enabled) { + if (deep_wkup_enabled) { HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); + HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); } } diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c index 5817feb585..5ca08fa994 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.c +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -34,6 +34,7 @@ #include STM32_HAL_H STATIC volatile bool woke_up; +STATIC uint32_t deep_sleep_ticks; void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) { self->monotonic_time = monotonic_time; @@ -95,7 +96,24 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ uint32_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs); uint32_t wakeup_in_ticks = wakeup_in_secs * 1024; + // In the deep sleep case, we can't start the timer until the USB delay has finished + if (deep_sleep) { + deep_sleep_ticks = wakeup_in_ticks; + } else { + deep_sleep_ticks = 0; + } // Use alarm B, since port reserves A + // If true deep sleep is called, it will either ignore or overwrite this depending on + // whether it is shorter or longer than the USB delay stm32_peripherals_rtc_assign_alarm_callback(PERIPHERALS_ALARM_B,timer_callback); stm32_peripherals_rtc_set_alarm(PERIPHERALS_ALARM_B,wakeup_in_ticks); } + +void alarm_time_timealarm_prepare_for_deep_sleep(void) { + if (deep_sleep_ticks) { + // This is used for both fake and real deep sleep, so it still needs the callback + stm32_peripherals_rtc_assign_alarm_callback(PERIPHERALS_ALARM_B,timer_callback); + stm32_peripherals_rtc_set_alarm(PERIPHERALS_ALARM_B,deep_sleep_ticks); + deep_sleep_ticks = 0; + } +} diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.h b/ports/stm/common-hal/alarm/time/TimeAlarm.h index d4041dc0ae..11c7a634c5 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.h +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.h @@ -38,3 +38,5 @@ mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t * bool alarm_time_timealarm_woke_us_up(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); diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index d040cee184..49cc92ca5b 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -369,3 +369,9 @@ void _init(void) { } + +#if CIRCUITPY_ALARM +// in case boards/xxx/board.c does not provide board_deinit() +MP_WEAK void board_deinit(void) { +} +#endif diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 46aa88dff4..b04e821bbb 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -92,7 +92,7 @@ void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) { //| This allows the user to interrupt an existing program with ctrl-C, //| and to edit the files in CIRCUITPY, which would not be possible in true light sleep. //| Thus, to use light sleep and save significant power, -// it may be necessary to disconnect from the host. +//| it may be necessary to disconnect from the host. //| """ //| ... //| From 4f52554eb3977a7da19161ea139906d95f2937c7 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Thu, 1 Apr 2021 20:53:25 -0400 Subject: [PATCH 05/16] Fix to RTC reset --- ports/stm/common-hal/alarm/__init__.c | 3 --- ports/stm/supervisor/port.c | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 0cefc58834..9df19ed705 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -79,9 +79,6 @@ bool common_hal_alarm_woken_from_sleep(void) { } STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { - if (alarm_pin_pinalarm_woke_us_up()) { - return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); - } uint8_t cause = _get_wakeup_cause(); switch (cause) { case STM_WAKEUP_RTC: { diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 947bb7c3af..78c05fc98e 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -169,10 +169,9 @@ safe_mode_t port_init(void) { HAL_Init(); // Turns on SysTick __HAL_RCC_SYSCFG_CLK_ENABLE(); - #if (CPY_STM32F4) __HAL_RCC_PWR_CLK_ENABLE(); - #endif + HAL_PWR_EnableBkUpAccess(); __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); From 91e530d36cb33d0cfa439b49ad6a7d2631c634c5 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 2 Apr 2021 13:42:22 -0400 Subject: [PATCH 06/16] Resolve wake alarm crash --- ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 2 +- ports/stm/common-hal/alarm/__init__.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index a6bd0ed376..9ea9b9b998 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -152,7 +152,7 @@ static uint64_t high_alarms = 0; static uint64_t low_alarms = 0; static uint64_t pull_pins = 0; -void alarm_pin_pinalarm_reset_alarms(void) { +void alarm_pin_pinalarm_reset(void) { if (gpio_interrupt_handle != NULL) { esp_intr_free(gpio_interrupt_handle); gpio_interrupt_handle = NULL; diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 9df19ed705..6b0d6f4681 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -161,5 +161,5 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) { } void common_hal_alarm_gc_collect(void) { - gc_collect_ptr(common_hal_alarm_get_wake_alarm()); + gc_collect_ptr(shared_alarm_get_wake_alarm()); } From 17585e1e079d4c837877daf1b5c7352b7bd11c9d Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 2 Apr 2021 14:08:48 -0400 Subject: [PATCH 07/16] Clean up API --- main.c | 7 ++++++- ports/esp32s2/common-hal/alarm/__init__.c | 4 ++-- ports/esp32s2/common-hal/alarm/__init__.h | 2 +- ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 4 ++-- ports/esp32s2/common-hal/alarm/pin/PinAlarm.h | 2 +- ports/stm/common-hal/alarm/__init__.c | 4 ++-- ports/stm/common-hal/alarm/__init__.h | 2 +- ports/stm/common-hal/alarm/pin/PinAlarm.c | 16 +++------------- ports/stm/common-hal/alarm/pin/PinAlarm.h | 3 +-- shared-bindings/alarm/pin/PinAlarm.c | 4 ++-- shared-bindings/alarm/pin/PinAlarm.h | 4 ++-- 11 files changed, 23 insertions(+), 29 deletions(-) diff --git a/main.c b/main.c index 9979d9a59d..c9226bf3e5 100755 --- a/main.c +++ b/main.c @@ -163,7 +163,7 @@ STATIC void start_mp(supervisor_allocation* heap) { // Record which alarm woke us up, if any. An object may be created so the heap must be functional. shared_alarm_save_wake_alarm(); // Reset alarm module only after we retrieved the wakeup alarm. - common_hal_alarm_reset(); + alarm_reset(); #endif #if CIRCUITPY_NETWORK @@ -293,9 +293,13 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { stack_resize(); filesystem_flush(); supervisor_allocation* heap = allocate_remaining_memory(); + + // Prepare the VM state. Includes an alarm check/reset for sleep. start_mp(heap); + // This is where the user's python code is actually executed: found_main = maybe_run_list(supported_filenames, &result); + // If that didn't work, double check the extensions #if CIRCUITPY_FULL_BUILD if (!found_main){ found_main = maybe_run_list(double_extension_filenames, &result); @@ -305,6 +309,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { } #endif + // Finished executing python code. Cleanup includes a board reset. cleanup_after_vm(heap); if (result.return_code & PYEXEC_FORCED_EXIT) { diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 264a525cf7..696e3ec150 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -54,7 +54,7 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { }, }; -void common_hal_alarm_reset(void) { +void alarm_reset(void) { alarm_sleep_memory_reset(); alarm_pin_pinalarm_reset(); alarm_time_timealarm_reset(); @@ -144,7 +144,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj } mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); - alarm_pin_pinalarm_reset_alarms(n_alarms, alarms); + alarm_reset(); return wake_alarm; } diff --git a/ports/esp32s2/common-hal/alarm/__init__.h b/ports/esp32s2/common-hal/alarm/__init__.h index 2b46907778..0823ff842e 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.h +++ b/ports/esp32s2/common-hal/alarm/__init__.h @@ -31,6 +31,6 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; -extern void common_hal_alarm_reset(void); +extern void alarm_reset(void); #endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM__INIT__H diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index 9ea9b9b998..7a743fc0f2 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -38,7 +38,7 @@ #include "components/soc/src/esp32s2/include/hal/gpio_ll.h" #include "components/xtensa/include/esp_debug_helpers.h" -void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { if (edge) { mp_raise_ValueError(translate("Cannot wake on pin edge. Only level.")); } @@ -51,7 +51,7 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu self->pull = pull; } -mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { +const mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { return self->pin; } diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h index 93672c1f2d..4d86af4c3d 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h @@ -29,7 +29,7 @@ typedef struct { mp_obj_base_t base; - mcu_pin_obj_t *pin; + const mcu_pin_obj_t *pin; bool value; bool pull; } alarm_pin_pinalarm_obj_t; diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 6b0d6f4681..14c484f1b0 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -45,7 +45,7 @@ #define STM_ALARM_FLAG RTC->BKP0R -void common_hal_alarm_reset(void) { +void alarm_reset(void) { // Reset the alarm flag STM_ALARM_FLAG = 0x00; // alarm_sleep_memory_reset(); @@ -131,7 +131,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj } mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); - common_hal_alarm_reset(); + alarm_reset(); return wake_alarm; } diff --git a/ports/stm/common-hal/alarm/__init__.h b/ports/stm/common-hal/alarm/__init__.h index 18defefc0b..cb90dccb28 100644 --- a/ports/stm/common-hal/alarm/__init__.h +++ b/ports/stm/common-hal/alarm/__init__.h @@ -31,6 +31,6 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; -extern void common_hal_alarm_reset(void); +extern void alarm_reset(void); #endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c index 3bff19b76c..d7f1c30398 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.c +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -43,7 +43,7 @@ STATIC void pin_alarm_callback(uint8_t num) { HAL_GPIO_EXTI_IRQHandler(pin_mask(num)); } -void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { if (!edge) { mp_raise_NotImplementedError(translate("Only edge detection is available on this hardware")); } @@ -70,7 +70,7 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu self->pull = pull; } -mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { +const mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { return self->pin; } @@ -112,6 +112,7 @@ void alarm_pin_pinalarm_reset(void) { HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); alarm_pin_triggered = 0; woke_up = false; + deep_wkup_enabled = false; } // Deep sleep alarms don't actually make use of EXTI, but we pretend they're the same. @@ -135,17 +136,6 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob } } -void alarm_pin_pinalarm_reset_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { - alarm_pin_triggered = 0; - deep_wkup_enabled = false; - for (size_t i = 0; i < n_alarms; i++) { - if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { - alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); - stm_peripherals_exti_disable(alarm->pin->number); - } - } -} - // If we don't have WKUP enabled, ensure it's disabled // TODO; is this really required? void alarm_pin_pinalarm_prepare_for_deep_sleep(void) { diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.h b/ports/stm/common-hal/alarm/pin/PinAlarm.h index b26930b103..2b94f1cb7e 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.h +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.h @@ -29,14 +29,13 @@ typedef struct { mp_obj_base_t base; - mcu_pin_obj_t *pin; + const mcu_pin_obj_t *pin; bool value; bool pull; } alarm_pin_pinalarm_obj_t; 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_reset_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); diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index 04063e89c2..69e6be8c73 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -73,7 +73,7 @@ STATIC mp_obj_t alarm_pin_pinalarm_make_new(const mp_obj_type_t *type, mp_uint_t mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(0, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); + const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); common_hal_alarm_pin_pinalarm_construct(self, pin, @@ -89,7 +89,7 @@ STATIC mp_obj_t alarm_pin_pinalarm_make_new(const mp_obj_type_t *type, mp_uint_t //| STATIC mp_obj_t alarm_pin_pinalarm_obj_get_pin(mp_obj_t self_in) { alarm_pin_pinalarm_obj_t *self = MP_OBJ_TO_PTR(self_in); - mcu_pin_obj_t *pin = common_hal_alarm_pin_pinalarm_get_pin(self); + const mcu_pin_obj_t *pin = common_hal_alarm_pin_pinalarm_get_pin(self); if (pin == NULL) { return mp_const_none; } diff --git a/shared-bindings/alarm/pin/PinAlarm.h b/shared-bindings/alarm/pin/PinAlarm.h index 48865009c3..ba74bab5f3 100644 --- a/shared-bindings/alarm/pin/PinAlarm.h +++ b/shared-bindings/alarm/pin/PinAlarm.h @@ -34,8 +34,8 @@ extern const mp_obj_type_t alarm_pin_pinalarm_type; -void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull); -extern mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self); +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull); +extern const mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self); extern bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self); extern bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self); extern bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self); From 66a1583183c8b7e0afcd726569952a9456c705d1 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 2 Apr 2021 15:13:10 -0400 Subject: [PATCH 08/16] Implement fake and true deep sleep alarm differentiation --- ports/stm/common-hal/alarm/__init__.c | 36 +++++++++++++++-------- ports/stm/common-hal/alarm/__init__.h | 7 +++++ ports/stm/common-hal/alarm/pin/PinAlarm.c | 30 ++++++++++++++----- ports/stm/peripherals/exti.c | 20 +++++++++++-- ports/stm/peripherals/exti.h | 2 ++ ports/stm/peripherals/rtc.c | 2 +- ports/stm/peripherals/rtc.h | 2 +- ports/stm/supervisor/port.c | 17 +++++++++-- 8 files changed, 89 insertions(+), 27 deletions(-) diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 14c484f1b0..0f19f7922e 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -39,11 +39,7 @@ #include "supervisor/port.h" #include "supervisor/shared/workflow.h" -#define STM_WAKEUP_UNDEF 0 -#define STM_WAKEUP_GPIO 1 -#define STM_WAKEUP_RTC 2 - -#define STM_ALARM_FLAG RTC->BKP0R +STATIC uint8_t true_deep_wake_reason; void alarm_reset(void) { // Reset the alarm flag @@ -54,6 +50,12 @@ void alarm_reset(void) { // esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } +// Kind of a hack, required as RTC is reset in port.c +// TODO: in the future, don't reset it at all, just override critical flags +void alarm_set_wakeup_reason(uint8_t reason) { + true_deep_wake_reason = reason; +} + STATIC uint8_t _get_wakeup_cause(void) { // If in light/fake sleep, check modules if (alarm_pin_pinalarm_woke_us_up()) { @@ -62,14 +64,9 @@ STATIC uint8_t _get_wakeup_cause(void) { if (alarm_time_timealarm_woke_us_up()) { return STM_WAKEUP_RTC; } - if (RTC->BKP0R & 0x01) { - // We've woken from deep sleep. Was it the WKUP pin or the RTC? - if (RTC->ISR & RTC_FLAG_ALRBF) { - // Alarm B is the deep sleep alarm - return STM_WAKEUP_RTC; - } else { - return STM_WAKEUP_GPIO; - } + // Check to see if we woke from deep sleep (reason set in port_init) + if (true_deep_wake_reason) { + return true_deep_wake_reason; } return STM_WAKEUP_UNDEF; } @@ -160,6 +157,19 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) { while(1); } +void common_hal_alarm_pretending_deep_sleep(void) { + // Re-enable the WKUP pin (PA00) since VM cleanup resets it + // If there are no PinAlarms, EXTI won't be turned on, and this won't do anything + // TODO: replace with `prepare_for_fake_deep_sleep` if other WKUP are added. + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = pin_mask(0); + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + port_idle_until_interrupt(); +} + void common_hal_alarm_gc_collect(void) { gc_collect_ptr(shared_alarm_get_wake_alarm()); } diff --git a/ports/stm/common-hal/alarm/__init__.h b/ports/stm/common-hal/alarm/__init__.h index cb90dccb28..0bfafbcee2 100644 --- a/ports/stm/common-hal/alarm/__init__.h +++ b/ports/stm/common-hal/alarm/__init__.h @@ -31,6 +31,13 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; +#define STM_WAKEUP_UNDEF 0 +#define STM_WAKEUP_GPIO 1 +#define STM_WAKEUP_RTC 2 + +#define STM_ALARM_FLAG RTC->BKP0R + +extern void alarm_set_wakeup_reason(uint8_t reason); extern void alarm_reset(void); #endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c index d7f1c30398..d2594c10d9 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.c +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -36,6 +36,7 @@ STATIC bool woke_up; STATIC uint16_t alarm_pin_triggered; STATIC bool deep_wkup_enabled; +STATIC bool reserved_alarms[STM32_GPIO_PORT_SIZE]; STATIC void pin_alarm_callback(uint8_t num) { alarm_pin_triggered |= (1 << num); @@ -50,7 +51,6 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, con if (!stm_peripherals_exti_is_free(pin->number)) { mp_raise_RuntimeError(translate("Pin interrupt already in use")); } - stm_peripherals_exti_reserve(pin->number); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = pin_mask(pin->number); GPIO_InitStruct.Mode = value ? GPIO_MODE_IT_RISING : GPIO_MODE_IT_FALLING; @@ -63,8 +63,7 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, con } HAL_GPIO_Init(pin_port(pin->port), &GPIO_InitStruct); - stm_peripherals_exti_set_callback(pin_alarm_callback,pin->number); - + // EXTI is set up and enabled in set_alarm self->pin = pin; self->value = value; self->pull = pull; @@ -101,10 +100,11 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al } } - // Placeholder for deep sleep + // If the above isn't true, we woke from deep sleep, so create a new alarm alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); alarm->base.type = &alarm_pin_pinalarm_type; - alarm->pin = NULL; + // TODO: replace this if/when other WKUP pins are supported + alarm->pin = &pin_PA00; return alarm; } @@ -113,6 +113,12 @@ void alarm_pin_pinalarm_reset(void) { alarm_pin_triggered = 0; woke_up = false; deep_wkup_enabled = false; + for (uint8_t i = 0; i < STM32_GPIO_PORT_SIZE; i++) { + if (reserved_alarms[i]) { + stm_peripherals_exti_reset_exti(i); + reserved_alarms[i] = false; + } + } } // Deep sleep alarms don't actually make use of EXTI, but we pretend they're the same. @@ -124,14 +130,24 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob // Deep sleep only wakes on a rising edge from one pin, WKUP (PA00) // All pin settings are handled automatically. if (alarm->pin != &pin_PA00) { - mp_raise_ValueError(translate("Only the WKUP pin can be used to wake from Deep Sleep")); + mp_raise_ValueError(translate("Pin cannot wake from Deep Sleep")); + } + if (alarm->value == false || alarm->pull == false) { + // Enabling WakeUp automatically sets this, but warn anyway to set expectations + mp_raise_ValueError(translate("Deep sleep pins must use a rising edge with pulldown")); } // We can't actually turn WakeUp on here, since enabling it disables EXTI, // so we put it off until right before sleeping. deep_wkup_enabled = true; + // EXTI needs to persist past the VM cleanup for fake deep sleep + stm_peripherals_exti_never_reset(alarm->pin->number); } - + if (!stm_peripherals_exti_reserve(alarm->pin->number)) { + mp_raise_RuntimeError(translate("Pin interrupt already in use")); + } + stm_peripherals_exti_set_callback(pin_alarm_callback,alarm->pin->number); stm_peripherals_exti_enable(alarm->pin->number); + reserved_alarms[alarm->pin->number] = true; } } } diff --git a/ports/stm/peripherals/exti.c b/ports/stm/peripherals/exti.c index 26e7195671..fe17309f06 100644 --- a/ports/stm/peripherals/exti.c +++ b/ports/stm/peripherals/exti.c @@ -33,16 +33,30 @@ #include "peripherals/exti.h" STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE]; +STATIC bool stm_exti_never_reset[STM32_GPIO_PORT_SIZE]; STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num); void exti_reset(void) { for (size_t i = 0;i < STM32_GPIO_PORT_SIZE; i++) { - stm_exti_reserved[i] = false; - stm_exti_callback[i] = NULL; - stm_peripherals_exti_disable(i); + if (!stm_exti_never_reset[i]) { + stm_exti_reserved[i] = false; + stm_exti_callback[i] = NULL; + stm_peripherals_exti_disable(i); + } } } +void stm_peripherals_exti_never_reset(uint8_t num) { + stm_exti_never_reset[num] = true; +} + +void stm_peripherals_exti_reset_exti(uint8_t num) { + stm_peripherals_exti_disable(num); + stm_exti_never_reset[num] = false; + stm_exti_reserved[num] = false; + stm_exti_callback[num] = NULL; +} + bool stm_peripherals_exti_is_free(uint8_t num) { return !stm_exti_reserved[num]; } diff --git a/ports/stm/peripherals/exti.h b/ports/stm/peripherals/exti.h index 15e2207c9c..4a3358ec2e 100644 --- a/ports/stm/peripherals/exti.h +++ b/ports/stm/peripherals/exti.h @@ -32,6 +32,8 @@ #define STM32_GPIO_PORT_SIZE 16 void exti_reset(void); +void stm_peripherals_exti_never_reset(uint8_t num); +void stm_peripherals_exti_reset_exti(uint8_t num); bool stm_peripherals_exti_is_free(uint8_t num); bool stm_peripherals_exti_reserve(uint8_t num); void stm_peripherals_exti_enable(uint8_t num); diff --git a/ports/stm/peripherals/rtc.c b/ports/stm/peripherals/rtc.c index 70753d3b8e..427dcf4e9a 100644 --- a/ports/stm/peripherals/rtc.c +++ b/ports/stm/peripherals/rtc.c @@ -154,7 +154,7 @@ void stm32_peripherals_rtc_disable_wakeup_timer(void) { HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); } -void stm32_peripherals_reset_alarms(void) { +void stm32_peripherals_rtc_reset_alarms(void) { HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A); HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_B); } diff --git a/ports/stm/peripherals/rtc.h b/ports/stm/peripherals/rtc.h index d010a2a0c8..2dea6920a4 100644 --- a/ports/stm/peripherals/rtc.h +++ b/ports/stm/peripherals/rtc.h @@ -43,7 +43,7 @@ void stm32_peripherals_rtc_set_wakeup_mode_tick(void); void stm32_peripherals_rtc_enable_wakeup_timer(void); void stm32_peripherals_rtc_disable_wakeup_timer(void); -void stm32_peripherals_reset_alarms(void); +void stm32_peripherals_rtc_reset_alarms(void); void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) ; void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks); bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx); diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 78c05fc98e..22061257d5 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -53,6 +53,9 @@ #if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM #include "peripherals/exti.h" #endif +#if CIRCUITPY_ALARM +#include "common-hal/alarm/__init__.h" +#endif #include "peripherals/clocks.h" #include "peripherals/gpio.h" @@ -170,8 +173,18 @@ safe_mode_t port_init(void) { __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); - HAL_PWR_EnableBkUpAccess(); + + // TODO: don't reset RTC entirely and move this back to alarm + if (STM_ALARM_FLAG & 0x01) { + // We've woken from deep sleep. Was it the WKUP pin or the RTC? + if (RTC->ISR & RTC_FLAG_ALRBF) { + // Alarm B is the deep sleep alarm + alarm_set_wakeup_reason(STM_WAKEUP_RTC); + } else { + alarm_set_wakeup_reason(STM_WAKEUP_GPIO); + } + } __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); @@ -180,7 +193,7 @@ safe_mode_t port_init(void) { stm32_peripherals_rtc_init(); __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); - stm32_peripherals_reset_alarms(); + stm32_peripherals_rtc_reset_alarms(); // Turn off SysTick SysTick->CTRL = 0; From 9240146b221dbea37c68ca7b9c760bf0b3be0ebc Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 2 Apr 2021 16:58:42 -0400 Subject: [PATCH 09/16] Make light sleep store true alarm object to global map --- ports/stm/common-hal/alarm/__init__.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 0f19f7922e..7540584ef7 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -40,8 +40,10 @@ #include "supervisor/shared/workflow.h" STATIC uint8_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_sleep_memory_reset(); @@ -93,6 +95,10 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { } 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); } @@ -106,9 +112,8 @@ STATIC void _idle_until_alarm(void) { // Poll for alarms. while (!mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; - // Allow ctrl-C interrupt. + // Detect if interrupt was alarm or ctrl-C interrupt. if (common_hal_alarm_woken_from_sleep()) { - shared_alarm_save_wake_alarm(); return; } port_idle_until_interrupt(); @@ -128,11 +133,19 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj } mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); - alarm_reset(); + + // TODO: make this 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(); 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); } @@ -147,9 +160,6 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) { // Set a flag in the backup registers to indicate sleep wakeup STM_ALARM_FLAG = 0x01; - // HAL_PWR_EnableBkUpAccess(); - // __HAL_RCC_BACKUPRESET_FORCE(); - // __HAL_RCC_BACKUPRESET_RELEASE(); HAL_PWR_EnterSTANDBYMode(); From 8a2143f161f3503b50bbc1b424571a89a19f63ff Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Fri, 2 Apr 2021 17:25:17 -0400 Subject: [PATCH 10/16] Clean up comments and debugging pins --- ports/stm/common-hal/alarm/SleepMemory.c | 3 +++ ports/stm/common-hal/alarm/__init__.c | 7 +------ ports/stm/common-hal/alarm/time/TimeAlarm.c | 2 -- ports/stm/peripherals/rtc.c | 14 -------------- ports/stm/supervisor/port.c | 17 +++-------------- 5 files changed, 7 insertions(+), 36 deletions(-) diff --git a/ports/stm/common-hal/alarm/SleepMemory.c b/ports/stm/common-hal/alarm/SleepMemory.c index f1e2772abb..0829902a22 100644 --- a/ports/stm/common-hal/alarm/SleepMemory.c +++ b/ports/stm/common-hal/alarm/SleepMemory.c @@ -34,13 +34,16 @@ void alarm_sleep_memory_reset(void) { } uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) { + mp_raise_NotImplementedError(translate("Sleep Memory not available")); return 0; } bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t* values, uint32_t len) { + mp_raise_NotImplementedError(translate("Sleep Memory not available")); return false; } void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t* values, uint32_t len) { + mp_raise_NotImplementedError(translate("Sleep Memory not available")); return; } diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 7540584ef7..0d8f8a5ff9 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -46,10 +46,8 @@ void alarm_reset(void) { most_recent_alarm = NULL; // Reset the alarm flag STM_ALARM_FLAG = 0x00; - // alarm_sleep_memory_reset(); alarm_pin_pinalarm_reset(); alarm_time_timealarm_reset(); - // esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } // Kind of a hack, required as RTC is reset in port.c @@ -134,7 +132,7 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); - // TODO: make this less roundabout + // TODO: make assignment to global array less roundabout most_recent_alarm = wake_alarm; shared_alarm_save_wake_alarm(); @@ -149,10 +147,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -//#define NORETURN __attribute__((noreturn)) void NORETURN common_hal_alarm_enter_deep_sleep(void) { - HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1); - HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,0); alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); port_disable_tick(); diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c index 5ca08fa994..fb3b5fa03d 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.c +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -64,12 +64,10 @@ STATIC void timer_callback(void) { } bool alarm_time_timealarm_woke_us_up(void) { - //mp_printf(&mp_plat_print,"Woke Up:%d\n",woke_up); return woke_up; } void alarm_time_timealarm_reset(void) { - // mp_printf(&mp_plat_print,"timealarm reset"); woke_up = false; } diff --git a/ports/stm/peripherals/rtc.c b/ports/stm/peripherals/rtc.c index 427dcf4e9a..8a1805c7ba 100644 --- a/ports/stm/peripherals/rtc.c +++ b/ports/stm/peripherals/rtc.c @@ -164,10 +164,6 @@ void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callba } void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks) { - // TEMP: ping set alarm (called by port_interrupt_after_ticks and alarm_time_timealarm_set_alarms) - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,1); - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,0); - uint64_t raw_ticks = stm32_peripherals_rtc_raw_ticks(NULL) + ticks; RTC_AlarmTypeDef alarm; @@ -205,8 +201,6 @@ bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx) { } void RTC_WKUP_IRQHandler(void) { - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,1); - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,0); if (wkup_callback) { wkup_callback(); } @@ -220,10 +214,6 @@ void RTC_Alarm_IRQHandler(void) { } void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *_hrtc) { - // TEMP - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,1); - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,0); - if (alarm_callbacks[PERIPHERALS_ALARM_A]) { alarm_callbacks[PERIPHERALS_ALARM_A](); } @@ -232,10 +222,6 @@ void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *_hrtc) { } void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *_hrtc) { - //TEMP - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,1); - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,0); - if (alarm_callbacks[PERIPHERALS_ALARM_B]) { alarm_callbacks[PERIPHERALS_ALARM_B](); } diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 22061257d5..4d11c0e61f 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -175,6 +175,7 @@ safe_mode_t port_init(void) { __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWR_EnableBkUpAccess(); + #if CIRCUITPY_ALARM // TODO: don't reset RTC entirely and move this back to alarm if (STM_ALARM_FLAG & 0x01) { // We've woken from deep sleep. Was it the WKUP pin or the RTC? @@ -185,6 +186,8 @@ safe_mode_t port_init(void) { alarm_set_wakeup_reason(STM_WAKEUP_GPIO); } } + #endif + __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); @@ -251,20 +254,6 @@ void reset_port(void) { #if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM exti_reset(); #endif - - // TEMP: set up interrupt logging pins - GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - // TEMP: ping port init - HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,1); - HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,0); } void reset_to_bootloader(void) { From 8ce89860e62cc7f37b579ee2970f3ab13b54e8a7 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Wed, 21 Apr 2021 17:34:13 -0400 Subject: [PATCH 11/16] Pass pre-commit formatting --- locale/circuitpython.pot | 30 ++++++++++++++++++++++++++---- ports/stm/peripherals/exti.h | 2 +- ports/stm/supervisor/port.c | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 5ddce15209..711d3f6419 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -837,6 +837,10 @@ msgstr "" msgid "Data too large for advertisement packet" msgstr "" +#: ports/stm/common-hal/alarm/pin/PinAlarm.c +msgid "Deep sleep pins must use a rising edge with pulldown" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -1653,6 +1657,10 @@ msgid "" "Only Windows format, uncompressed BMP supported: given header size is %d" msgstr "" +#: ports/stm/common-hal/alarm/pin/PinAlarm.c +msgid "Only edge detection is available on this hardware" +msgstr "" + #: shared-module/displayio/OnDiskBitmap.c #, c-format msgid "" @@ -1665,6 +1673,7 @@ msgid "Only one TouchAlarm can be set in deep sleep." msgstr "" #: ports/esp32s2/common-hal/alarm/time/TimeAlarm.c +#: ports/stm/common-hal/alarm/time/TimeAlarm.c msgid "Only one alarm.time alarm can be set." msgstr "" @@ -1740,6 +1749,10 @@ msgstr "" msgid "Permission denied" msgstr "" +#: ports/stm/common-hal/alarm/pin/PinAlarm.c +msgid "Pin cannot wake from Deep Sleep" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Pin count must be at least 1" msgstr "" @@ -1758,6 +1771,11 @@ msgstr "" msgid "Pin does not have ADC capabilities" msgstr "" +#: ports/stm/common-hal/alarm/pin/PinAlarm.c +#: ports/stm/common-hal/pulseio/PulseIn.c +msgid "Pin interrupt already in use" +msgstr "" + #: shared-bindings/adafruit_bus_device/SPIDevice.c #: shared-bindings/digitalio/DigitalInOut.c msgid "Pin is input only" @@ -1771,10 +1789,6 @@ msgstr "" msgid "Pin must support hardware interrupts" msgstr "" -#: ports/stm/common-hal/pulseio/PulseIn.c -msgid "Pin number already reserved by EXTI" -msgstr "" - #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format msgid "" @@ -1995,6 +2009,10 @@ msgstr "" msgid "Size not supported" msgstr "" +#: ports/stm/common-hal/alarm/SleepMemory.c +msgid "Sleep Memory not available" +msgstr "" + #: shared-bindings/alarm/SleepMemory.c shared-bindings/nvm/ByteArray.c msgid "Slice and value different lengths." msgstr "" @@ -2135,6 +2153,10 @@ msgstr "" msgid "Total data to write is larger than outgoing_packet_length" msgstr "" +#: ports/stm/common-hal/alarm/touch/TouchAlarm.c +msgid "Touch alarms not available" +msgstr "" + #: py/obj.c msgid "Traceback (most recent call last):\n" msgstr "" diff --git a/ports/stm/peripherals/exti.h b/ports/stm/peripherals/exti.h index 4a3358ec2e..7c0525aa36 100644 --- a/ports/stm/peripherals/exti.h +++ b/ports/stm/peripherals/exti.h @@ -42,4 +42,4 @@ void stm_peripherals_exti_set_callback(void(*callback)(uint8_t num), uint8_t num void stm_peripherals_exti_free(uint8_t num); IRQn_Type stm_peripherals_exti_get_irq(uint8_t num); -#endif // __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__ \ No newline at end of file +#endif // __MICROPY_INCLUDED_STM32_PERIPHERALS_EXTI_H__ diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 9fc2e465fe..df82398351 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -190,7 +190,7 @@ safe_mode_t port_init(void) { } } #endif - + __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); From 9fe8d61656bedd1ead7d8c707945fd38ece58337 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Wed, 28 Apr 2021 18:26:52 -0400 Subject: [PATCH 12/16] Fix broken MP macros from 1.11 merge --- ports/nrf/common-hal/alarm/pin/PinAlarm.c | 4 ++-- ports/nrf/common-hal/alarm/time/TimeAlarm.c | 4 ++-- ports/stm/common-hal/alarm/pin/PinAlarm.c | 4 ++-- ports/stm/common-hal/alarm/time/TimeAlarm.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/nrf/common-hal/alarm/pin/PinAlarm.c b/ports/nrf/common-hal/alarm/pin/PinAlarm.c index 59bb4a84a1..3c38cad1ac 100644 --- a/ports/nrf/common-hal/alarm/pin/PinAlarm.c +++ b/ports/nrf/common-hal/alarm/pin/PinAlarm.c @@ -93,7 +93,7 @@ bool alarm_pin_pinalarm_woke_us_up(void) { mp_obj_t alarm_pin_pinalarm_get_wakeup_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)) { + if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) { continue; } alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); @@ -197,7 +197,7 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob int pin_number = -1; for (size_t i = 0; i < n_alarms; i++) { - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { + if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) { continue; } alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); diff --git a/ports/nrf/common-hal/alarm/time/TimeAlarm.c b/ports/nrf/common-hal/alarm/time/TimeAlarm.c index 09409e7ce4..6fb1aea1ef 100644 --- a/ports/nrf/common-hal/alarm/time/TimeAlarm.c +++ b/ports/nrf/common-hal/alarm/time/TimeAlarm.c @@ -43,7 +43,7 @@ mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timeala 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 for (size_t i = 0; i < n_alarms; i++) { - if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { + if (mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) { return alarms[i]; } } @@ -82,7 +82,7 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ wakeup_time_saved = 0; for (size_t i = 0; i < n_alarms; i++) { - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { + if (!mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) { continue; } if (timealarm_set) { diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c index d2594c10d9..55029b7c4a 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.c +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -91,7 +91,7 @@ bool alarm_pin_pinalarm_woke_us_up(void) { mp_obj_t alarm_pin_pinalarm_get_wakeup_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)) { + if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) { continue; } alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); @@ -124,7 +124,7 @@ void alarm_pin_pinalarm_reset(void) { // Deep sleep alarms don't actually make use of EXTI, but we pretend they're the same. void alarm_pin_pinalarm_set_alarms(bool deep_sleep, 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)) { + if (mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) { alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); if (deep_sleep) { // Deep sleep only wakes on a rising edge from one pin, WKUP (PA00) diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c index fb3b5fa03d..f22cc5ef32 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.c +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -47,7 +47,7 @@ mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timeala 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 for (size_t i = 0; i < n_alarms; i++) { - if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { + if (mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) { return alarms[i]; } } @@ -76,7 +76,7 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ bool timealarm_set = false; alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL; for (size_t i = 0; i < n_alarms; i++) { - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { + if (!mp_obj_is_type(alarms[i], &alarm_time_timealarm_type)) { continue; } if (timealarm_set) { From bab5a22f0c27e5ccef9f4497b0a59005c819ec2b Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Thu, 29 Apr 2021 14:48:16 -0400 Subject: [PATCH 13/16] Fix build issues H7 compatibility problems in port.c and peripherals/exti NRF build failures due to new use of const for PinAlarm pin objects Isolated board flash overage on blackpill_with_flash, remove audio modules --- ports/nrf/common-hal/alarm/pin/PinAlarm.c | 4 ++-- ports/nrf/common-hal/alarm/pin/PinAlarm.h | 2 +- .../boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk | 3 +++ ports/stm/common-hal/alarm/pin/PinAlarm.h | 5 +++++ ports/stm/common-hal/alarm/time/TimeAlarm.h | 4 ++++ ports/stm/peripherals/exti.c | 4 ++++ ports/stm/supervisor/port.c | 3 +++ 7 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ports/nrf/common-hal/alarm/pin/PinAlarm.c b/ports/nrf/common-hal/alarm/pin/PinAlarm.c index 3c38cad1ac..747ff4c8ae 100644 --- a/ports/nrf/common-hal/alarm/pin/PinAlarm.c +++ b/ports/nrf/common-hal/alarm/pin/PinAlarm.c @@ -50,7 +50,7 @@ static bool pins_configured = false; extern uint32_t reset_reason_saved; extern void dbg_dump_GPIOregs(void); -void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, const mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { if (edge) { mp_raise_ValueError(translate("Cannot wake on pin edge. Only level.")); } @@ -62,7 +62,7 @@ void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu self->pull = pull; } -mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { +const mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { return self->pin; } diff --git a/ports/nrf/common-hal/alarm/pin/PinAlarm.h b/ports/nrf/common-hal/alarm/pin/PinAlarm.h index 69684386fa..42f9f115c8 100644 --- a/ports/nrf/common-hal/alarm/pin/PinAlarm.h +++ b/ports/nrf/common-hal/alarm/pin/PinAlarm.h @@ -29,7 +29,7 @@ typedef struct { mp_obj_base_t base; - mcu_pin_obj_t *pin; + const mcu_pin_obj_t *pin; bool value; bool pull; } alarm_pin_pinalarm_obj_t; diff --git a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk index 211a658967..4b53ef2da1 100644 --- a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk +++ b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk @@ -17,4 +17,7 @@ MCU_PACKAGE = UFQFPN48 LD_COMMON = boards/common_default.ld LD_FILE = boards/STM32F411_nvm_nofs.ld +# Too big for the flash +CIRCUITPY_AUDIOCORE = 0 +CIRCUITPY_AUDIOPWMIO = 0 CIRCUITPY_SYNTHIO = 0 diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.h b/ports/stm/common-hal/alarm/pin/PinAlarm.h index 2b94f1cb7e..bd18c840ff 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.h +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.h @@ -24,6 +24,9 @@ * THE SOFTWARE. */ +#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H +#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H + #include "py/obj.h" #include "py/objtuple.h" @@ -39,3 +42,5 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob 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); + +#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_PINALARM_H diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.h b/ports/stm/common-hal/alarm/time/TimeAlarm.h index 11c7a634c5..0d0c25deae 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.h +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.h @@ -24,6 +24,8 @@ * THE SOFTWARE. */ +#ifndef MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TIMEALARM_H +#define MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TIMEALARM_H #include "py/obj.h" @@ -40,3 +42,5 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ void alarm_time_timealarm_reset(void); void alarm_time_timealarm_prepare_for_deep_sleep(void); + +#endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM_TIMEALARM_H diff --git a/ports/stm/peripherals/exti.c b/ports/stm/peripherals/exti.c index fe17309f06..fe8fc14fbe 100644 --- a/ports/stm/peripherals/exti.c +++ b/ports/stm/peripherals/exti.c @@ -32,6 +32,8 @@ #include "peripherals/exti.h" +#if !(CPY_STM32H7) + STATIC bool stm_exti_reserved[STM32_GPIO_PORT_SIZE]; STATIC bool stm_exti_never_reset[STM32_GPIO_PORT_SIZE]; STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num); @@ -145,3 +147,5 @@ void EXTI15_10_IRQHandler(void) } } } + +#endif diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index df82398351..d435f1e175 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -175,6 +175,7 @@ safe_mode_t port_init(void) { HAL_Init(); // Turns on SysTick __HAL_RCC_SYSCFG_CLK_ENABLE(); + #if CPY_STM32F4 __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWR_EnableBkUpAccess(); @@ -194,6 +195,8 @@ safe_mode_t port_init(void) { __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); + #endif + stm32_peripherals_clocks_init(); stm32_peripherals_gpio_init(); stm32_peripherals_rtc_init(); From 07b86fcb765484ae2cbfd414c4eb0891f29a597f Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Thu, 29 Apr 2021 17:28:06 -0400 Subject: [PATCH 14/16] fix sleepmemory object redefine error --- ports/stm/common-hal/alarm/__init__.c | 8 ++++++++ ports/stm/common-hal/alarm/__init__.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 0d8f8a5ff9..4ebadd7c63 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -31,6 +31,7 @@ #include "lib/utils/interrupt_char.h" #include "shared-bindings/alarm/__init__.h" +#include "shared-bindings/alarm/SleepMemory.h" #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h" @@ -39,6 +40,13 @@ #include "supervisor/port.h" #include "supervisor/shared/workflow.h" +// Singleton instance of SleepMemory. +const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { + .base = { + .type = &alarm_sleep_memory_type, + }, +}; + STATIC uint8_t true_deep_wake_reason; STATIC mp_obj_t most_recent_alarm; diff --git a/ports/stm/common-hal/alarm/__init__.h b/ports/stm/common-hal/alarm/__init__.h index 0bfafbcee2..5f1532fc37 100644 --- a/ports/stm/common-hal/alarm/__init__.h +++ b/ports/stm/common-hal/alarm/__init__.h @@ -29,7 +29,7 @@ #include "common-hal/alarm/SleepMemory.h" -const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; +extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; #define STM_WAKEUP_UNDEF 0 #define STM_WAKEUP_GPIO 1 From 525b34b04253fcb156f83db93dbf3b1b03dd5848 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Mon, 10 May 2021 18:04:43 -0400 Subject: [PATCH 15/16] Fix formatting and broken links Implmements missed pre-commit changes for all files, and fixes links broken by cleanup in #4698 --- ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 2 +- ports/stm/common-hal/alarm/SleepMemory.c | 4 +-- ports/stm/common-hal/alarm/__init__.c | 6 ++-- ports/stm/common-hal/alarm/pin/PinAlarm.c | 4 +-- ports/stm/common-hal/alarm/time/TimeAlarm.c | 2 +- ports/stm/common-hal/pulseio/PulseIn.c | 14 ++++----- ports/stm/peripherals/exti.c | 31 +++++++------------ ports/stm/peripherals/exti.h | 2 +- ports/stm/peripherals/rtc.c | 14 ++++----- ports/stm/peripherals/rtc.h | 6 ++-- ports/stm/supervisor/port.c | 4 +-- 11 files changed, 42 insertions(+), 47 deletions(-) diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index 587e7de726..34c8a5690e 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -102,7 +102,7 @@ bool alarm_pin_pinalarm_woke_us_up(void) { mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { // For light sleep, we check if we match any existing alarms - uint64_t pin_status = ((uint64_t) pin_63_32_status) << 32 | pin_31_0_status; + uint64_t pin_status = ((uint64_t)pin_63_32_status) << 32 | pin_31_0_status; for (size_t i = 0; i < n_alarms; i++) { if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) { continue; diff --git a/ports/stm/common-hal/alarm/SleepMemory.c b/ports/stm/common-hal/alarm/SleepMemory.c index 0829902a22..3b89efbca3 100644 --- a/ports/stm/common-hal/alarm/SleepMemory.c +++ b/ports/stm/common-hal/alarm/SleepMemory.c @@ -38,12 +38,12 @@ uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self return 0; } -bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t* values, uint32_t len) { +bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, const uint8_t *values, uint32_t len) { mp_raise_NotImplementedError(translate("Sleep Memory not available")); return false; } -void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t* values, uint32_t len) { +void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, uint32_t start_index, uint8_t *values, uint32_t len) { mp_raise_NotImplementedError(translate("Sleep Memory not available")); return; } diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 4ebadd7c63..59aa7c4445 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -38,7 +38,7 @@ #include "shared-bindings/microcontroller/__init__.h" #include "supervisor/port.h" -#include "supervisor/shared/workflow.h" +#include "supervisor/workflow.h" // Singleton instance of SleepMemory. const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { @@ -167,7 +167,9 @@ void NORETURN common_hal_alarm_enter_deep_sleep(void) { HAL_PWR_EnterSTANDBYMode(); // The above shuts down RAM, so we should never hit this - while(1); + while (1) { + ; + } } void common_hal_alarm_pretending_deep_sleep(void) { diff --git a/ports/stm/common-hal/alarm/pin/PinAlarm.c b/ports/stm/common-hal/alarm/pin/PinAlarm.c index 55029b7c4a..381a13b220 100644 --- a/ports/stm/common-hal/alarm/pin/PinAlarm.c +++ b/ports/stm/common-hal/alarm/pin/PinAlarm.c @@ -94,7 +94,7 @@ mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *al if (!mp_obj_is_type(alarms[i], &alarm_pin_pinalarm_type)) { continue; } - alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); if (alarm_pin_triggered & (1 << alarm->pin->number)) { return alarms[i]; } @@ -125,7 +125,7 @@ void alarm_pin_pinalarm_reset(void) { void alarm_pin_pinalarm_set_alarms(bool deep_sleep, 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)) { - alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); if (deep_sleep) { // Deep sleep only wakes on a rising edge from one pin, WKUP (PA00) // All pin settings are handled automatically. diff --git a/ports/stm/common-hal/alarm/time/TimeAlarm.c b/ports/stm/common-hal/alarm/time/TimeAlarm.c index f22cc5ef32..2c38066d3a 100644 --- a/ports/stm/common-hal/alarm/time/TimeAlarm.c +++ b/ports/stm/common-hal/alarm/time/TimeAlarm.c @@ -82,7 +82,7 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ if (timealarm_set) { mp_raise_ValueError(translate("Only one alarm.time alarm can be set.")); } - timealarm = MP_OBJ_TO_PTR(alarms[i]); + timealarm = MP_OBJ_TO_PTR(alarms[i]); timealarm_set = true; } if (!timealarm_set) { diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c index e31068ab55..27ef978dac 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.c +++ b/ports/stm/common-hal/pulseio/PulseIn.c @@ -40,7 +40,7 @@ #include STM32_HAL_H #define STM32_GPIO_PORT_SIZE 16 -STATIC pulseio_pulsein_obj_t* callback_obj_ref[STM32_GPIO_PORT_SIZE]; +STATIC pulseio_pulsein_obj_t *callback_obj_ref[STM32_GPIO_PORT_SIZE]; STATIC TIM_HandleTypeDef tim_handle; STATIC uint32_t overflow_count = 0; @@ -64,7 +64,7 @@ STATIC void pulsein_exti_event_handler(uint8_t num) { // Interrupt register must be cleared manually EXTI->PR = 1 << num; - pulseio_pulsein_obj_t* self = callback_obj_ref[num]; + pulseio_pulsein_obj_t *self = callback_obj_ref[num]; if (!self) { return; } @@ -118,7 +118,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu // Allocate pulse buffer self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t), false); if (self->buffer == NULL) { - //TODO: free the EXTI here? + // TODO: free the EXTI here? mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), maxlen * sizeof(uint16_t)); } @@ -189,7 +189,7 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t *self) { if (common_hal_pulseio_pulsein_deinited(self)) { return; } - //Remove pulsein slot from shared array + // Remove pulsein slot from shared array callback_obj_ref[self->pin->number] = NULL; stm_peripherals_exti_free(self->pin->number); reset_pin_number(self->pin->port, self->pin->number); @@ -201,7 +201,7 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t *self) { } } -void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) { +void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t *self) { stm_peripherals_exti_disable(self->pin->number); self->paused = true; } @@ -239,14 +239,14 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t *self, uint16_t tri stm_peripherals_exti_enable(self->pin->number); } -void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) { +void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t *self) { stm_peripherals_exti_disable(self->pin->number); self->start = 0; self->len = 0; stm_peripherals_exti_enable(self->pin->number); } -uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) { +uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t *self, int16_t index) { stm_peripherals_exti_disable(self->pin->number); if (index < 0) { index += self->len; diff --git a/ports/stm/peripherals/exti.c b/ports/stm/peripherals/exti.c index fe8fc14fbe..3ba943a208 100644 --- a/ports/stm/peripherals/exti.c +++ b/ports/stm/peripherals/exti.c @@ -39,7 +39,7 @@ STATIC bool stm_exti_never_reset[STM32_GPIO_PORT_SIZE]; STATIC void (*stm_exti_callback[STM32_GPIO_PORT_SIZE])(uint8_t num); void exti_reset(void) { - for (size_t i = 0;i < STM32_GPIO_PORT_SIZE; i++) { + for (size_t i = 0; i < STM32_GPIO_PORT_SIZE; i++) { if (!stm_exti_never_reset[i]) { stm_exti_reserved[i] = false; stm_exti_callback[i] = NULL; @@ -79,7 +79,7 @@ void stm_peripherals_exti_disable(uint8_t num) { HAL_NVIC_DisableIRQ(stm_peripherals_exti_get_irq(num)); } -void stm_peripherals_exti_set_callback(void(*callback)(uint8_t num), uint8_t number) { +void stm_peripherals_exti_set_callback(void (*callback)(uint8_t num), uint8_t number) { stm_exti_callback[number] = callback; } @@ -98,7 +98,7 @@ IRQn_Type stm_peripherals_exti_get_irq(uint8_t num) { return EXTI3_IRQn; } else if (num == 4) { return EXTI4_IRQn; - } else if (num >= 5 && num <= 9 ) { + } else if (num >= 5 && num <= 9) { return EXTI9_5_IRQn; } else if (num >= 10 && num <= 15) { return EXTI15_10_IRQn; @@ -107,42 +107,35 @@ IRQn_Type stm_peripherals_exti_get_irq(uint8_t num) { } } -void EXTI0_IRQHandler(void) -{ +void EXTI0_IRQHandler(void) { stm_exti_callback[0](0); } -void EXTI1_IRQHandler(void) -{ +void EXTI1_IRQHandler(void) { stm_exti_callback[1](1); } -void EXTI2_IRQHandler(void) -{ +void EXTI2_IRQHandler(void) { stm_exti_callback[2](2); } -void EXTI3_IRQHandler(void) -{ +void EXTI3_IRQHandler(void) { stm_exti_callback[3](3); } -void EXTI4_IRQHandler(void) -{ +void EXTI4_IRQHandler(void) { stm_exti_callback[4](4); } -void EXTI9_5_IRQHandler(void) -{ +void EXTI9_5_IRQHandler(void) { uint32_t pending = EXTI->PR; for (uint i = 5; i <= 9; i++) { - if(pending & (1 << i)) { + if (pending & (1 << i)) { stm_exti_callback[i](i); } } } -void EXTI15_10_IRQHandler(void) -{ +void EXTI15_10_IRQHandler(void) { uint32_t pending = EXTI->PR; for (uint i = 10; i <= 15; i++) { - if(pending & (1 << i)) { + if (pending & (1 << i)) { stm_exti_callback[i](i); } } diff --git a/ports/stm/peripherals/exti.h b/ports/stm/peripherals/exti.h index 7c0525aa36..09936fb283 100644 --- a/ports/stm/peripherals/exti.h +++ b/ports/stm/peripherals/exti.h @@ -38,7 +38,7 @@ bool stm_peripherals_exti_is_free(uint8_t num); bool stm_peripherals_exti_reserve(uint8_t num); void stm_peripherals_exti_enable(uint8_t num); void stm_peripherals_exti_disable(uint8_t num); -void stm_peripherals_exti_set_callback(void(*callback)(uint8_t num), uint8_t number); +void stm_peripherals_exti_set_callback(void (*callback)(uint8_t num), uint8_t number); void stm_peripherals_exti_free(uint8_t num); IRQn_Type stm_peripherals_exti_get_irq(uint8_t num); diff --git a/ports/stm/peripherals/rtc.c b/ports/stm/peripherals/rtc.c index 8a1805c7ba..5f8f05b2bf 100644 --- a/ports/stm/peripherals/rtc.c +++ b/ports/stm/peripherals/rtc.c @@ -78,7 +78,7 @@ void stm32_peripherals_rtc_init(void) { // This function is called often for timing so we cache the seconds elapsed computation based on the // register value. The STM HAL always does shifts and conversion if we use it directly. -uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t* subticks) { +uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks) { // Disable IRQs to ensure we read all of the RTC registers as close in time as possible. Read // SSR twice to make sure we didn't read across a tick. __disable_irq(); @@ -122,16 +122,16 @@ uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t* subticks) { *subticks = subseconds % 32; } - uint64_t raw_ticks = ((uint64_t) TICK_DIVISOR) * (seconds_to_date + seconds_to_minute + seconds) + subseconds / 32; + uint64_t raw_ticks = ((uint64_t)TICK_DIVISOR) * (seconds_to_date + seconds_to_minute + seconds) + subseconds / 32; return raw_ticks; } -void stm32_peripherals_rtc_assign_wkup_callback(void(*callback)(void)) { +void stm32_peripherals_rtc_assign_wkup_callback(void (*callback)(void)) { wkup_callback = callback; } void stm32_peripherals_rtc_set_wakeup_mode_seconds(uint32_t seconds) { - //prep stuff from CubeMX + // prep stuff from CubeMX __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); @@ -159,8 +159,8 @@ void stm32_peripherals_rtc_reset_alarms(void) { HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_B); } -void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) { - alarm_callbacks[alarm_idx] = callback; +void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void (*callback)(void)) { + alarm_callbacks[alarm_idx] = callback; } void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks) { @@ -183,7 +183,7 @@ void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks) { } alarm.AlarmTime.SubSeconds = rtc_clock_frequency - 1 - - ((raw_ticks % TICK_DIVISOR) * 32); + ((raw_ticks % TICK_DIVISOR) * 32); alarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; alarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_SET; // Masking here means that the bits are ignored so we set none of them. diff --git a/ports/stm/peripherals/rtc.h b/ports/stm/peripherals/rtc.h index 2dea6920a4..65cae14d1c 100644 --- a/ports/stm/peripherals/rtc.h +++ b/ports/stm/peripherals/rtc.h @@ -35,16 +35,16 @@ uint32_t stm32_peripherals_get_rtc_freq(void); void stm32_peripherals_rtc_init(void); -uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t* subticks); +uint64_t stm32_peripherals_rtc_raw_ticks(uint8_t *subticks); -void stm32_peripherals_rtc_assign_wkup_callback(void(*callback)(void)); +void stm32_peripherals_rtc_assign_wkup_callback(void (*callback)(void)); void stm32_peripherals_rtc_set_wakeup_mode_seconds(uint32_t seconds); void stm32_peripherals_rtc_set_wakeup_mode_tick(void); void stm32_peripherals_rtc_enable_wakeup_timer(void); void stm32_peripherals_rtc_disable_wakeup_timer(void); void stm32_peripherals_rtc_reset_alarms(void); -void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void(*callback)(void)) ; +void stm32_peripherals_rtc_assign_alarm_callback(uint8_t alarm_idx, void (*callback)(void)); void stm32_peripherals_rtc_set_alarm(uint8_t alarm_idx, uint32_t ticks); bool stm32_peripherals_rtc_alarm_triggered(uint8_t alarm_idx); diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index d435f1e175..b62fe9d24a 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -261,7 +261,7 @@ void reset_port(void) { pwmout_reset(); #endif #if CIRCUITPY_PULSEIO || CIRCUITPY_ALARM - exti_reset(); + exti_reset(); #endif } @@ -334,7 +334,7 @@ __attribute__((used)) void HardFault_Handler(void) { } } -uint64_t port_get_raw_ticks(uint8_t* subticks) { +uint64_t port_get_raw_ticks(uint8_t *subticks) { return stm32_peripherals_rtc_raw_ticks(subticks); } From 849e3a7319e337e0565715c44146ce2d88e123b3 Mon Sep 17 00:00:00 2001 From: Lucian Copeland Date: Thu, 13 May 2021 11:24:27 -0400 Subject: [PATCH 16/16] Style fixes, submodules --- frozen/Adafruit_CircuitPython_HID | 2 +- frozen/Adafruit_CircuitPython_SimpleMath | 2 +- ports/stm/common-hal/alarm/__init__.c | 8 ++++---- ports/stm/common-hal/alarm/__init__.h | 12 +++++++----- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/frozen/Adafruit_CircuitPython_HID b/frozen/Adafruit_CircuitPython_HID index 829ba0f0a2..de68b7d457 160000 --- a/frozen/Adafruit_CircuitPython_HID +++ b/frozen/Adafruit_CircuitPython_HID @@ -1 +1 @@ -Subproject commit 829ba0f0a2d8a63f7d0215c6c9fc821e14e52a93 +Subproject commit de68b7d4575151c1648c734559e59c2932965939 diff --git a/frozen/Adafruit_CircuitPython_SimpleMath b/frozen/Adafruit_CircuitPython_SimpleMath index cdf9944730..5f382650e6 160000 --- a/frozen/Adafruit_CircuitPython_SimpleMath +++ b/frozen/Adafruit_CircuitPython_SimpleMath @@ -1 +1 @@ -Subproject commit cdf99447307473080b2f2e95e7c3667247095ac0 +Subproject commit 5f382650e62e05cc72a67dbedce13d706d699621 diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 59aa7c4445..e0b900bbfc 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -47,7 +47,7 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { }, }; -STATIC uint8_t true_deep_wake_reason; +STATIC stm_sleep_source_t true_deep_wake_reason; STATIC mp_obj_t most_recent_alarm; void alarm_reset(void) { @@ -60,11 +60,11 @@ void alarm_reset(void) { // Kind of a hack, required as RTC is reset in port.c // TODO: in the future, don't reset it at all, just override critical flags -void alarm_set_wakeup_reason(uint8_t reason) { +void alarm_set_wakeup_reason(stm_sleep_source_t reason) { true_deep_wake_reason = reason; } -STATIC uint8_t _get_wakeup_cause(void) { +STATIC stm_sleep_source_t _get_wakeup_cause(void) { // If in light/fake sleep, check modules if (alarm_pin_pinalarm_woke_us_up()) { return STM_WAKEUP_GPIO; @@ -84,7 +84,7 @@ bool common_hal_alarm_woken_from_sleep(void) { } STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { - uint8_t cause = _get_wakeup_cause(); + stm_sleep_source_t cause = _get_wakeup_cause(); switch (cause) { case STM_WAKEUP_RTC: { return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms); diff --git a/ports/stm/common-hal/alarm/__init__.h b/ports/stm/common-hal/alarm/__init__.h index 5f1532fc37..4ec7222d2e 100644 --- a/ports/stm/common-hal/alarm/__init__.h +++ b/ports/stm/common-hal/alarm/__init__.h @@ -31,13 +31,15 @@ extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; -#define STM_WAKEUP_UNDEF 0 -#define STM_WAKEUP_GPIO 1 -#define STM_WAKEUP_RTC 2 +typedef enum { + STM_WAKEUP_UNDEF, + STM_WAKEUP_GPIO, + STM_WAKEUP_RTC +} stm_sleep_source_t; -#define STM_ALARM_FLAG RTC->BKP0R +#define STM_ALARM_FLAG (RTC->BKP0R) -extern void alarm_set_wakeup_reason(uint8_t reason); +extern void alarm_set_wakeup_reason(stm_sleep_source_t reason); extern void alarm_reset(void); #endif // MICROPY_INCLUDED_STM32_COMMON_HAL_ALARM__INIT__H