From 85dadf3a561c21e284d5daf42b1b3e367ce7ebc6 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 15 Oct 2020 16:59:29 -0700 Subject: More API changes --- shared-bindings/supervisor/RunReason.c | 62 ++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 shared-bindings/supervisor/RunReason.c (limited to 'shared-bindings/supervisor/RunReason.c') diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c new file mode 100644 index 000000000..5233cf959 --- /dev/null +++ b/shared-bindings/supervisor/RunReason.c @@ -0,0 +1,62 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft 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/enum.h" + +#include "shared-bindings/supervisor/RunReason.h" + +MAKE_ENUM_VALUE(canio_bus_state_type, run_reason, ERROR_ACTIVE, RUN_REASON_STARTUP); +MAKE_ENUM_VALUE(canio_bus_state_type, bus_state, ERROR_PASSIVE, RUN_REASON_AUTORELOAD); +MAKE_ENUM_VALUE(canio_bus_state_type, bus_state, ERROR_WARNING, RUN_REASON_SUPERVISOR_RELOAD); +MAKE_ENUM_VALUE(canio_bus_state_type, bus_state, BUS_OFF, RUN_REASON_RELOAD_HOTKEY); + +//| class RunReason: +//| """The state of the CAN bus""" +//| +//| STARTUP: object +//| """The first VM was run after the microcontroller started up. See `microcontroller.start_reason` +//| for more detail why the microcontroller was started.""" +//| +//| AUTORELOAD: object +//| """The VM was run due to a USB write to the filesystem.""" +//| +//| SUPERVISOR_RELOAD: object +//| """The VM was run due to a call to `supervisor.reload()`.""" +//| +//| RELOAD_HOTKEY: object +//| """The VM was run due CTRL-D.""" +//| +MAKE_ENUM_MAP(canio_bus_state) { + MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_ACTIVE), + MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_PASSIVE), + MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_WARNING), + MAKE_ENUM_MAP_ENTRY(bus_state, BUS_OFF), +}; +STATIC MP_DEFINE_CONST_DICT(canio_bus_state_locals_dict, canio_bus_state_locals_table); + +MAKE_PRINTER(canio, canio_bus_state); + +MAKE_ENUM_TYPE(canio, BusState, canio_bus_state); -- cgit v1.2.3 From 75559f35ccc946dfd292e25671919e5d5b3bd7a6 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 21 Nov 2020 23:29:52 -0500 Subject: wip: ResetReason to microcontroller.cpu --- locale/circuitpython.pot | 18 ++--- main.c | 9 +-- .../common-hal/microcontroller/Processor.c | 5 ++ .../common-hal/microcontroller/__init__.c | 4 -- ports/cxd56/common-hal/microcontroller/Processor.c | 5 ++ ports/cxd56/common-hal/microcontroller/__init__.c | 4 -- ports/esp32s2/common-hal/alarm/__init__.c | 17 ----- .../esp32s2/common-hal/microcontroller/Processor.c | 23 ++++++- .../esp32s2/common-hal/microcontroller/__init__.c | 4 -- ports/litex/common-hal/microcontroller/Processor.c | 8 ++- ports/litex/common-hal/microcontroller/__init__.c | 4 -- .../common-hal/microcontroller/Processor.c | 5 ++ .../common-hal/microcontroller/__init__.c | 4 -- ports/nrf/common-hal/microcontroller/Processor.c | 8 ++- ports/nrf/common-hal/microcontroller/__init__.c | 4 -- ports/stm/common-hal/microcontroller/Processor.c | 9 ++- ports/stm/common-hal/microcontroller/__init__.c | 4 -- py/circuitpy_defns.mk | 2 +- shared-bindings/_typing/__init__.pyi | 11 ++-- shared-bindings/alarm/ResetReason.c | 77 ---------------------- shared-bindings/alarm/ResetReason.h | 47 ------------- shared-bindings/alarm/__init__.c | 74 ++++++++++++--------- shared-bindings/alarm/__init__.h | 6 +- shared-bindings/alarm/pin/PinAlarm.c | 28 ++++---- shared-bindings/alarm/time/DurationAlarm.c | 11 ++-- shared-bindings/microcontroller/Processor.c | 18 +++++ shared-bindings/microcontroller/Processor.h | 3 +- shared-bindings/microcontroller/ResetReason.c | 72 ++++++++++++++++++++ shared-bindings/microcontroller/ResetReason.h | 51 ++++++++++++++ shared-bindings/microcontroller/__init__.c | 9 --- shared-bindings/microcontroller/__init__.h | 4 +- shared-bindings/supervisor/RunReason.c | 38 +++++------ shared-bindings/supervisor/RunReason.h | 4 +- shared-bindings/supervisor/Runtime.c | 10 +-- supervisor/shared/safe_mode.c | 14 ++-- 35 files changed, 314 insertions(+), 300 deletions(-) delete mode 100644 shared-bindings/alarm/ResetReason.c delete mode 100644 shared-bindings/alarm/ResetReason.h create mode 100644 shared-bindings/microcontroller/ResetReason.c create mode 100644 shared-bindings/microcontroller/ResetReason.h (limited to 'shared-bindings/supervisor/RunReason.c') diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 969f3f36f..1dae9547a 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-11-19 00:28-0500\n" +"POT-Creation-Date: 2020-11-21 12:36-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -990,7 +990,7 @@ msgstr "" msgid "I2SOut not available" msgstr "" -#: ports/esp32s2/common-hal/alarm_io/__init__.c +#: ports/esp32s2/common-hal/alarm/pin/__init__.c msgid "IOs 0, 2 & 4 do not support internal pullup in sleep" msgstr "" @@ -2449,6 +2449,10 @@ msgstr "" msgid "division by zero" msgstr "" +#: ports/esp32s2/common-hal/alarm/time/DurationAlarm.c +msgid "duration out of range" +msgstr "" + #: py/objdeque.c msgid "empty" msgstr "" @@ -2809,7 +2813,7 @@ msgstr "" msgid "invalid syntax for number" msgstr "" -#: ports/esp32s2/common-hal/alarm_io/__init__.c +#: ports/esp32s2/common-hal/alarm/pin/__init__.c msgid "io must be rtc io" msgstr "" @@ -3434,10 +3438,6 @@ msgstr "" msgid "threshold must be in the range 0-65536" msgstr "" -#: ports/esp32s2/common-hal/alarm_time/__init__.c -msgid "time out of range" -msgstr "" - #: shared-bindings/time/__init__.c msgid "time.struct_time() takes a 9-sequence" msgstr "" @@ -3484,7 +3484,7 @@ msgstr "" msgid "trapz is defined for 1D arrays of equal length" msgstr "" -#: ports/esp32s2/common-hal/alarm_io/__init__.c +#: ports/esp32s2/common-hal/alarm/pin/__init__.c msgid "trigger level must be 0 or 1" msgstr "" @@ -3630,7 +3630,7 @@ msgstr "" msgid "vectors must have same lengths" msgstr "" -#: ports/esp32s2/common-hal/alarm_io/__init__.c +#: ports/esp32s2/common-hal/alarm/pin/__init__.c msgid "wakeup conflict" msgstr "" diff --git a/main.c b/main.c index 30ceaeaa6..8938d714a 100755 --- a/main.c +++ b/main.c @@ -330,7 +330,7 @@ bool run_code_py(safe_mode_t safe_mode) { #if CIRCUITPY_ALARM // If USB isn't enumerated then deep sleep. if (ok && !supervisor_workflow_active() && supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024) { - common_hal_mcu_deep_sleep(); + common_hal_alarm_restart_on_alarm(0, NULL); } #endif // Show the animation every N seconds. @@ -430,14 +430,9 @@ void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { if (!skip_boot_output) { // Wait 1.5 seconds before opening CIRCUITPY_BOOT_OUTPUT_FILE for write, // in case power is momentary or will fail shortly due to, say a low, battery. -#if CIRCUITPY_ALARM - if (common_hal_alarm_get_reset_reason() == RESET_REASON_POWER_ON) { -#endif + if (common_hal_mcu_processor_get_reset_reason() == RESET_REASON_POWER_ON) { mp_hal_delay_ms(1500); -#if CIRCUITPY_ALARM } -#endif - // USB isn't up, so we can write the file. filesystem_set_internal_writable_by_usb(false); f_open(fs, boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS); diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c index ba8daf3fb..995521265 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Processor.c +++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c @@ -65,6 +65,7 @@ #include "py/mphal.h" #include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" #include "samd/adc.h" @@ -349,3 +350,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { } } } + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + return RESET_REASON_POWER_ON; +} diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index ca39f2838..50a1ec038 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -84,10 +84,6 @@ void common_hal_mcu_reset(void) { reset(); } -void common_hal_mcu_deep_sleep(void) { - //deep sleep call here -} - // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/cxd56/common-hal/microcontroller/Processor.c b/ports/cxd56/common-hal/microcontroller/Processor.c index 1eddbb01d..bd778e80d 100644 --- a/ports/cxd56/common-hal/microcontroller/Processor.c +++ b/ports/cxd56/common-hal/microcontroller/Processor.c @@ -31,6 +31,7 @@ // For NAN: remove when not needed. #include #include "py/mphal.h" +#include "shared-bindings/microcontroller/ResetReason.h" uint32_t common_hal_mcu_processor_get_frequency(void) { return cxd56_get_cpu_baseclk(); @@ -47,3 +48,7 @@ float common_hal_mcu_processor_get_voltage(void) { void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { boardctl(BOARDIOC_UNIQUEID, (uintptr_t) raw_id); } + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + return RESET_REASON_POWER_ON; +} diff --git a/ports/cxd56/common-hal/microcontroller/__init__.c b/ports/cxd56/common-hal/microcontroller/__init__.c index 57140dec7..7aa3b839d 100644 --- a/ports/cxd56/common-hal/microcontroller/__init__.c +++ b/ports/cxd56/common-hal/microcontroller/__init__.c @@ -81,10 +81,6 @@ void common_hal_mcu_reset(void) { boardctl(BOARDIOC_RESET, 0); } -void common_hal_mcu_deep_sleep(void) { - //deep sleep call here -} - STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_UART2_RXD), MP_ROM_PTR(&pin_UART2_RXD) }, { MP_ROM_QSTR(MP_QSTR_UART2_TXD), MP_ROM_PTR(&pin_UART2_TXD) }, diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index d2ac3981e..e33534550 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -35,23 +35,6 @@ void common_hal_alarm_disable_all(void) { esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } -alarm_reset_reason_t common_hal_alarm_get_reset_reason(void) { - switch (esp_sleep_get_wakeup_cause()) { - case ESP_SLEEP_WAKEUP_TIMER: - return RESET_REASON_DEEP_SLEEP_ALARM; - - case ESP_SLEEP_WAKEUP_EXT0: - return RESET_REASON_DEEP_SLEEP_ALARM; - - case ESP_SLEEP_WAKEUP_TOUCHPAD: - //TODO: implement TouchIO - case ESP_SLEEP_WAKEUP_UNDEFINED: - default: - return RESET_REASON_INVALID; - } -} - - mp_obj_t common_hal_alarm_get_wake_alarm(void) { switch (esp_sleep_get_wakeup_cause()) { case ESP_SLEEP_WAKEUP_TIMER: { diff --git a/ports/esp32s2/common-hal/microcontroller/Processor.c b/ports/esp32s2/common-hal/microcontroller/Processor.c index b81521601..bd625dc6e 100644 --- a/ports/esp32s2/common-hal/microcontroller/Processor.c +++ b/ports/esp32s2/common-hal/microcontroller/Processor.c @@ -28,8 +28,9 @@ #include #include -#include "common-hal/microcontroller/Processor.h" #include "py/runtime.h" + +#include "common-hal/microcontroller/Processor.h" #include "supervisor/shared/translate.h" #include "soc/efuse_reg.h" @@ -74,3 +75,23 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { *ptr-- = swap_nibbles(mac_address_part & 0xff); mac_address_part >>= 8; *ptr-- = swap_nibbles(mac_address_part & 0xff); } + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_TIMER: + return RESET_REASON_DEEP_SLEEP_ALARM; + + case ESP_SLEEP_WAKEUP_EXT0: + return RESET_REASON_DEEP_SLEEP_ALARM; + + case ESP_SLEEP_WAKEUP_TOUCHPAD: + //TODO: implement TouchIO + case ESP_SLEEP_WAKEUP_UNDEFINED: + default: + return RESET_REASON_POWER_APPLIED; + } +} + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + return RESET_REASON_POWER_ON; +} diff --git a/ports/esp32s2/common-hal/microcontroller/__init__.c b/ports/esp32s2/common-hal/microcontroller/__init__.c index 79cb93893..3056c6565 100644 --- a/ports/esp32s2/common-hal/microcontroller/__init__.c +++ b/ports/esp32s2/common-hal/microcontroller/__init__.c @@ -79,10 +79,6 @@ void common_hal_mcu_reset(void) { while(1); } -void common_hal_mcu_deep_sleep(void) { - esp_deep_sleep_start(); -} - // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/litex/common-hal/microcontroller/Processor.c b/ports/litex/common-hal/microcontroller/Processor.c index 9d2b05aad..013a7ca03 100644 --- a/ports/litex/common-hal/microcontroller/Processor.c +++ b/ports/litex/common-hal/microcontroller/Processor.c @@ -26,8 +26,10 @@ */ #include -#include "common-hal/microcontroller/Processor.h" #include "py/runtime.h" + +#include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" #include "supervisor/shared/translate.h" #include "csr.h" @@ -62,3 +64,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { raw_id[13] = csr_readl(CSR_VERSION_SEED_ADDR + 8); raw_id[14] = csr_readl(CSR_VERSION_SEED_ADDR + 12); } + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + return RESET_REASON_POWER_ON; +} diff --git a/ports/litex/common-hal/microcontroller/__init__.c b/ports/litex/common-hal/microcontroller/__init__.c index e6f50ed5a..3c9166114 100644 --- a/ports/litex/common-hal/microcontroller/__init__.c +++ b/ports/litex/common-hal/microcontroller/__init__.c @@ -89,10 +89,6 @@ void common_hal_mcu_reset(void) { while(1); } -void common_hal_mcu_deep_sleep(void) { - //deep sleep call here -} - // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/mimxrt10xx/common-hal/microcontroller/Processor.c b/ports/mimxrt10xx/common-hal/microcontroller/Processor.c index f3a578014..28fe67db7 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/Processor.c +++ b/ports/mimxrt10xx/common-hal/microcontroller/Processor.c @@ -28,6 +28,7 @@ #include #include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" #include "fsl_tempmon.h" #include "fsl_ocotp.h" @@ -70,3 +71,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { } OCOTP_Deinit(OCOTP); } + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + return RESET_REASON_POWER_ON; +} diff --git a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c index 0329ced69..6a8537e2d 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c +++ b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c @@ -86,10 +86,6 @@ void common_hal_mcu_reset(void) { NVIC_SystemReset(); } -void common_hal_mcu_deep_sleep(void) { - //deep sleep call here -} - // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/nrf/common-hal/microcontroller/Processor.c b/ports/nrf/common-hal/microcontroller/Processor.c index 03d9c4d3f..e2695139c 100644 --- a/ports/nrf/common-hal/microcontroller/Processor.c +++ b/ports/nrf/common-hal/microcontroller/Processor.c @@ -24,8 +24,10 @@ * THE SOFTWARE. */ -#include "common-hal/microcontroller/Processor.h" #include "py/runtime.h" + +#include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" #include "supervisor/shared/translate.h" #include "nrfx_saadc.h" @@ -119,3 +121,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { ((uint32_t*) raw_id)[i] = NRF_FICR->DEVICEID[i]; } } + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + return RESET_REASON_POWER_ON; +} diff --git a/ports/nrf/common-hal/microcontroller/__init__.c b/ports/nrf/common-hal/microcontroller/__init__.c index 9911896bf..06aac9409 100644 --- a/ports/nrf/common-hal/microcontroller/__init__.c +++ b/ports/nrf/common-hal/microcontroller/__init__.c @@ -95,10 +95,6 @@ void common_hal_mcu_reset(void) { reset_cpu(); } -void common_hal_mcu_deep_sleep(void) { - //deep sleep call here -} - // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/stm/common-hal/microcontroller/Processor.c b/ports/stm/common-hal/microcontroller/Processor.c index 8dc968b36..d77d287a9 100644 --- a/ports/stm/common-hal/microcontroller/Processor.c +++ b/ports/stm/common-hal/microcontroller/Processor.c @@ -25,9 +25,12 @@ */ #include -#include "common-hal/microcontroller/Processor.h" #include "py/runtime.h" + +#include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" #include "supervisor/shared/translate.h" + #include STM32_HAL_H #if CPY_STM32F4 @@ -138,3 +141,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { } #endif } + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + return RESET_REASON_POWER_ON; +} diff --git a/ports/stm/common-hal/microcontroller/__init__.c b/ports/stm/common-hal/microcontroller/__init__.c index bc81b0e4f..a827399cc 100644 --- a/ports/stm/common-hal/microcontroller/__init__.c +++ b/ports/stm/common-hal/microcontroller/__init__.c @@ -81,10 +81,6 @@ void common_hal_mcu_reset(void) { NVIC_SystemReset(); } -void common_hal_mcu_deep_sleep(void) { - //deep sleep call here -} - // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index d788a5411..2731f2ae8 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -394,7 +394,6 @@ $(filter $(SRC_PATTERNS), \ _bleio/Attribute.c \ _bleio/ScanEntry.c \ _eve/__init__.c \ - alarm/ResetReason.c \ camera/ImageFormat.c \ canio/Match.c \ digitalio/Direction.c \ @@ -402,6 +401,7 @@ $(filter $(SRC_PATTERNS), \ digitalio/Pull.c \ fontio/Glyph.c \ math/__init__.c \ + microcontroller/ResetReason.c \ microcontroller/RunMode.c \ ) diff --git a/shared-bindings/_typing/__init__.pyi b/shared-bindings/_typing/__init__.pyi index 3b3f18cb9..02839ab47 100644 --- a/shared-bindings/_typing/__init__.pyi +++ b/shared-bindings/_typing/__init__.pyi @@ -54,13 +54,12 @@ FrameBuffer = Union[rgbmatrix.RGBMatrix] """ Alarm = Union[ - alarm_time.Time, alarm_pin.PinLevel, alarm_touch.PinTouch + alarm.pin.PinAlarm, alarm.time.DurationAlarm ] -"""Classes that implement the audiosample protocol +"""Classes that implement alarms for sleeping and asynchronous notification. - - `alarm_time.Time` - - `alarm_pin.PinLevel` - - `alarm_touch.PinTouch` + - `alarm.pin.PinAlarm` + - `alarm.time.DurationAlarm` - You can play use these alarms to wake from light or deep sleep. + You can use these alarms to wake from light or deep sleep. """ diff --git a/shared-bindings/alarm/ResetReason.c b/shared-bindings/alarm/ResetReason.c deleted file mode 100644 index 086562fc9..000000000 --- a/shared-bindings/alarm/ResetReason.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Scott Shawcroft 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/enum.h" - -#include "shared-bindings/alarm/ResetReason.h" - -MAKE_ENUM_VALUE(alarm_reset_reason_type, reset_reason, INVALID, RESET_REASON_INVALID); -MAKE_ENUM_VALUE(alarm_reset_reason_type, reset_reason, POWER_ON, RESET_REASON_POWER_ON); -MAKE_ENUM_VALUE(alarm_reset_reason_type, reset_reason, BROWNOUT, RESET_REASON_BROWNOUT); -MAKE_ENUM_VALUE(alarm_reset_reason_type, reset_reason, SOFTWARE, RESET_REASON_SOFTWARE); -MAKE_ENUM_VALUE(alarm_reset_reason_type, reset_reason, DEEP_SLEEP_ALARM, RESET_REASON_DEEP_SLEEP_ALARM); -MAKE_ENUM_VALUE(alarm_reset_reason_type, reset_reason, RESET_PIN, RESET_REASON_RESET_PIN); -MAKE_ENUM_VALUE(alarm_reset_reason_type, reset_reason, WATCHDOG, RESET_REASON_WATCHDOG); - -//| class ResetReason: -//| """The reason the chip was last reset""" -//| -//| INVALID: object -//| """Invalid reason: indicates an internal error.""" -//| -//| POWER_ON: object -//| """The chip was started from power off.""" -//| -//| BROWNOUT: object -//| """The chip was reset due to voltage brownout.""" -//| -//| SOFTWARE: object -//| """The chip was reset from software.""" -//| -//| DEEP_SLEEP_ALARM: object -//| """The chip was reset for deep sleep and restarted by an alarm.""" -//| -//| RESET_PIN: object -//| """The chip was reset by a signal on its reset pin. The pin might be connected to a reset buton.""" -//| -//| WATCHDOG: object -//| """The chip was reset by its watchdog timer.""" -//| -MAKE_ENUM_MAP(alarm_reset_reason) { - MAKE_ENUM_MAP_ENTRY(reset_reason, INVALID), - MAKE_ENUM_MAP_ENTRY(reset_reason, POWER_ON), - MAKE_ENUM_MAP_ENTRY(reset_reason, BROWNOUT), - MAKE_ENUM_MAP_ENTRY(reset_reason, SOFTWARE), - MAKE_ENUM_MAP_ENTRY(reset_reason, DEEP_SLEEP_ALARM), - MAKE_ENUM_MAP_ENTRY(reset_reason, RESET_PIN), - MAKE_ENUM_MAP_ENTRY(reset_reason, WATCHDOG), -}; -STATIC MP_DEFINE_CONST_DICT(alarm_reset_reason_locals_dict, alarm_reset_reason_locals_table); - -MAKE_PRINTER(alarm, alarm_reset_reason); - -MAKE_ENUM_TYPE(alarm, ResetReason, alarm_reset_reason); diff --git a/shared-bindings/alarm/ResetReason.h b/shared-bindings/alarm/ResetReason.h deleted file mode 100644 index 2d6b8bc0c..000000000 --- a/shared-bindings/alarm/ResetReason.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 Scott Shawcroft 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_SHARED_BINDINGS_ALARM__RESET_REASON__H -#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM__RESET_REASON__H - -#include "py/obj.h" -#include "py/enum.h" - -typedef enum { - RESET_REASON_INVALID, - RESET_REASON_POWER_ON, - RESET_REASON_BROWNOUT, - RESET_REASON_SOFTWARE, - RESET_REASON_DEEP_SLEEP_ALARM, - RESET_REASON_RESET_PIN, - RESET_REASON_WATCHDOG, -} alarm_reset_reason_t; - -extern const cp_enum_obj_t reset_reason_INVALID_obj; - -extern const mp_obj_type_t alarm_reset_reason_type; - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM__RESET_REASON__H diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 771c8ff9b..934544216 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -1,3 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Dan Halbert 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/runtime.h" + +#include "shared-bindings/alarm/__init__.h" +#include "shared-bindings/alarm/ResetReason.h" +#include "shared-bindings/alarm/pin/PinAlarm.h" +#include "shared-bindings/alarm/time/DurationAlarm.h" + //| """Power-saving light and deep sleep. Alarms can be set to wake up from sleep. //| //| The `alarm` module provides sleep related functionality. There are two supported levels of @@ -11,54 +45,43 @@ //| Deep sleep shuts down power to nearly all of the chip including the CPU and RAM. This can save //| a more significant amount of power, but CircuitPython must start ``code.py`` from the beginning when woken //| up. CircuitPython will enter deep sleep automatically when the current program exits without error -//| or calls `sys.exit(0)`. +//| or calls ``sys.exit(0)``. //| If an error causes CircuitPython to exit, error LED error flashes will be done periodically. //| An error includes an uncaught exception, or sys.exit called with a non-zero argumetn. -//| To set alarms for deep sleep use `alarm.reload_on_alarm()` they will apply to next deep sleep only.""" +//| To set alarms for deep sleep use `alarm.restart_on_alarm()` they will apply to next deep sleep only.""" //| - //| wake_alarm: Alarm //| """The most recent alarm to wake us up from a sleep (light or deep.)""" //| -//| reset_reason: ResetReason -//| """The reason the chip started up from reset state. This can may be power up or due to an alarm.""" -//| - -//| def sleep(alarm: Alarm, ...) -> Alarm: +//| def sleep_until_alarm(*alarms: Alarm) -> Alarm: //| """Performs a light sleep until woken by one of the alarms. The alarm that triggers the wake //| is returned, and is also available as `alarm.wake_alarm` +//| """ //| ... //| - -#include "py/obj.h" -#include "py/runtime.h" - -#include "shared-bindings/alarm/__init__.h" -#include "shared-bindings/alarm/ResetReason.h" -#include "shared-bindings/alarm/pin/PinAlarm.h" -#include "shared-bindings/alarm/time/DurationAlarm.h" - STATIC mp_obj_t alarm_sleep_until_alarm(size_t n_args, const mp_obj_t *args) { // TODO + common_hal_alarm_sleep_until_alarm(size_t n_args, const mp_obj_t *args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_sleep_until_alarm_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_sleep_until_alarm); -//| def restart_on_alarm(alarm: Alarm, ...) -> None: +//| def restart_on_alarm(*alarms: Alarm) -> None: //| """Set one or more alarms to wake up from a deep sleep. //| When awakened, ``code.py`` will restart from the beginning. -//| The last alarm to wake us up is available as `wake_alarm`. +//| The last alarm to wake us up is available as `alarm.wake_alarm`. //| """ //| ... //| STATIC mp_obj_t alarm_restart_on_alarm(size_t n_args, const mp_obj_t *args) { // TODO + common_hal_alarm_restart_on_alarm(size_t n_args, const mp_obj_t *args); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_restart_on_alarm_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_restart_on_alarm); -//| """The `alarm.pin` module contains alarm attributes and classes related to pins +//| """The `alarm.pin` module contains alarm attributes and classes related to pins. //| """ //| STATIC const mp_map_elem_t alarm_pin_globals_table[] = { @@ -95,7 +118,6 @@ STATIC mp_map_elem_t alarm_module_globals_table[] = { // wake_alarm and reset_reason are mutable attributes. { MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none }, - { MP_ROM_QSTR(MP_QSTR_reset_reason), MP_OBJ_FROM_PTR(&reset_reason_INVALID_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_until_alarm), MP_OBJ_FROM_PTR(&alarm_sleep_until_alarm_obj) }, { MP_ROM_QSTR(MP_QSTR_restart_on_alarm), MP_OBJ_FROM_PTR(&alarm_restart_on_alarm_obj) }, @@ -116,16 +138,6 @@ void common_hal_alarm_set_wake_alarm(mp_obj_t alarm) { } } -void common_hal_alarm_set_reset_reason(mp_obj_t reset_reason) { - // Equivalent of: - // alarm.reset_reason = reset_reason - mp_map_elem_t *elem = - mp_map_lookup(&alarm_module_globals.map, MP_ROM_QSTR(MP_QSTR_reset_reason), MP_MAP_LOOKUP); - if (elem) { - elem->value = reset_reason; - } -} - const mp_obj_module_t alarm_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&alarm_module_globals, diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index a0ee76e53..29be8716c 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -29,11 +29,9 @@ #include "py/obj.h" -#include "shared-bindings/alarm/ResetReason.h" - extern void common_hal_alarm_set_wake_alarm(mp_obj_t alarm); -extern alarm_reset_reason_t common_hal_alarm_get_reset_reason(void); -extern void common_hal_alarm_set_reset_reason(mp_obj_t reset_reason); +extern mp_obj_t common_hal_alarm_restart_on_alarm(size_t n_alarms, const mp_obj_t *alarms); +extern mp_obj_t alarm_sleep_until_alarm(size_t n_alarms, const mp_obj_t *alarms); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index fef1face7..835a5be5c 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -35,27 +35,27 @@ #include "supervisor/shared/translate.h" //| class PinAlarm: -//| """Trigger an alarm when a pin changes state. +//| """Trigger an alarm when a pin changes state.""" //| //| def __init__(self, pin: microcontroller.Pin, level: bool, *, edge: bool = False, pull: bool = False) -> None: //| """Create an alarm triggered by a `~microcontroller.Pin` level. The alarm is not active -//| until it is listed in an `alarm`-enabling function, such as `alarm.sleep()` or -//| `alarm.wake_after_exit()`. - +//| until it is listed in an `alarm`-enabling function, such as `alarm.sleep_until_alarm()` or +//| `alarm.restart_on_alarm()`. +//| //| :param ~microcontroller.Pin pin: The pin to monitor. On some ports, the choice of pin -//| may be limited due to hardware restrictions, particularly for deep-sleep alarms. +//| may be limited due to hardware restrictions, particularly for deep-sleep alarms. //| :param bool level: When active, trigger when the level is high (``True``) or low (``False``). -//| On some ports, multiple `PinAlarm` objects may need to have coordinated levels -//| for deep-sleep alarms +//| On some ports, multiple `PinAlarm` objects may need to have coordinated levels +//| for deep-sleep alarms. //| :param bool edge: If ``True``, trigger only when there is a transition to the specified -//| value of `level`. If ``True``, if the alarm becomes active when the pin level already -//| matches `level`, the alarm is not triggered: the pin must transition from ``not level`` -//| to ``level`` to trigger the alarm. On some ports, edge-triggering may not be available, -//| particularly for deep-sleep alarms. +//| value of `level`. If ``True``, if the alarm becomes active when the pin level already +//| matches `level`, the alarm is not triggered: the pin must transition from ``not level`` +//| to ``level`` to trigger the alarm. On some ports, edge-triggering may not be available, +//| particularly for deep-sleep alarms. //| :param bool pull: Enable a pull-up or pull-down which pulls the pin to level opposite -//| opposite that of `level`. For instance, if `level` is set to ``True``, setting `pull` -//| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal -//| pulls it high. +//| opposite that of `level`. For instance, if `level` is set to ``True``, setting `pull` +//| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal +//| pulls it high. //| """ //| ... //| diff --git a/shared-bindings/alarm/time/DurationAlarm.c b/shared-bindings/alarm/time/DurationAlarm.c index 5fb232f4a..c105bbebf 100644 --- a/shared-bindings/alarm/time/DurationAlarm.c +++ b/shared-bindings/alarm/time/DurationAlarm.c @@ -34,14 +34,13 @@ #include "supervisor/shared/translate.h" //| class DurationAlarm: -//| """Trigger an alarm at a specified interval from now. +//| """Trigger an alarm at a specified interval from now.""" //| //| def __init__(self, secs: float) -> None: -//| """Create an alarm that will be triggered in `secs` seconds **from the time -//| the alarm is created**. The alarm is not active until it is listed in an -//| `alarm`-enabling function, such as `alarm.sleep()` or -//| `alarm.wake_after_exit()`. But the interval starts immediately upon -//| instantiation. +//| """Create an alarm that will be triggered in `secs` seconds from the time +//| sleep starts. The alarm is not active until it is listed in an +//| `alarm`-enabling function, such as `alarm.sleep_until_alarm()` or +//| `alarm.restart_on_alarm()`. //| """ //| ... //| diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index 8c703891d..b0ab842f4 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -67,6 +67,23 @@ const mp_obj_property_t mcu_processor_frequency_obj = { }, }; +//| reset_reason: `microcontroller.ResetReason` +//| """The reason the microcontroller started up from reset state.""" +//| +STATIC mp_obj_t mcu_processor_get_reset_reason(mp_obj_t self) { + return cp_enum_find(&mcu_reset_reason_type, common_hal_mcu_processor_get_reset_reason()); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mcu_processor_get_reset_reason_obj, mcu_processor_get_reset_reason); + +const mp_obj_property_t mcu_reset_reason_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&mcu_processor_get_reason_reason_obj, // getter + (mp_obj_t)&mp_const_none_obj, // no setter + (mp_obj_t)&mp_const_none_obj, // no deleter + }, +}; + //| temperature: Optional[float] //| """The on-chip temperature, in Celsius, as a float. (read-only) //| @@ -128,6 +145,7 @@ const mp_obj_property_t mcu_processor_voltage_obj = { STATIC const mp_rom_map_elem_t mcu_processor_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&mcu_processor_frequency_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_reason), MP_ROM_PTR(&mcu_processor_reset_reason_obj) }, { MP_ROM_QSTR(MP_QSTR_temperature), MP_ROM_PTR(&mcu_processor_temperature_obj) }, { MP_ROM_QSTR(MP_QSTR_uid), MP_ROM_PTR(&mcu_processor_uid_obj) }, { MP_ROM_QSTR(MP_QSTR_voltage), MP_ROM_PTR(&mcu_processor_voltage_obj) }, diff --git a/shared-bindings/microcontroller/Processor.h b/shared-bindings/microcontroller/Processor.h index 0f520f940..a842e06f3 100644 --- a/shared-bindings/microcontroller/Processor.h +++ b/shared-bindings/microcontroller/Processor.h @@ -29,11 +29,12 @@ #include "py/obj.h" -#include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" extern const mp_obj_type_t mcu_processor_type; uint32_t common_hal_mcu_processor_get_frequency(void); +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void); float common_hal_mcu_processor_get_temperature(void); void common_hal_mcu_processor_get_uid(uint8_t raw_id[]); float common_hal_mcu_processor_get_voltage(void); diff --git a/shared-bindings/microcontroller/ResetReason.c b/shared-bindings/microcontroller/ResetReason.c new file mode 100644 index 000000000..151fcf315 --- /dev/null +++ b/shared-bindings/microcontroller/ResetReason.c @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft 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/enum.h" + +#include "shared-bindings/microcontroller/ResetReason.h" + +MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, POWER_ON, RESET_REASON_POWER_ON); +MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, BROWNOUT, RESET_REASON_BROWNOUT); +MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, SOFTWARE, RESET_REASON_SOFTWARE); +MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, DEEP_SLEEP_ALARM, RESET_REASON_DEEP_SLEEP_ALARM); +MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, RESET_PIN, RESET_REASON_RESET_PIN); +MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, WATCHDOG, RESET_REASON_WATCHDOG); + +//| class ResetReason: +//| """The reason the microntroller was last reset""" +//| +//| POWER_ON: object +//| """The microntroller was started from power off.""" +//| +//| BROWNOUT: object +//| """The microntroller was reset due to too low a voltage.""" +//| +//| SOFTWARE: object +//| """The microntroller was reset from software.""" +//| +//| DEEP_SLEEP_ALARM: object +//| """The microntroller was reset for deep sleep and restarted by an alarm.""" +//| +//| RESET_PIN: object +//| """The microntroller was reset by a signal on its reset pin. The pin might be connected to a reset button.""" +//| +//| WATCHDOG: object +//| """The chip microcontroller reset by its watchdog timer.""" +//| +MAKE_ENUM_MAP(mcu_reset_reason) { + MAKE_ENUM_MAP_ENTRY(reset_reason, POWER_ON), + MAKE_ENUM_MAP_ENTRY(reset_reason, BROWNOUT), + MAKE_ENUM_MAP_ENTRY(reset_reason, SOFTWARE), + MAKE_ENUM_MAP_ENTRY(reset_reason, DEEP_SLEEP_ALARM), + MAKE_ENUM_MAP_ENTRY(reset_reason, RESET_PIN), + MAKE_ENUM_MAP_ENTRY(reset_reason, WATCHDOG), +}; +STATIC MP_DEFINE_CONST_DICT(mcu_reset_reason_locals_dict, mcu_reset_reason_locals_table); + +MAKE_PRINTER(alarm, mcu_reset_reason); + +MAKE_ENUM_TYPE(alarm, ResetReason, mcu_reset_reason); diff --git a/shared-bindings/microcontroller/ResetReason.h b/shared-bindings/microcontroller/ResetReason.h new file mode 100644 index 000000000..df1abf266 --- /dev/null +++ b/shared-bindings/microcontroller/ResetReason.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft 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_SHARED_BINDINGS_MCU__RESET_REASON__H +#define MICROPY_INCLUDED_SHARED_BINDINGS_MCU__RESET_REASON__H + +#include "py/obj.h" +#include "py/enum.h" + +typedef enum { + RESET_REASON_POWER_ON, + RESET_REASON_BROWNOUT, + RESET_REASON_SOFTWARE, + RESET_REASON_DEEP_SLEEP_ALARM, + RESET_REASON_RESET_PIN, + RESET_REASON_WATCHDOG, +} mcu_reset_reason_t; + +extern const cp_enum_obj_t reset_reason_POWER_ON_obj; +extern const cp_enum_obj_t reset_reason_BROWNOUT_obj; +extern const cp_enum_obj_t reset_reason_SOFTWARE_obj; +extern const cp_enum_obj_t reset_reason_DEEP_SLEEP_ALARM_obj; +extern const cp_enum_obj_t reset_reason_RESET_PIN_obj; +extern const cp_enum_obj_t reset_reason_WATCHDOG_obj; + +extern const mp_obj_type_t mcu_reset_reason_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MCU__RESET_REASON__H diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index bfeb812d6..d09cf8f44 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -135,13 +135,6 @@ STATIC mp_obj_t mcu_reset(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_reset_obj, mcu_reset); -STATIC mp_obj_t mcu_sleep(void) { - common_hal_mcu_deep_sleep(); - // We won't actually get here because mcu is going into sleep. - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mcu_sleep_obj, mcu_sleep); - //| nvm: Optional[ByteArray] //| """Available non-volatile memory. //| This object is the sole instance of `nvm.ByteArray` when available or ``None`` otherwise. @@ -176,8 +169,6 @@ STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) }, { MP_ROM_QSTR(MP_QSTR_on_next_reset), MP_ROM_PTR(&mcu_on_next_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mcu_reset_obj) }, - //ToDo: Remove MP_QSTR_sleep when sleep on code.py exit implemented. - { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mcu_sleep_obj) }, #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 { MP_ROM_QSTR(MP_QSTR_nvm), MP_ROM_PTR(&common_hal_mcu_nvm_obj) }, #else diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h index f5bcfaa08..ac71de424 100644 --- a/shared-bindings/microcontroller/__init__.h +++ b/shared-bindings/microcontroller/__init__.h @@ -32,7 +32,7 @@ #include "py/mpconfig.h" #include "common-hal/microcontroller/Processor.h" - +#include "shared-bindings/microcontroller/ResetReason.h" #include "shared-bindings/microcontroller/RunMode.h" extern void common_hal_mcu_delay_us(uint32_t); @@ -43,8 +43,6 @@ extern void common_hal_mcu_enable_interrupts(void); extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode); extern void common_hal_mcu_reset(void); -extern void common_hal_mcu_deep_sleep(void); - extern const mp_obj_dict_t mcu_pin_globals; extern const mcu_processor_obj_t common_hal_mcu_processor_obj; diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c index 5233cf959..ee08f6d71 100644 --- a/shared-bindings/supervisor/RunReason.c +++ b/shared-bindings/supervisor/RunReason.c @@ -28,35 +28,35 @@ #include "shared-bindings/supervisor/RunReason.h" -MAKE_ENUM_VALUE(canio_bus_state_type, run_reason, ERROR_ACTIVE, RUN_REASON_STARTUP); -MAKE_ENUM_VALUE(canio_bus_state_type, bus_state, ERROR_PASSIVE, RUN_REASON_AUTORELOAD); -MAKE_ENUM_VALUE(canio_bus_state_type, bus_state, ERROR_WARNING, RUN_REASON_SUPERVISOR_RELOAD); -MAKE_ENUM_VALUE(canio_bus_state_type, bus_state, BUS_OFF, RUN_REASON_RELOAD_HOTKEY); +MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, STARTUP, RUN_REASON_STARTUP); +MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTORELOAD, RUN_REASON_AUTORELOAD); +MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, SUPERVISOR_RELOAD, RUN_REASON_SUPERVISOR_RELOAD); +MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_REPL_RELOAD); //| class RunReason: -//| """The state of the CAN bus""" +//| """The reason that CircuitPython started running.""" //| //| STARTUP: object -//| """The first VM was run after the microcontroller started up. See `microcontroller.start_reason` -//| for more detail why the microcontroller was started.""" +//| """CircuitPython started the microcontroller started up. See `microcontroller.cpu.reset_reason` +//| for more detail on why the microcontroller was started.""" //| //| AUTORELOAD: object -//| """The VM was run due to a USB write to the filesystem.""" +//| """CircuitPython restarted due to a USB write to the filesystem.""" //| //| SUPERVISOR_RELOAD: object -//| """The VM was run due to a call to `supervisor.reload()`.""" +//| """CircuitPython restarted due to a call to `supervisor.reload()`.""" //| -//| RELOAD_HOTKEY: object -//| """The VM was run due CTRL-D.""" +//| REPL_RELOAD: object +//| """CircuitPython started due to the user typing CTRL-D in the REPL.""" //| -MAKE_ENUM_MAP(canio_bus_state) { - MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_ACTIVE), - MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_PASSIVE), - MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_WARNING), - MAKE_ENUM_MAP_ENTRY(bus_state, BUS_OFF), +MAKE_ENUM_MAP(run_reason) { + MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP), + MAKE_ENUM_MAP_ENTRY(run_reason, AUTORELOAD), + MAKE_ENUM_MAP_ENTRY(run_reason, SUPERVISOR_RELOAD), + MAKE_ENUM_MAP_ENTRY(run_reason, REPL_RELOAD), }; -STATIC MP_DEFINE_CONST_DICT(canio_bus_state_locals_dict, canio_bus_state_locals_table); +STATIC MP_DEFINE_CONST_DICT(supervisor_run_reason_locals_dict, supervisor_run_reason_locals_table); -MAKE_PRINTER(canio, canio_bus_state); +MAKE_PRINTER(supervisor, supervisor_run_reason); -MAKE_ENUM_TYPE(canio, BusState, canio_bus_state); +MAKE_ENUM_TYPE(supervisor, RunReason, supervisor_run_reason); diff --git a/shared-bindings/supervisor/RunReason.h b/shared-bindings/supervisor/RunReason.h index f9aaacae6..934c72fd8 100644 --- a/shared-bindings/supervisor/RunReason.h +++ b/shared-bindings/supervisor/RunReason.h @@ -30,7 +30,7 @@ typedef enum { RUN_REASON_STARTUP, RUN_REASON_AUTORELOAD, RUN_REASON_SUPERVISOR_RELOAD, - RUN_REASON_RELOAD_HOTKEY + RUN_REASON_REPL_RELOAD, } supervisor_run_reason_t; -extern const mp_obj_type_t canio_bus_state_type; +extern const mp_obj_type_t supervisor_run_reason_type; diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index f9db38c9b..6500dadd5 100755 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -91,15 +91,11 @@ const mp_obj_property_t supervisor_serial_bytes_available_obj = { //| run_reason: RunReason -//| """Returns why the Python VM was run this time.""" +//| """Returns why CircuitPython started running this particular time. //| STATIC mp_obj_t supervisor_get_run_reason(mp_obj_t self) { - if (!common_hal_get_serial_bytes_available()) { - return mp_const_false; - } - else { - return mp_const_true; - } + mp_raise_NotImplementedError(NULL); + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_run_reason_obj, supervisor_get_run_reason); diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c index ee8af2c2c..9032e4045 100644 --- a/supervisor/shared/safe_mode.c +++ b/supervisor/shared/safe_mode.c @@ -29,10 +29,8 @@ #include "mphalport.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#if CIRCUITPY_ALARM -#include "shared-bindings/alarm/__init__.h" -#include "shared-bindings/alarm/ResetReason.h" -#endif +#include "shared-bindings/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" #include "supervisor/serial.h" #include "supervisor/shared/rgb_led_colors.h" @@ -56,12 +54,12 @@ safe_mode_t wait_for_safe_mode_reset(void) { current_safe_mode = safe_mode; return safe_mode; } -#if CIRCUITPY_ALARM - if (common_hal_alarm_get_reset_reason() != RESET_REASON_POWER_ON && - common_hal_alarm_get_reset_reason() != RESET_REASON_RESET_PIN) { + + const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); + if (reset_reason != RESET_REASON_POWER_ON && + reset_reason != RESET_REASON_RESET_PIN) { return NO_SAFE_MODE; } -#endif port_set_saved_word(SAFE_MODE_DATA_GUARD | (MANUAL_SAFE_MODE << 8)); // Wait for a while to allow for reset. temp_status_color(SAFE_MODE); -- cgit v1.2.3 From a0f1ec3c4a3dd52b11752e10d0dd31202e9c705f Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 22 Nov 2020 19:10:09 -0500 Subject: wip --- main.c | 16 ++++-- .../common-hal/microcontroller/__init__.c | 4 ++ ports/cxd56/common-hal/microcontroller/__init__.c | 4 ++ ports/esp32s2/common-hal/alarm/__init__.c | 43 ++++++++++++++ ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 19 ++++--- ports/esp32s2/common-hal/alarm/pin/PinAlarm.h | 7 ++- .../esp32s2/common-hal/microcontroller/Processor.c | 55 +++++++++++++----- .../esp32s2/common-hal/microcontroller/Processor.h | 6 +- .../esp32s2/common-hal/microcontroller/__init__.c | 8 +++ ports/esp32s2/common-hal/rtc/RTC.h | 6 +- ports/esp32s2/common-hal/supervisor/Runtime.h | 6 +- .../supervisor/internal_flash_root_pointers.h | 6 +- ports/litex/common-hal/microcontroller/__init__.c | 4 ++ .../common-hal/microcontroller/__init__.c | 4 ++ .../peripherals/mimxrt10xx/MIMXRT1011/periph.h | 6 +- .../peripherals/mimxrt10xx/MIMXRT1062/periph.h | 6 +- ports/nrf/common-hal/microcontroller/__init__.c | 4 ++ ports/nrf/common-hal/rgbmatrix/RGBMatrix.h | 4 +- ports/stm/common-hal/microcontroller/__init__.c | 4 ++ ports/stm/common-hal/rgbmatrix/RGBMatrix.h | 4 +- shared-bindings/alarm/__init__.c | 60 +++++++++++++------- shared-bindings/alarm/__init__.h | 7 ++- shared-bindings/alarm/pin/PinAlarm.c | 66 ++++++++-------------- shared-bindings/alarm/pin/PinAlarm.h | 5 +- shared-bindings/audiopwmio/__init__.h | 6 +- shared-bindings/microcontroller/Processor.c | 4 +- shared-bindings/microcontroller/Processor.h | 1 + shared-bindings/microcontroller/ResetReason.c | 7 ++- shared-bindings/microcontroller/ResetReason.h | 14 ++--- shared-bindings/microcontroller/__init__.c | 14 +++++ shared-bindings/microcontroller/__init__.h | 2 + shared-bindings/supervisor/RunReason.c | 8 +-- shared-bindings/supervisor/RunReason.h | 2 +- shared-bindings/supervisor/Runtime.c | 10 +++- shared-bindings/supervisor/Runtime.h | 3 + shared-bindings/supervisor/__init__.c | 1 + supervisor/shared/usb/usb.c | 4 -- supervisor/shared/workflow.c | 8 +-- 38 files changed, 287 insertions(+), 151 deletions(-) (limited to 'shared-bindings/supervisor/RunReason.c') diff --git a/main.c b/main.c index 8938d714a..f77bf41d8 100755 --- a/main.c +++ b/main.c @@ -61,6 +61,8 @@ #include "supervisor/usb.h" #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Processor.h" +#include "shared-bindings/supervisor/Runtime.h" #include "boards/board.h" @@ -327,24 +329,27 @@ bool run_code_py(safe_mode_t safe_mode) { #endif rgb_status_animation_t animation; bool ok = result.return_code != PYEXEC_EXCEPTION; - #if CIRCUITPY_ALARM // If USB isn't enumerated then deep sleep. if (ok && !supervisor_workflow_active() && supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024) { - common_hal_alarm_restart_on_alarm(0, NULL); + common_hal_mcu_deep_sleep(); } - #endif // Show the animation every N seconds. prep_rgb_status_animation(&result, found_main, safe_mode, &animation); while (true) { RUN_BACKGROUND_TASKS; if (reload_requested) { + supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD); reload_requested = false; return true; } if (serial_connected() && serial_bytes_available()) { // Skip REPL if reload was requested. - return (serial_read() == CHAR_CTRL_D); + bool ctrl_d = serial_read() == CHAR_CTRL_D; + if (ctrl_d) { + supervisor_set_run_reason(RUN_REASON_REPL_RELOAD); + } + return (ctrl_d); } if (!serial_connected_before_animation && serial_connected()) { @@ -521,6 +526,9 @@ int __attribute__((used)) main(void) { reset_devices(); reset_board(); + // This is first time we are running CircuitPython after a reset or power-up. + supervisor_set_run_reason(RUN_REASON_STARTUP); + // If not in safe mode turn on autoreload by default but before boot.py in case it wants to change it. if (safe_mode == NO_SAFE_MODE) { autoreload_enable(); diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index 50a1ec038..ca39f2838 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -84,6 +84,10 @@ void common_hal_mcu_reset(void) { reset(); } +void common_hal_mcu_deep_sleep(void) { + //deep sleep call here +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/cxd56/common-hal/microcontroller/__init__.c b/ports/cxd56/common-hal/microcontroller/__init__.c index 7aa3b839d..57140dec7 100644 --- a/ports/cxd56/common-hal/microcontroller/__init__.c +++ b/ports/cxd56/common-hal/microcontroller/__init__.c @@ -81,6 +81,10 @@ void common_hal_mcu_reset(void) { boardctl(BOARDIOC_RESET, 0); } +void common_hal_mcu_deep_sleep(void) { + //deep sleep call here +} + STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_UART2_RXD), MP_ROM_PTR(&pin_UART2_RXD) }, { MP_ROM_QSTR(MP_QSTR_UART2_TXD), MP_ROM_PTR(&pin_UART2_TXD) }, diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index e33534550..4a255c51c 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -25,12 +25,20 @@ * THE SOFTWARE. */ +#include "py/objtuple.h" + #include "shared-bindings/alarm/__init__.h" #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/DurationAlarm.h" #include "esp_sleep.h" +STATIC mp_obj_tuple_t *_deep_sleep_alarms; + +void alarm_reset(void) { + _deep_sleep_alarms = &mp_const_empty_tuple; +} + void common_hal_alarm_disable_all(void) { esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } @@ -63,3 +71,38 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) { } return mp_const_none; } + +mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms) { + bool time_alarm_set = false; + for (size_t i = 0; i < n_alarms; i++) { + if (MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) { + mp_raise_NotImplementedError(translate("PinAlarm deep sleep not yet implemented")); + } + if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_duration_alarm_type)) { + if (time_alarm_set) { + mp_raise_ValueError(translate("Only one alarm.time alarm can be set.")); + } + time_alarm_set = true; + } + } + + _deep_sleep_alarms = mp_obj_new_tuple(n_alarms, alarms); +} + +void common_hal_deep_sleep_with_alarms(void) { + for (size_t i = 0; i < _deep_sleep_alarms.len; i++) { + mp_obj_t alarm = _deep_sleep_alarms.items[i] + if (MP_OBJ_IS_TYPE(alarm, &alarm_time_duration_alarm_type)) { + alarm_time_duration_alarm_obj_t *duration_alarm = MP_OBJ_TO_PTR(alarm); + esp_sleep_enable_timer_wakeup( + (uint64_t) (duration_alarm->duration * 1000000.0f)); + } + // TODO: handle pin alarms + } + + common_hal_mcu_deep_sleep(); +} diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index 6ac3d05f8..f26c8a179 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -30,19 +30,24 @@ #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/microcontroller/Pin.h" -void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, const mcu_pin_obj_t *pin, bool level, bool edge, bool pull) { - self->pin = pin; - self->level = level; +void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, const mp_obj_t pins[], size_t num_pins, bool value, bool all_same_value, bool edge, bool pull) { + self->pins = mp_obj_new_tuple(num_pins, pins); + self->value = value; + self->all_same_value = all_same_value; self->edge = edge; self->pull = pull; } -const mcu_pin_obj_t *common_hal_alarm_pin_pin_alarm_get_pin(alarm_pin_pin_alarm_obj_t *self) { - return self->pin; +const mp_obj_tuple_t *common_hal_alarm_pin_pin_alarm_get_pins(alarm_pin_pin_alarm_obj_t *self) { + return self->pins; } -bool common_hal_alarm_pin_pin_alarm_get_level(alarm_pin_pin_alarm_obj_t *self) { - return self->level; +bool common_hal_alarm_pin_pin_alarm_get_value(alarm_pin_pin_alarm_obj_t *self) { + return self->value; +} + +bool common_hal_alarm_pin_pin_alarm_get_all_same_value(alarm_pin_pin_alarm_obj_t *self) { + return self->all_same_value; } bool common_hal_alarm_pin_pin_alarm_get_edge(alarm_pin_pin_alarm_obj_t *self) { diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h index c6a760b96..d7e7e2552 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h @@ -24,13 +24,14 @@ * THE SOFTWARE. */ - #include "py/obj.h" +#include "py/objtuple.h" typedef struct { mp_obj_base_t base; - const mcu_pin_obj_t *pin; - bool level; + mp_obj_tuple_t *pins; + bool value; + bool all_same_value; bool edge; bool pull; } alarm_pin_pin_alarm_obj_t; diff --git a/ports/esp32s2/common-hal/microcontroller/Processor.c b/ports/esp32s2/common-hal/microcontroller/Processor.c index bd625dc6e..fffd1a1b1 100644 --- a/ports/esp32s2/common-hal/microcontroller/Processor.c +++ b/ports/esp32s2/common-hal/microcontroller/Processor.c @@ -31,8 +31,12 @@ #include "py/runtime.h" #include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" #include "supervisor/shared/translate.h" +#include "esp_sleep.h" +#include "esp_system.h" + #include "soc/efuse_reg.h" #include "components/driver/esp32s2/include/driver/temp_sensor.h" @@ -77,21 +81,42 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { } mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { - switch (esp_sleep_get_wakeup_cause()) { - case ESP_SLEEP_WAKEUP_TIMER: - return RESET_REASON_DEEP_SLEEP_ALARM; - - case ESP_SLEEP_WAKEUP_EXT0: - return RESET_REASON_DEEP_SLEEP_ALARM; - - case ESP_SLEEP_WAKEUP_TOUCHPAD: - //TODO: implement TouchIO - case ESP_SLEEP_WAKEUP_UNDEFINED: + switch (esp_reset_reason()) { + case ESP_RST_POWERON: + return RESET_REASON_POWER_ON; + + case ESP_RST_SW: + case ESP_RST_PANIC: + return RESET_REASON_SOFTWARE; + + case ESP_RST_INT_WDT: + case ESP_RST_TASK_WDT: + case ESP_RST_WDT: + return RESET_REASON_WATCHDOG; + + case ESP_RST_BROWNOUT: + return RESET_REASON_BROWNOUT; + + case ESP_RST_SDIO: + case ESP_RST_EXT: + return RESET_REASON_RESET_PIN; + + case ESP_RST_DEEPSLEEP: + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_TIMER: + case ESP_SLEEP_WAKEUP_EXT0: + case ESP_SLEEP_WAKEUP_EXT1: + case ESP_SLEEP_WAKEUP_TOUCHPAD: + return RESET_REASON_DEEP_SLEEP_ALARM; + + case ESP_SLEEP_WAKEUP_UNDEFINED: + default: + return RESET_REASON_UNKNOWN; + } + + case ESP_RST_UNKNOWN: default: - return RESET_REASON_POWER_APPLIED; - } -} + return RESET_REASON_UNKNOWN; -mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { - return RESET_REASON_POWER_ON; + } } diff --git a/ports/esp32s2/common-hal/microcontroller/Processor.h b/ports/esp32s2/common-hal/microcontroller/Processor.h index f6636b333..641a11d55 100644 --- a/ports/esp32s2/common-hal/microcontroller/Processor.h +++ b/ports/esp32s2/common-hal/microcontroller/Processor.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_LITEX_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H -#define MICROPY_INCLUDED_LITEX_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H +#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H +#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H #define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 6 @@ -36,4 +36,4 @@ typedef struct { // Stores no state currently. } mcu_processor_obj_t; -#endif // MICROPY_INCLUDED_LITEX_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H +#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H diff --git a/ports/esp32s2/common-hal/microcontroller/__init__.c b/ports/esp32s2/common-hal/microcontroller/__init__.c index 3056c6565..fdfbd65fa 100644 --- a/ports/esp32s2/common-hal/microcontroller/__init__.c +++ b/ports/esp32s2/common-hal/microcontroller/__init__.c @@ -79,6 +79,14 @@ void common_hal_mcu_reset(void) { while(1); } +void common_hal_mcu_deep_sleep(void) { + // Shut down wifi cleanly. + esp_wifi_stop(); + + // Does not return. + esp_deep_sleep_start(); +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/esp32s2/common-hal/rtc/RTC.h b/ports/esp32s2/common-hal/rtc/RTC.h index e51f1f784..233cde3fd 100644 --- a/ports/esp32s2/common-hal/rtc/RTC.h +++ b/ports/esp32s2/common-hal/rtc/RTC.h @@ -24,11 +24,11 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_RTC_RTC_H -#define MICROPY_INCLUDED_NRF_COMMON_HAL_RTC_RTC_H +#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_RTC_RTC_H +#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_RTC_RTC_H extern void rtc_init(void); extern void rtc_reset(void); extern void common_hal_rtc_init(void); -#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_RTC_RTC_H +#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_RTC_RTC_H diff --git a/ports/esp32s2/common-hal/supervisor/Runtime.h b/ports/esp32s2/common-hal/supervisor/Runtime.h index d1fe24621..840ce1bbb 100644 --- a/ports/esp32s2/common-hal/supervisor/Runtime.h +++ b/ports/esp32s2/common-hal/supervisor/Runtime.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_LITEX_COMMON_HAL_SUPERVISOR_RUNTIME_H -#define MICROPY_INCLUDED_LITEX_COMMON_HAL_SUPERVISOR_RUNTIME_H +#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SUPERVISOR_RUNTIME_H +#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SUPERVISOR_RUNTIME_H #include "py/obj.h" @@ -34,4 +34,4 @@ typedef struct { // Stores no state currently. } super_runtime_obj_t; -#endif // MICROPY_INCLUDED_LITEX_COMMON_HAL_SUPERVISOR_RUNTIME_H +#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SUPERVISOR_RUNTIME_H diff --git a/ports/esp32s2/supervisor/internal_flash_root_pointers.h b/ports/esp32s2/supervisor/internal_flash_root_pointers.h index ae3e45e14..a9a8c2a22 100644 --- a/ports/esp32s2/supervisor/internal_flash_root_pointers.h +++ b/ports/esp32s2/supervisor/internal_flash_root_pointers.h @@ -23,9 +23,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_LITEX_INTERNAL_FLASH_ROOT_POINTERS_H -#define MICROPY_INCLUDED_LITEX_INTERNAL_FLASH_ROOT_POINTERS_H +#ifndef MICROPY_INCLUDED_ESP32S2_INTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_ESP32S2_INTERNAL_FLASH_ROOT_POINTERS_H #define FLASH_ROOT_POINTERS -#endif // MICROPY_INCLUDED_LITEX_INTERNAL_FLASH_ROOT_POINTERS_H +#endif // MICROPY_INCLUDED_ESP32S2_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/litex/common-hal/microcontroller/__init__.c b/ports/litex/common-hal/microcontroller/__init__.c index 3c9166114..e6f50ed5a 100644 --- a/ports/litex/common-hal/microcontroller/__init__.c +++ b/ports/litex/common-hal/microcontroller/__init__.c @@ -89,6 +89,10 @@ void common_hal_mcu_reset(void) { while(1); } +void common_hal_mcu_deep_sleep(void) { + //deep sleep call here +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c index 6a8537e2d..0329ced69 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/__init__.c +++ b/ports/mimxrt10xx/common-hal/microcontroller/__init__.c @@ -86,6 +86,10 @@ void common_hal_mcu_reset(void) { NVIC_SystemReset(); } +void common_hal_mcu_deep_sleep(void) { + //deep sleep call here +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/periph.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/periph.h index c3f04a049..c50d73294 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/periph.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/periph.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_MIMXRT10XX_PERIPHERALS_MIMXRT1011_PERIPH_H -#define MICROPY_INCLUDED_MIMXRT10XX_PERIPHERALS_MIMXRT1011_PERIPH_H +#ifndef MICROPY_INCLUDED_MIMXRT10XX_MIMXRT1011_PERIPHERALS_MIMXRT1011_PERIPH_H +#define MICROPY_INCLUDED_MIMXRT10XX_MIMXRT1011_PERIPHERALS_MIMXRT1011_PERIPH_H extern LPI2C_Type *mcu_i2c_banks[2]; @@ -47,4 +47,4 @@ extern const mcu_periph_obj_t mcu_uart_cts_list[4]; extern const mcu_pwm_obj_t mcu_pwm_list[20]; -#endif // MICROPY_INCLUDED_MIMXRT10XX_PERIPHERALS_MIMXRT1011_PERIP_H +#endif // MICROPY_INCLUDED_MIMXRT10XX_MIMXRT1011_PERIPHERALS_MIMXRT1011_PERIPH_H diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h index 4f6ab6261..067c05d0d 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_MIMXRT10XX_PERIPHERALS_MIMXRT1011_PERIPH_H -#define MICROPY_INCLUDED_MIMXRT10XX_PERIPHERALS_MIMXRT1011_PERIPH_H +#ifndef MICROPY_INCLUDED_MIMXRT10XX_MIMXRT1062_PERIPHERALS_MIMXRT1011_PERIPH_H +#define MICROPY_INCLUDED_MIMXRT10XX_MIMXRT1062_PERIPHERALS_MIMXRT1011_PERIPH_H extern LPI2C_Type *mcu_i2c_banks[4]; @@ -47,4 +47,4 @@ extern const mcu_periph_obj_t mcu_uart_cts_list[9]; extern const mcu_pwm_obj_t mcu_pwm_list[67]; -#endif // MICROPY_INCLUDED_MIMXRT10XX_PERIPHERALS_MIMXRT1011_PERIPH_H +#endif // MICROPY_INCLUDED_MIMXRT10XX_MIMXRT1062_PERIPHERALS_MIMXRT1011_PERIPH_H diff --git a/ports/nrf/common-hal/microcontroller/__init__.c b/ports/nrf/common-hal/microcontroller/__init__.c index 06aac9409..9911896bf 100644 --- a/ports/nrf/common-hal/microcontroller/__init__.c +++ b/ports/nrf/common-hal/microcontroller/__init__.c @@ -95,6 +95,10 @@ void common_hal_mcu_reset(void) { reset_cpu(); } +void common_hal_mcu_deep_sleep(void) { + //deep sleep call here +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/nrf/common-hal/rgbmatrix/RGBMatrix.h b/ports/nrf/common-hal/rgbmatrix/RGBMatrix.h index 48de4dcb2..24d86f177 100644 --- a/ports/nrf/common-hal/rgbmatrix/RGBMatrix.h +++ b/ports/nrf/common-hal/rgbmatrix/RGBMatrix.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H -#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H +#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_RGBMATRIX_RGBMATRIX_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_RGBMATRIX_RGBMATRIX_H void *common_hal_rgbmatrix_timer_allocate(void); void common_hal_rgbmatrix_timer_enable(void*); diff --git a/ports/stm/common-hal/microcontroller/__init__.c b/ports/stm/common-hal/microcontroller/__init__.c index a827399cc..bc81b0e4f 100644 --- a/ports/stm/common-hal/microcontroller/__init__.c +++ b/ports/stm/common-hal/microcontroller/__init__.c @@ -81,6 +81,10 @@ void common_hal_mcu_reset(void) { NVIC_SystemReset(); } +void common_hal_mcu_deep_sleep(void) { + //deep sleep call here +} + // The singleton microcontroller.Processor object, bound to microcontroller.cpu // It currently only has properties, and no state. const mcu_processor_obj_t common_hal_mcu_processor_obj = { diff --git a/ports/stm/common-hal/rgbmatrix/RGBMatrix.h b/ports/stm/common-hal/rgbmatrix/RGBMatrix.h index 48de4dcb2..323878d20 100644 --- a/ports/stm/common-hal/rgbmatrix/RGBMatrix.h +++ b/ports/stm/common-hal/rgbmatrix/RGBMatrix.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H -#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_RGBMATRIX_RGBMATRIX_H +#ifndef MICROPY_INCLUDED_STM_COMMON_HAL_RGBMATRIX_RGBMATRIX_H +#define MICROPY_INCLUDED_STM_COMMON_HAL_RGBMATRIX_RGBMATRIX_H void *common_hal_rgbmatrix_timer_allocate(void); void common_hal_rgbmatrix_timer_enable(void*); diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 934544216..22b2e7f6a 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -28,7 +28,6 @@ #include "py/runtime.h" #include "shared-bindings/alarm/__init__.h" -#include "shared-bindings/alarm/ResetReason.h" #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/DurationAlarm.h" @@ -44,42 +43,61 @@ //| //| Deep sleep shuts down power to nearly all of the chip including the CPU and RAM. This can save //| a more significant amount of power, but CircuitPython must start ``code.py`` from the beginning when woken -//| up. CircuitPython will enter deep sleep automatically when the current program exits without error -//| or calls ``sys.exit(0)``. -//| If an error causes CircuitPython to exit, error LED error flashes will be done periodically. -//| An error includes an uncaught exception, or sys.exit called with a non-zero argumetn. +//| up. If the board is not actively connected to a host computer (usually via USB), +//| CircuitPython will enter deep sleep automatically when the current program finishes its last statement +//| or calls ``sys.exit()``. +//| If the board is connected, the board will not enter deep sleep unless `supervisor.exit_and_deep_sleep()` +//| is called explicitly. +//| +//| An error includes an uncaught exception, or sys.exit() called with a non-zero argument +//| //| To set alarms for deep sleep use `alarm.restart_on_alarm()` they will apply to next deep sleep only.""" //| //| wake_alarm: Alarm //| """The most recent alarm to wake us up from a sleep (light or deep.)""" //| -//| def sleep_until_alarm(*alarms: Alarm) -> Alarm: -//| """Performs a light sleep until woken by one of the alarms. The alarm that triggers the wake +void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) { + for (size_t i = 0; i < n_args; i++) { + if (MP_OBJ_IS_TYPE(objs[i], &alarm_pin_pin_alarm_type) || + MP_OBJ_IS_TYPE(objs[i], &alarm_time_duration_alarm_type)) { + continue; + } + mp_raise_TypeError_varg(translate("Expected an alarm")); + } +} + +//| def sleep_until_alarms(*alarms: Alarm) -> Alarm: +//| """Performs a light sleep until woken by one of the alarms. The alarm caused the wake-up //| is returned, and is also available as `alarm.wake_alarm` //| """ //| ... //| -STATIC mp_obj_t alarm_sleep_until_alarm(size_t n_args, const mp_obj_t *args) { - // TODO - common_hal_alarm_sleep_until_alarm(size_t n_args, const mp_obj_t *args); +STATIC mp_obj_t alarm_sleep_until_alarms(size_t n_args, const mp_obj_t *args) { + validate_objs_are_alarms(n_args, args); + common_hal_alarm_sleep_until_alarms(n_args, args); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_sleep_until_alarm_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_sleep_until_alarm); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_sleep_until_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_sleep_until_alarms); -//| def restart_on_alarm(*alarms: Alarm) -> None: +//| def set_deep_sleep_alarms(*alarms: Alarm) -> None: //| """Set one or more alarms to wake up from a deep sleep. -//| When awakened, ``code.py`` will restart from the beginning. -//| The last alarm to wake us up is available as `alarm.wake_alarm`. +//| +//| When awakened, the microcontroller will restart and run ``boot.py`` and ``code.py`` +//| from the beginning. +//| +//| The alarm that caused the wake-up is available as `alarm.wake_alarm`. +//| +//| If you call this routine more than once, only the last set of alarms given will be used. //| """ //| ... //| -STATIC mp_obj_t alarm_restart_on_alarm(size_t n_args, const mp_obj_t *args) { - // TODO - common_hal_alarm_restart_on_alarm(size_t n_args, const mp_obj_t *args); +STATIC mp_obj_t alarm_set_deep_sleep_alarms(size_t n_args, const mp_obj_t *args) { + validate_objs_are_alarms(n_args, args); + common_hal_alarm_set_deep_sleep_alarms(n_args, args); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_restart_on_alarm_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_restart_on_alarm); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_set_deep_sleep_alarms_obj, 1, MP_OBJ_FUN_ARGS_MAX, alarm_set_deep_sleep_alarms); //| """The `alarm.pin` module contains alarm attributes and classes related to pins. //| """ @@ -116,11 +134,11 @@ STATIC const mp_obj_module_t alarm_time_module = { STATIC mp_map_elem_t alarm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) }, - // wake_alarm and reset_reason are mutable attributes. + // wake_alarm is a mutable attribute. { MP_ROM_QSTR(MP_QSTR_wake_alarm), mp_const_none }, - { MP_ROM_QSTR(MP_QSTR_sleep_until_alarm), MP_OBJ_FROM_PTR(&alarm_sleep_until_alarm_obj) }, - { MP_ROM_QSTR(MP_QSTR_restart_on_alarm), MP_OBJ_FROM_PTR(&alarm_restart_on_alarm_obj) }, + { MP_ROM_QSTR(MP_QSTR_sleep_until_alarms), MP_OBJ_FROM_PTR(&alarm_sleep_until_alarms_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_deep_sleep_alarms), MP_OBJ_FROM_PTR(&alarm_set_deep_sleep_alarms_obj) }, { MP_ROM_QSTR(MP_QSTR_pin), MP_OBJ_FROM_PTR(&alarm_pin_module) }, { MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module) } diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index 29be8716c..4df12175d 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -29,9 +29,10 @@ #include "py/obj.h" -extern void common_hal_alarm_set_wake_alarm(mp_obj_t alarm); +extern mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms); +extern mp_obj_t common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms); -extern mp_obj_t common_hal_alarm_restart_on_alarm(size_t n_alarms, const mp_obj_t *alarms); -extern mp_obj_t alarm_sleep_until_alarm(size_t n_alarms, const mp_obj_t *alarms); +// Used by wake-up code. +extern void common_hal_alarm_set_wake_alarm(mp_obj_t alarm); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___H diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index 835a5be5c..a2d2e0ab7 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -37,23 +37,25 @@ //| class PinAlarm: //| """Trigger an alarm when a pin changes state.""" //| -//| def __init__(self, pin: microcontroller.Pin, level: bool, *, edge: bool = False, pull: bool = False) -> None: +//| def __init__(self, *pins: microcontroller.Pin, value: bool, all_same_value: bool = False, edge: bool = False, pull: bool = False) -> None: //| """Create an alarm triggered by a `~microcontroller.Pin` level. The alarm is not active //| until it is listed in an `alarm`-enabling function, such as `alarm.sleep_until_alarm()` or //| `alarm.restart_on_alarm()`. //| -//| :param ~microcontroller.Pin pin: The pin to monitor. On some ports, the choice of pin +//| :param pins: The pins to monitor. On some ports, the choice of pins //| may be limited due to hardware restrictions, particularly for deep-sleep alarms. -//| :param bool level: When active, trigger when the level is high (``True``) or low (``False``). -//| On some ports, multiple `PinAlarm` objects may need to have coordinated levels +//| :param bool value: When active, trigger when the pin value is high (``True``) or low (``False``). +//| On some ports, multiple `PinAlarm` objects may need to have coordinated values //| for deep-sleep alarms. +//| :param bool all_same_value: If ``True``, all pins listed must be at `value` to trigger the alarm. +//| If ``False``, any one of the pins going to `value` will trigger the alarm. //| :param bool edge: If ``True``, trigger only when there is a transition to the specified -//| value of `level`. If ``True``, if the alarm becomes active when the pin level already -//| matches `level`, the alarm is not triggered: the pin must transition from ``not level`` -//| to ``level`` to trigger the alarm. On some ports, edge-triggering may not be available, +//| value of `value`. If ``True``, if the alarm becomes active when the pin value already +//| matches `value`, the alarm is not triggered: the pin must transition from ``not value`` +//| to ``value`` to trigger the alarm. On some ports, edge-triggering may not be available, //| particularly for deep-sleep alarms. -//| :param bool pull: Enable a pull-up or pull-down which pulls the pin to level opposite -//| opposite that of `level`. For instance, if `level` is set to ``True``, setting `pull` +//| :param bool pull: Enable a pull-up or pull-down which pulls the pin to value opposite +//| opposite that of `value`. For instance, if `value` is set to ``True``, setting `pull` //| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal //| pulls it high. //| """ @@ -62,51 +64,30 @@ STATIC mp_obj_t alarm_pin_pin_alarm_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_pin_pin_alarm_obj_t *self = m_new_obj(alarm_pin_pin_alarm_obj_t); self->base.type = &alarm_pin_pin_alarm_type; - enum { ARG_pin, ARG_level, ARG_edge, ARG_pull }; + enum { ARG_value, ARG_all_same_value, ARG_edge, ARG_pull }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_level, MP_ARG_REQUIRED | MP_ARG_BOOL }, + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_BOOL }, + { MP_QSTR_all_same_value, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_edge, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_pull, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_arg_parse_all(0, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); + for (size_t i = 0; i < n_args; i ++) { + validate_obj_is_free_pin(pos_args[i]); + } common_hal_alarm_pin_pin_alarm_construct( - self, pin, args[ARG_level].u_bool, args[ARG_edge].u_bool, args[ARG_pull].u_bool); + self, pos_args, n_args, + args[ARG_value].u_bool, + args[ARG_all_same_value].u_bool, + args[ARG_edge].u_bool, + args[ARG_pull].u_bool); return MP_OBJ_FROM_PTR(self); } -//| def __eq__(self, other: object) -> bool: -//| """Two PinAlarm objects are equal if their durations are the same if their pin, -//| level, edge, and pull attributes are all the same.""" -//| ... -//| -STATIC mp_obj_t alarm_pin_pin_alarm_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { - switch (op) { - case MP_BINARY_OP_EQUAL: - if (MP_OBJ_IS_TYPE(rhs_in, &alarm_pin_pin_alarm_type)) { - // Pins are singletons, so we can compare them directly. - return mp_obj_new_bool( - common_hal_alarm_pin_pin_alarm_get_pin(lhs_in) == - common_hal_alarm_pin_pin_alarm_get_pin(rhs_in) && - common_hal_alarm_pin_pin_alarm_get_level(lhs_in) == - common_hal_alarm_pin_pin_alarm_get_level(rhs_in) && - common_hal_alarm_pin_pin_alarm_get_edge(lhs_in) == - common_hal_alarm_pin_pin_alarm_get_edge(rhs_in) && - common_hal_alarm_pin_pin_alarm_get_pull(lhs_in) == - common_hal_alarm_pin_pin_alarm_get_pull(rhs_in)); - } - return mp_const_false; - - default: - return MP_OBJ_NULL; // op not supported - } -} - STATIC const mp_rom_map_elem_t alarm_pin_pin_alarm_locals_dict_table[] = { }; @@ -116,6 +97,5 @@ const mp_obj_type_t alarm_pin_pin_alarm_type = { { &mp_type_type }, .name = MP_QSTR_PinAlarm, .make_new = alarm_pin_pin_alarm_make_new, - .binary_op = alarm_pin_pin_alarm_binary_op, .locals_dict = (mp_obj_t)&alarm_pin_pin_alarm_locals_dict, }; diff --git a/shared-bindings/alarm/pin/PinAlarm.h b/shared-bindings/alarm/pin/PinAlarm.h index 978ceaad5..bbf3018b5 100644 --- a/shared-bindings/alarm/pin/PinAlarm.h +++ b/shared-bindings/alarm/pin/PinAlarm.h @@ -28,13 +28,14 @@ #define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PIN_ALARM_H #include "py/obj.h" +#include "py/objtuple.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/alarm/pin/PinAlarm.h" extern const mp_obj_type_t alarm_pin_pin_alarm_type; -extern void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, const mcu_pin_obj_t *pin, bool level, bool edge, bool pull); -extern const mcu_pin_obj_t *common_hal_alarm_pin_pin_alarm_get_pin(alarm_pin_pin_alarm_obj_t *self); +void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, const mp_obj_t pins[], size_t num_pins, bool value, bool all_same_value, bool edge, bool pull); +extern const mp_obj_tuple_t *common_hal_alarm_pin_pin_alarm_get_pins(alarm_pin_pin_alarm_obj_t *self); extern bool common_hal_alarm_pin_pin_alarm_get_level(alarm_pin_pin_alarm_obj_t *self); extern bool common_hal_alarm_pin_pin_alarm_get_edge(alarm_pin_pin_alarm_obj_t *self); extern bool common_hal_alarm_pin_pin_alarm_get_pull(alarm_pin_pin_alarm_obj_t *self); diff --git a/shared-bindings/audiopwmio/__init__.h b/shared-bindings/audiopwmio/__init__.h index e4b7067d1..d7956d31e 100644 --- a/shared-bindings/audiopwmio/__init__.h +++ b/shared-bindings/audiopwmio/__init__.h @@ -24,11 +24,11 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H -#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO___INIT___H #include "py/obj.h" // Nothing now. -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO___INIT___H +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOPWMIO___INIT___H diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index b0ab842f4..ea4368821 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -76,9 +76,9 @@ STATIC mp_obj_t mcu_processor_get_reset_reason(mp_obj_t self) { MP_DEFINE_CONST_FUN_OBJ_1(mcu_processor_get_reset_reason_obj, mcu_processor_get_reset_reason); -const mp_obj_property_t mcu_reset_reason_obj = { +const mp_obj_property_t mcu_processor_reset_reason_obj = { .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&mcu_processor_get_reason_reason_obj, // getter + .proxy = {(mp_obj_t)&mcu_processor_get_reset_reason_obj, // getter (mp_obj_t)&mp_const_none_obj, // no setter (mp_obj_t)&mp_const_none_obj, // no deleter }, diff --git a/shared-bindings/microcontroller/Processor.h b/shared-bindings/microcontroller/Processor.h index a842e06f3..98d479087 100644 --- a/shared-bindings/microcontroller/Processor.h +++ b/shared-bindings/microcontroller/Processor.h @@ -29,6 +29,7 @@ #include "py/obj.h" +#include "common-hal/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" extern const mp_obj_type_t mcu_processor_type; diff --git a/shared-bindings/microcontroller/ResetReason.c b/shared-bindings/microcontroller/ResetReason.c index 151fcf315..61891934a 100644 --- a/shared-bindings/microcontroller/ResetReason.c +++ b/shared-bindings/microcontroller/ResetReason.c @@ -35,6 +35,7 @@ MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, SOFTWARE, RESET_REASON_SOFT MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, DEEP_SLEEP_ALARM, RESET_REASON_DEEP_SLEEP_ALARM); MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, RESET_PIN, RESET_REASON_RESET_PIN); MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, WATCHDOG, RESET_REASON_WATCHDOG); +MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, UNKNOWN, RESET_REASON_UNKNOWN); //| class ResetReason: //| """The reason the microntroller was last reset""" @@ -55,7 +56,10 @@ MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, WATCHDOG, RESET_REASON_WATC //| """The microntroller was reset by a signal on its reset pin. The pin might be connected to a reset button.""" //| //| WATCHDOG: object -//| """The chip microcontroller reset by its watchdog timer.""" +//| """The microcontroller was reset by its watchdog timer.""" +//| +//| UNKNOWN: object +//| """The microntroller restarted for an unknown reason.""" //| MAKE_ENUM_MAP(mcu_reset_reason) { MAKE_ENUM_MAP_ENTRY(reset_reason, POWER_ON), @@ -64,6 +68,7 @@ MAKE_ENUM_MAP(mcu_reset_reason) { MAKE_ENUM_MAP_ENTRY(reset_reason, DEEP_SLEEP_ALARM), MAKE_ENUM_MAP_ENTRY(reset_reason, RESET_PIN), MAKE_ENUM_MAP_ENTRY(reset_reason, WATCHDOG), + MAKE_ENUM_MAP_ENTRY(reset_reason, UNKNOWN), }; STATIC MP_DEFINE_CONST_DICT(mcu_reset_reason_locals_dict, mcu_reset_reason_locals_table); diff --git a/shared-bindings/microcontroller/ResetReason.h b/shared-bindings/microcontroller/ResetReason.h index df1abf266..8ed5e4831 100644 --- a/shared-bindings/microcontroller/ResetReason.h +++ b/shared-bindings/microcontroller/ResetReason.h @@ -24,8 +24,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MCU__RESET_REASON__H -#define MICROPY_INCLUDED_SHARED_BINDINGS_MCU__RESET_REASON__H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_MCU_RESET_REASON__H +#define MICROPY_INCLUDED_SHARED_BINDINGS_MCU_RESET_REASON__H #include "py/obj.h" #include "py/enum.h" @@ -37,15 +37,9 @@ typedef enum { RESET_REASON_DEEP_SLEEP_ALARM, RESET_REASON_RESET_PIN, RESET_REASON_WATCHDOG, + RESET_REASON_UNKNOWN, } mcu_reset_reason_t; -extern const cp_enum_obj_t reset_reason_POWER_ON_obj; -extern const cp_enum_obj_t reset_reason_BROWNOUT_obj; -extern const cp_enum_obj_t reset_reason_SOFTWARE_obj; -extern const cp_enum_obj_t reset_reason_DEEP_SLEEP_ALARM_obj; -extern const cp_enum_obj_t reset_reason_RESET_PIN_obj; -extern const cp_enum_obj_t reset_reason_WATCHDOG_obj; - extern const mp_obj_type_t mcu_reset_reason_type; -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MCU__RESET_REASON__H +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MCU_RESET_REASON__H diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index d09cf8f44..d6ce323c5 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -56,6 +56,19 @@ //| This object is the sole instance of `microcontroller.Processor`.""" //| +//| def deep_sleep() -> None: +//| Go into deep sleep. If the board is connected via USB, disconnect USB first. +//| +//| The board will awake from deep sleep only if the reset button is pressed +//| or it is awoken by an alarm set by `alarm.set_deep_sleep_alarms()`. +//| ... +//| +STATIC mp_obj_t mcu_deep_sleep(void){ + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_0(mcu_deep_sleep_obj, mcu_deep_sleep); + //| def delay_us(delay: int) -> None: //| """Dedicated delay method used for very short delays. **Do not** do long delays //| because this stops all other functions from completing. Think of this as an empty @@ -164,6 +177,7 @@ const mp_obj_module_t mcu_pin_module = { STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) }, { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&common_hal_mcu_processor_obj) }, + { MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&mcu_deep_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) }, diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h index ac71de424..c6ccccea7 100644 --- a/shared-bindings/microcontroller/__init__.h +++ b/shared-bindings/microcontroller/__init__.h @@ -43,6 +43,8 @@ extern void common_hal_mcu_enable_interrupts(void); extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode); extern void common_hal_mcu_reset(void); +extern void common_hal_mcu_deep_sleep(void); + extern const mp_obj_dict_t mcu_pin_globals; extern const mcu_processor_obj_t common_hal_mcu_processor_obj; diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c index ee08f6d71..7e7a74d2f 100644 --- a/shared-bindings/supervisor/RunReason.c +++ b/shared-bindings/supervisor/RunReason.c @@ -29,7 +29,7 @@ #include "shared-bindings/supervisor/RunReason.h" MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, STARTUP, RUN_REASON_STARTUP); -MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTORELOAD, RUN_REASON_AUTORELOAD); +MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTORELOAD, RUN_REASON_AUTO_RELOAD); MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, SUPERVISOR_RELOAD, RUN_REASON_SUPERVISOR_RELOAD); MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_REPL_RELOAD); @@ -40,8 +40,8 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_ //| """CircuitPython started the microcontroller started up. See `microcontroller.cpu.reset_reason` //| for more detail on why the microcontroller was started.""" //| -//| AUTORELOAD: object -//| """CircuitPython restarted due to a USB write to the filesystem.""" +//| AUTO_RELOAD: object +//| """CircuitPython restarted due to an external write to the filesystem.""" //| //| SUPERVISOR_RELOAD: object //| """CircuitPython restarted due to a call to `supervisor.reload()`.""" @@ -51,7 +51,7 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_ //| MAKE_ENUM_MAP(run_reason) { MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP), - MAKE_ENUM_MAP_ENTRY(run_reason, AUTORELOAD), + MAKE_ENUM_MAP_ENTRY(run_reason, AUTO_RELOAD), MAKE_ENUM_MAP_ENTRY(run_reason, SUPERVISOR_RELOAD), MAKE_ENUM_MAP_ENTRY(run_reason, REPL_RELOAD), }; diff --git a/shared-bindings/supervisor/RunReason.h b/shared-bindings/supervisor/RunReason.h index 934c72fd8..391e6d306 100644 --- a/shared-bindings/supervisor/RunReason.h +++ b/shared-bindings/supervisor/RunReason.h @@ -28,7 +28,7 @@ typedef enum { RUN_REASON_STARTUP, - RUN_REASON_AUTORELOAD, + RUN_REASON_AUTO_RELOAD, RUN_REASON_SUPERVISOR_RELOAD, RUN_REASON_REPL_RELOAD, } supervisor_run_reason_t; diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index 6500dadd5..67193e051 100755 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -25,9 +25,13 @@ */ #include +#include "py/enum.h" #include "py/objproperty.h" +#include "shared-bindings/supervisor/RunReason.h" #include "shared-bindings/supervisor/Runtime.h" +STATIC supervisor_run_reason_t _run_reason; + //TODO: add USB, REPL to description once they're operational //| class Runtime: //| """Current status of runtime objects. @@ -94,8 +98,7 @@ const mp_obj_property_t supervisor_serial_bytes_available_obj = { //| """Returns why CircuitPython started running this particular time. //| STATIC mp_obj_t supervisor_get_run_reason(mp_obj_t self) { - mp_raise_NotImplementedError(NULL); - return mp_const_none; + return cp_enum_find(&supervisor_run_reason_type, _run_reason); } MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_run_reason_obj, supervisor_get_run_reason); @@ -106,6 +109,9 @@ const mp_obj_property_t supervisor_run_reason_obj = { (mp_obj_t)&mp_const_none_obj}, }; +void supervisor_set_run_reason(supervisor_run_reason_t run_reason) { + _run_reason = run_reason; +} STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_serial_connected_obj) }, diff --git a/shared-bindings/supervisor/Runtime.h b/shared-bindings/supervisor/Runtime.h index 2dc59c3ab..51ed7604d 100755 --- a/shared-bindings/supervisor/Runtime.h +++ b/shared-bindings/supervisor/Runtime.h @@ -30,9 +30,12 @@ #include #include "py/obj.h" +#include "shared-bindings/supervisor/RunReason.h" extern const mp_obj_type_t supervisor_runtime_type; +void supervisor_set_run_reason(supervisor_run_reason_t run_reason); + bool common_hal_get_serial_connected(void); bool common_hal_get_serial_bytes_available(void); diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index bc6fdbff5..4d2d6db30 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -88,6 +88,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_rgb_status_brightness_obj, supervisor_s //| STATIC mp_obj_t supervisor_reload(void) { reload_requested = true; + supervisor_set_run_reason(RUN_REASON_SUPERVISOR_RELOAD); mp_raise_reload_exception(); return mp_const_none; } diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index 3d76e7000..ff08ade18 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -106,25 +106,21 @@ void usb_irq_handler(void) { // Invoked when device is mounted void tud_mount_cb(void) { usb_msc_mount(); - _workflow_active = true; } // Invoked when device is unmounted void tud_umount_cb(void) { usb_msc_umount(); - _workflow_active = false; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allows us to perform remote wakeup // USB Specs: Within 7ms, device must draw an average current less than 2.5 mA from bus void tud_suspend_cb(bool remote_wakeup_en) { - _workflow_active = false; } // Invoked when usb bus is resumed void tud_resume_cb(void) { - _workflow_active = true; } // Invoked when cdc when line state changed e.g connected/disconnected diff --git a/supervisor/shared/workflow.c b/supervisor/shared/workflow.c index cd19d3aa2..41af22eb7 100644 --- a/supervisor/shared/workflow.c +++ b/supervisor/shared/workflow.c @@ -25,10 +25,10 @@ */ #include - -// Set by the shared USB code. -volatile bool _workflow_active; +#include "tusb.h" bool supervisor_workflow_active(void) { - return _workflow_active; + // Eventually there might be other non-USB workflows, such as BLE. + // tud_ready() checks for usb mounted and not suspended. + return tud_ready(); } -- cgit v1.2.3 From 7a45afc54919162df342fab421ed113ff1771d01 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 23 Nov 2020 22:44:53 -0500 Subject: working, but need to avoid deep sleeping too fast before USB ready --- main.c | 104 ++++++++++++--------- ports/esp32s2/Makefile | 4 +- ports/esp32s2/common-hal/alarm/__init__.c | 4 +- .../esp32s2/common-hal/microcontroller/__init__.c | 4 +- py/circuitpy_defns.mk | 1 + shared-bindings/alarm/__init__.h | 3 + shared-bindings/microcontroller/__init__.c | 14 --- shared-bindings/microcontroller/__init__.h | 2 +- shared-bindings/supervisor/RunReason.c | 4 +- shared-bindings/supervisor/Runtime.c | 3 + shared-bindings/supervisor/__init__.c | 51 +++++++++- supervisor/shared/workflow.c | 26 ++++++ supervisor/shared/workflow.h | 8 +- 13 files changed, 153 insertions(+), 75 deletions(-) (limited to 'shared-bindings/supervisor/RunReason.c') diff --git a/main.c b/main.c index f77bf41d8..b2e527dde 100755 --- a/main.c +++ b/main.c @@ -47,17 +47,17 @@ #include "mpconfigboard.h" #include "supervisor/background_callback.h" #include "supervisor/cpu.h" +#include "supervisor/filesystem.h" #include "supervisor/memory.h" #include "supervisor/port.h" -#include "supervisor/filesystem.h" +#include "supervisor/serial.h" #include "supervisor/shared/autoreload.h" -#include "supervisor/shared/translate.h" #include "supervisor/shared/rgb_led_status.h" #include "supervisor/shared/safe_mode.h" -#include "supervisor/shared/status_leds.h" #include "supervisor/shared/stack.h" +#include "supervisor/shared/status_leds.h" +#include "supervisor/shared/translate.h" #include "supervisor/shared/workflow.h" -#include "supervisor/serial.h" #include "supervisor/usb.h" #include "shared-bindings/microcontroller/__init__.h" @@ -66,6 +66,8 @@ #include "boards/board.h" +#include "esp_log.h" + #if CIRCUITPY_ALARM #include "shared-bindings/alarm/__init__.h" #endif @@ -101,26 +103,6 @@ // How long to flash errors on the RGB status LED before going to sleep (secs) #define CIRCUITPY_FLASH_ERROR_PERIOD 10 -void do_str(const char *src, mp_parse_input_kind_t input_kind) { - mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); - if (lex == NULL) { - //printf("MemoryError: lexer could not allocate memory\n"); - return; - } - - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - qstr source_name = lex->source_name; - mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true); - mp_call_function_0(module_fun); - nlr_pop(); - } else { - // uncaught exception - mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); - } -} - #if MICROPY_ENABLE_PYSTACK static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]); #endif @@ -131,9 +113,13 @@ static void reset_devices(void) { #endif } -void start_mp(supervisor_allocation* heap) { +STATIC void start_mp(supervisor_allocation* heap) { reset_status_led(); autoreload_stop(); + supervisor_workflow_reset(); +#if CIRCUITPY_ALARM + alarm_reset(); +#endif // Stack limit should be less than real stack size, so we have a chance // to recover from limit hit. (Limit is measured in bytes.) @@ -182,7 +168,7 @@ void start_mp(supervisor_allocation* heap) { #endif } -void stop_mp(void) { +STATIC void stop_mp(void) { #if CIRCUITPY_NETWORK network_module_deinit(); #endif @@ -207,7 +193,7 @@ void stop_mp(void) { // Look for the first file that exists in the list of filenames, using mp_import_stat(). // Return its index. If no file found, return -1. -const char* first_existing_file_in_list(const char * const * filenames) { +STATIC const char* first_existing_file_in_list(const char * const * filenames) { for (int i = 0; filenames[i] != (char*)""; i++) { mp_import_stat_t stat = mp_import_stat(filenames[i]); if (stat == MP_IMPORT_STAT_FILE) { @@ -217,7 +203,7 @@ const char* first_existing_file_in_list(const char * const * filenames) { return NULL; } -bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result) { +STATIC bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result) { const char* filename = first_existing_file_in_list(filenames); if (filename == NULL) { return false; @@ -231,7 +217,7 @@ bool maybe_run_list(const char * const * filenames, pyexec_result_t* exec_result return true; } -void cleanup_after_vm(supervisor_allocation* heap) { +STATIC void cleanup_after_vm(supervisor_allocation* heap) { // Reset port-independent devices, like CIRCUITPY_BLEIO_HCI. reset_devices(); // Turn off the display and flush the fileystem before the heap disappears. @@ -260,7 +246,7 @@ void cleanup_after_vm(supervisor_allocation* heap) { reset_status_led(); } -void print_code_py_status_message(safe_mode_t safe_mode) { +STATIC void print_code_py_status_message(safe_mode_t safe_mode) { if (autoreload_is_enabled()) { serial_write_compressed(translate("Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\n")); } else { @@ -272,7 +258,7 @@ void print_code_py_status_message(safe_mode_t safe_mode) { } } -bool run_code_py(safe_mode_t safe_mode) { +STATIC bool run_code_py(safe_mode_t safe_mode) { bool serial_connected_at_start = serial_connected(); #if CIRCUITPY_AUTORELOAD_DELAY_MS > 0 if (serial_connected_at_start) { @@ -318,6 +304,8 @@ bool run_code_py(safe_mode_t safe_mode) { } } + // Program has finished running. + // Display a different completion message if the user has no USB attached (cannot save files) if (!serial_connected_at_start) { serial_write_compressed(translate("\nCode done running. Waiting for reload.\n")); @@ -329,11 +317,26 @@ bool run_code_py(safe_mode_t safe_mode) { #endif rgb_status_animation_t animation; bool ok = result.return_code != PYEXEC_EXCEPTION; - // If USB isn't enumerated then deep sleep. - if (ok && !supervisor_workflow_active() && supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024) { - common_hal_mcu_deep_sleep(); - } - // Show the animation every N seconds. + + ESP_LOGI("main", "common_hal_alarm_enable_deep_sleep_alarms()"); + // Decide whether to deep sleep. + #if CIRCUITPY_ALARM + // Enable pin or time alarms before sleeping. + common_hal_alarm_enable_deep_sleep_alarms(); + #endif + + // Normally we won't deep sleep if there was an error or if we are connected to a host + // but either of those can be enabled. + // *********DON'T SLEEP IF USB HASN'T HAD TIME TO ENUMERATE. + bool will_deep_sleep = + (ok || supervisor_workflow_get_allow_deep_sleep_on_error()) && + (!supervisor_workflow_active() || supervisor_workflow_get_allow_deep_sleep_when_connected()); + + ESP_LOGI("main", "ok %d", will_deep_sleep); + ESP_LOGI("main", "...on_error() %d", supervisor_workflow_get_allow_deep_sleep_on_error()); + ESP_LOGI("main", "supervisor_workflow_active() %d", supervisor_workflow_active()); + ESP_LOGI("main", "...when_connected() %d", supervisor_workflow_get_allow_deep_sleep_when_connected()); + will_deep_sleep = false; prep_rgb_status_animation(&result, found_main, safe_mode, &animation); while (true) { RUN_BACKGROUND_TASKS; @@ -356,9 +359,12 @@ bool run_code_py(safe_mode_t safe_mode) { if (!serial_connected_at_start) { print_code_py_status_message(safe_mode); } - print_safe_mode_message(safe_mode); - serial_write("\n"); - serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload.")); + // We won't be going into the REPL if we're going to sleep. + if (!will_deep_sleep) { + print_safe_mode_message(safe_mode); + serial_write("\n"); + serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload.")); + } } if (serial_connected_before_animation && !serial_connected()) { serial_connected_at_start = false; @@ -371,16 +377,22 @@ bool run_code_py(safe_mode_t safe_mode) { refreshed_epaper_display = maybe_refresh_epaperdisplay(); } #endif - bool animation_done = tick_rgb_status_animation(&animation); - if (animation_done && supervisor_workflow_active()) { - #if CIRCUITPY_ALARM + + bool animation_done = false; + if (will_deep_sleep && ok) { + // Skip animation if everything is OK. + animation_done = true; + } else { + animation_done = tick_rgb_status_animation(&animation); + } + // Do an error animation only once before deep-sleeping. + if (animation_done && will_deep_sleep) { int64_t remaining_enumeration_wait = CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64(); // If USB isn't enumerated then deep sleep after our waiting period. if (ok && remaining_enumeration_wait < 0) { common_hal_mcu_deep_sleep(); - return false; // Doesn't actually get here. + // Does not return. } - #endif // Wake up every so often to flash the error code. if (!ok) { port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024); @@ -394,7 +406,7 @@ bool run_code_py(safe_mode_t safe_mode) { FIL* boot_output_file; -void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { +STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { // If not in safe mode, run boot before initing USB and capture output in a // file. if (filesystem_present() && safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) { @@ -473,7 +485,7 @@ void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { } } -int run_repl(void) { +STATIC int run_repl(void) { int exit_code = PYEXEC_FORCED_EXIT; stack_resize(); filesystem_flush(); diff --git a/ports/esp32s2/Makefile b/ports/esp32s2/Makefile index 55d6e91d4..794df0dab 100644 --- a/ports/esp32s2/Makefile +++ b/ports/esp32s2/Makefile @@ -332,10 +332,10 @@ $(BUILD)/firmware.uf2: $(BUILD)/circuitpython-firmware.bin $(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xbfdd4eee -b 0x0000 -c -o $@ $^ flash: $(BUILD)/firmware.bin - esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x0000 $^ + esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x0000 $^ flash-circuitpython-only: $(BUILD)/circuitpython-firmware.bin - esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x10000 $^ + esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=no_reset write_flash $(FLASH_FLAGS) 0x10000 $^ include $(TOP)/py/mkrules.mk diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 0ea476d86..87276bdaf 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -95,7 +95,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _deep_sleep_alarms = mp_obj_new_tuple(n_alarms, alarms); } -void common_hal_deep_sleep_with_alarms(void) { +void common_hal_alarm_enable_deep_sleep_alarms(void) { for (size_t i = 0; i < _deep_sleep_alarms->len; i++) { mp_obj_t alarm = _deep_sleep_alarms->items[i]; if (MP_OBJ_IS_TYPE(alarm, &alarm_time_duration_alarm_type)) { @@ -105,6 +105,4 @@ void common_hal_deep_sleep_with_alarms(void) { } // TODO: handle pin alarms } - - common_hal_mcu_deep_sleep(); } diff --git a/ports/esp32s2/common-hal/microcontroller/__init__.c b/ports/esp32s2/common-hal/microcontroller/__init__.c index 59eb1afcc..5aa0ff8ed 100644 --- a/ports/esp32s2/common-hal/microcontroller/__init__.c +++ b/ports/esp32s2/common-hal/microcontroller/__init__.c @@ -80,11 +80,9 @@ void common_hal_mcu_reset(void) { while(1); } -void common_hal_mcu_deep_sleep(void) { +void NORETURN common_hal_mcu_deep_sleep(void) { // Shut down wifi cleanly. esp_wifi_stop(); - - // Does not return. esp_deep_sleep_start(); } diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 2731f2ae8..27466282a 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -403,6 +403,7 @@ $(filter $(SRC_PATTERNS), \ math/__init__.c \ microcontroller/ResetReason.c \ microcontroller/RunMode.c \ + supervisor/RunReason.c \ ) SRC_BINDINGS_ENUMS += \ diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index c74dfbe5c..d8d6812c9 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -29,7 +29,10 @@ #include "py/obj.h" +#include "common-hal/alarm/__init__.h" + extern mp_obj_t common_hal_alarm_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms); +extern void common_hal_alarm_enable_deep_sleep_alarms(void); extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms); // Used by wake-up code. diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index d6ce323c5..d09cf8f44 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -56,19 +56,6 @@ //| This object is the sole instance of `microcontroller.Processor`.""" //| -//| def deep_sleep() -> None: -//| Go into deep sleep. If the board is connected via USB, disconnect USB first. -//| -//| The board will awake from deep sleep only if the reset button is pressed -//| or it is awoken by an alarm set by `alarm.set_deep_sleep_alarms()`. -//| ... -//| -STATIC mp_obj_t mcu_deep_sleep(void){ - - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_0(mcu_deep_sleep_obj, mcu_deep_sleep); - //| def delay_us(delay: int) -> None: //| """Dedicated delay method used for very short delays. **Do not** do long delays //| because this stops all other functions from completing. Think of this as an empty @@ -177,7 +164,6 @@ const mp_obj_module_t mcu_pin_module = { STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) }, { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&common_hal_mcu_processor_obj) }, - { MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&mcu_deep_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_interrupts), MP_ROM_PTR(&mcu_disable_interrupts_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_interrupts), MP_ROM_PTR(&mcu_enable_interrupts_obj) }, diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h index c6ccccea7..87284fc2e 100644 --- a/shared-bindings/microcontroller/__init__.h +++ b/shared-bindings/microcontroller/__init__.h @@ -43,7 +43,7 @@ extern void common_hal_mcu_enable_interrupts(void); extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode); extern void common_hal_mcu_reset(void); -extern void common_hal_mcu_deep_sleep(void); +extern void NORETURN common_hal_mcu_deep_sleep(void); extern const mp_obj_dict_t mcu_pin_globals; diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c index 7e7a74d2f..73f62fed6 100644 --- a/shared-bindings/supervisor/RunReason.c +++ b/shared-bindings/supervisor/RunReason.c @@ -29,7 +29,7 @@ #include "shared-bindings/supervisor/RunReason.h" MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, STARTUP, RUN_REASON_STARTUP); -MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTORELOAD, RUN_REASON_AUTO_RELOAD); +MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, AUTO_RELOAD, RUN_REASON_AUTO_RELOAD); MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, SUPERVISOR_RELOAD, RUN_REASON_SUPERVISOR_RELOAD); MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_REPL_RELOAD); @@ -49,7 +49,7 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_ //| REPL_RELOAD: object //| """CircuitPython started due to the user typing CTRL-D in the REPL.""" //| -MAKE_ENUM_MAP(run_reason) { +MAKE_ENUM_MAP(supervisor_run_reason) { MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP), MAKE_ENUM_MAP_ENTRY(run_reason, AUTO_RELOAD), MAKE_ENUM_MAP_ENTRY(run_reason, SUPERVISOR_RELOAD), diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index 67193e051..1a283b35c 100755 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -25,8 +25,11 @@ */ #include +#include "py/obj.h" #include "py/enum.h" +#include "py/runtime.h" #include "py/objproperty.h" + #include "shared-bindings/supervisor/RunReason.h" #include "shared-bindings/supervisor/Runtime.h" diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index 4d2d6db30..c13b19e48 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -32,7 +32,9 @@ #include "supervisor/shared/rgb_led_status.h" #include "supervisor/shared/stack.h" #include "supervisor/shared/translate.h" +#include "supervisor/shared/workflow.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/supervisor/__init__.h" #include "shared-bindings/supervisor/Runtime.h" @@ -45,6 +47,47 @@ //| This object is the sole instance of `supervisor.Runtime`.""" //| +//| def allow_deep_sleep(*, when_connected: bool = False, on_error: bool = False): +//| """Configure when CircuitPython can go into deep sleep. Deep sleep can occur +//| after a program has finished running or when `supervisor.deep_sleep_now()` is called. +//| +//| :param bool when_connected: If ``True``, CircuitPython will go into deep sleep +//| when a program finishes, even if it is connected to a host computer over USB or other means. +//| It will disconnect from the host before sleeping. +//| If ``False``, deep sleep will not be entered if connected. +//| :param bool on_error: If ``True``, deep sleep will be entered if even a program +//| terminated due to an exception or fatal error. If ``False``, an error will cause +//| CircuitPython to stay awake, flashing error codes on the status RGB LED, if available. +//| ... +//| +STATIC mp_obj_t supervisor_allow_deep_sleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_when_connected, ARG_on_error }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_when_connected, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_on_error, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + supervisor_workflow_set_allow_deep_sleep_when_connected(args[ARG_when_connected].u_bool); + supervisor_workflow_set_allow_deep_sleep_on_error(args[ARG_on_error].u_bool); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_allow_deep_sleep_obj, 0, supervisor_allow_deep_sleep); + +//| def deep_sleep(): -> None +//| """Go into deep sleep mode immediately, if not connected to a host computer. +//| But if connected and `supervisor.runtime.allow_deep_sleep(when_connected=true)` +//| has not been called, simply restart. +//| + +STATIC mp_obj_t supervisor_deep_sleep(void) { + common_hal_mcu_deep_sleep(); +} +MP_DEFINE_CONST_FUN_OBJ_0(supervisor_deep_sleep_obj, supervisor_deep_sleep); + //| def enable_autoreload() -> None: //| """Enable autoreload based on USB file write activity.""" //| ... @@ -112,9 +155,11 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_next_stack_limit_obj, supervisor_set_ne STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_allow_deep_sleep), MP_ROM_PTR(&supervisor_allow_deep_sleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&supervisor_deep_sleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) }, { MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) }, { MP_ROM_QSTR(MP_QSTR_reload), MP_ROM_PTR(&supervisor_reload_obj) }, { MP_ROM_QSTR(MP_QSTR_set_next_stack_limit), MP_ROM_PTR(&supervisor_set_next_stack_limit_obj) }, diff --git a/supervisor/shared/workflow.c b/supervisor/shared/workflow.c index 41af22eb7..67d191172 100644 --- a/supervisor/shared/workflow.c +++ b/supervisor/shared/workflow.c @@ -25,10 +25,36 @@ */ #include +#include "py/mpconfig.h" #include "tusb.h" +STATIC bool _allow_deep_sleep_when_connected; +STATIC bool _allow_deep_sleep_on_error; + + +void supervisor_workflow_reset(void) { + _allow_deep_sleep_when_connected = false; + _allow_deep_sleep_on_error = false; +} + bool supervisor_workflow_active(void) { // Eventually there might be other non-USB workflows, such as BLE. // tud_ready() checks for usb mounted and not suspended. return tud_ready(); } + +bool supervisor_workflow_get_allow_deep_sleep_when_connected(void) { + return _allow_deep_sleep_when_connected; +} + +void supervisor_workflow_set_allow_deep_sleep_when_connected(bool allow) { + _allow_deep_sleep_when_connected = allow; +} + +bool supervisor_workflow_get_allow_deep_sleep_on_error(void) { + return _allow_deep_sleep_on_error; +} + +void supervisor_workflow_set_allow_deep_sleep_on_error(bool allow) { + _allow_deep_sleep_on_error = allow; +} diff --git a/supervisor/shared/workflow.h b/supervisor/shared/workflow.h index 2968961f4..97584a1f4 100644 --- a/supervisor/shared/workflow.h +++ b/supervisor/shared/workflow.h @@ -26,6 +26,12 @@ #pragma once -extern volatile bool _workflow_active; +extern void supervisor_workflow_reset(void); extern bool supervisor_workflow_active(void); + +extern bool supervisor_workflow_get_allow_deep_sleep_when_connected(void); +extern void supervisor_workflow_set_allow_deep_sleep_when_connected(bool allow); + +extern bool supervisor_workflow_get_allow_deep_sleep_on_error(void); +extern void supervisor_workflow_set_allow_deep_sleep_on_error(bool allow); -- cgit v1.2.3 From f868cc5dd02319957500180541281f41ec0d0573 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 24 Nov 2020 23:36:59 -0500 Subject: some API renaming and bug fixes; fix docs --- main.c | 50 ++++++++++++++++------------- shared-bindings/alarm/__init__.c | 4 +-- shared-bindings/alarm/pin/PinAlarm.c | 34 ++++++++++---------- shared-bindings/alarm/time/DurationAlarm.c | 6 ++-- shared-bindings/microcontroller/Processor.c | 4 +-- shared-bindings/supervisor/RunReason.c | 2 +- shared-bindings/supervisor/Runtime.c | 2 +- shared-bindings/supervisor/__init__.c | 37 ++++++++++----------- 8 files changed, 73 insertions(+), 66 deletions(-) (limited to 'shared-bindings/supervisor/RunReason.c') diff --git a/main.c b/main.c index b2e527dde..10066bd92 100755 --- a/main.c +++ b/main.c @@ -98,7 +98,7 @@ #endif // How long to wait for host to enumerate (secs). -#define CIRCUITPY_USB_ENUMERATION_DELAY 1 +#define CIRCUITPY_USB_ENUMERATION_DELAY 5 // How long to flash errors on the RGB status LED before going to sleep (secs) #define CIRCUITPY_FLASH_ERROR_PERIOD 10 @@ -319,26 +319,28 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { bool ok = result.return_code != PYEXEC_EXCEPTION; ESP_LOGI("main", "common_hal_alarm_enable_deep_sleep_alarms()"); - // Decide whether to deep sleep. #if CIRCUITPY_ALARM // Enable pin or time alarms before sleeping. common_hal_alarm_enable_deep_sleep_alarms(); #endif - // Normally we won't deep sleep if there was an error or if we are connected to a host - // but either of those can be enabled. - // *********DON'T SLEEP IF USB HASN'T HAD TIME TO ENUMERATE. - bool will_deep_sleep = - (ok || supervisor_workflow_get_allow_deep_sleep_on_error()) && - (!supervisor_workflow_active() || supervisor_workflow_get_allow_deep_sleep_when_connected()); - - ESP_LOGI("main", "ok %d", will_deep_sleep); - ESP_LOGI("main", "...on_error() %d", supervisor_workflow_get_allow_deep_sleep_on_error()); - ESP_LOGI("main", "supervisor_workflow_active() %d", supervisor_workflow_active()); - ESP_LOGI("main", "...when_connected() %d", supervisor_workflow_get_allow_deep_sleep_when_connected()); - will_deep_sleep = false; + prep_rgb_status_animation(&result, found_main, safe_mode, &animation); while (true) { + // Normally we won't deep sleep if there was an error or if we are connected to a host + // but either of those can be enabled. + // It's ok to deep sleep if we're not connected to a host, but we need to make sure + // we're giving enough time for USB enumeration to happen. + bool deep_sleep_allowed = + (ok || supervisor_workflow_get_allow_deep_sleep_on_error()) && + (!supervisor_workflow_active() || supervisor_workflow_get_allow_deep_sleep_when_connected()) && + (supervisor_ticks_ms64() > CIRCUITPY_USB_ENUMERATION_DELAY * 1024); + + ESP_LOGI("main", "ok %d", deep_sleep_allowed); + ESP_LOGI("main", "...on_error() %d", supervisor_workflow_get_allow_deep_sleep_on_error()); + ESP_LOGI("main", "supervisor_workflow_active() %d", supervisor_workflow_active()); + ESP_LOGI("main", "...when_connected() %d", supervisor_workflow_get_allow_deep_sleep_when_connected()); + ESP_LOGI("main", "supervisor_ticks_ms64() %lld", supervisor_ticks_ms64()); RUN_BACKGROUND_TASKS; if (reload_requested) { supervisor_set_run_reason(RUN_REASON_AUTO_RELOAD); @@ -360,7 +362,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { print_code_py_status_message(safe_mode); } // We won't be going into the REPL if we're going to sleep. - if (!will_deep_sleep) { + if (!deep_sleep_allowed) { print_safe_mode_message(safe_mode); serial_write("\n"); serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload.")); @@ -379,27 +381,31 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { #endif bool animation_done = false; - if (will_deep_sleep && ok) { + + if (deep_sleep_allowed && ok) { // Skip animation if everything is OK. animation_done = true; } else { animation_done = tick_rgb_status_animation(&animation); } // Do an error animation only once before deep-sleeping. - if (animation_done && will_deep_sleep) { - int64_t remaining_enumeration_wait = CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64(); - // If USB isn't enumerated then deep sleep after our waiting period. - if (ok && remaining_enumeration_wait < 0) { + if (animation_done) { + if (deep_sleep_allowed) { common_hal_mcu_deep_sleep(); // Does not return. } + // Wake up every so often to flash the error code. if (!ok) { port_interrupt_after_ticks(CIRCUITPY_FLASH_ERROR_PERIOD * 1024); } else { - port_interrupt_after_ticks(remaining_enumeration_wait); + int64_t remaining_enumeration_wait = + CIRCUITPY_USB_ENUMERATION_DELAY * 1024 - supervisor_ticks_ms64(); + if (remaining_enumeration_wait > 0) { + port_interrupt_after_ticks(remaining_enumeration_wait); + } + port_sleep_until_interrupt(); } - port_sleep_until_interrupt(); } } } diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 22b2e7f6a..b6b86c835 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -38,7 +38,7 @@ //| //| Light sleep leaves the CPU and RAM powered so that CircuitPython can resume where it left off //| after being woken up. CircuitPython automatically goes into a light sleep when `time.sleep()` is -//| called. To light sleep until a non-time alarm use `alarm.sleep_until_alarm()`. Any active +//| called. To light sleep until a non-time alarm use `alarm.sleep_until_alarms()`. Any active //| peripherals, such as I2C, are left on. //| //| Deep sleep shuts down power to nearly all of the chip including the CPU and RAM. This can save @@ -51,7 +51,7 @@ //| //| An error includes an uncaught exception, or sys.exit() called with a non-zero argument //| -//| To set alarms for deep sleep use `alarm.restart_on_alarm()` they will apply to next deep sleep only.""" +//| To set alarms for deep sleep use `alarm.set_deep_sleep_alarms()` they will apply to next deep sleep only.""" //| //| wake_alarm: Alarm //| """The most recent alarm to wake us up from a sleep (light or deep.)""" diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index a2d2e0ab7..bb48b93c4 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -38,26 +38,26 @@ //| """Trigger an alarm when a pin changes state.""" //| //| def __init__(self, *pins: microcontroller.Pin, value: bool, all_same_value: bool = False, edge: bool = False, pull: bool = False) -> None: -//| """Create an alarm triggered by a `~microcontroller.Pin` level. The alarm is not active -//| until it is listed in an `alarm`-enabling function, such as `alarm.sleep_until_alarm()` or -//| `alarm.restart_on_alarm()`. +//| """Create an alarm triggered by a `microcontroller.Pin` level. The alarm is not active +//| until it is listed in an `alarm`-enabling function, such as `alarm.sleep_until_alarms()` or +//| `alarm.set_deep_sleep_alarms()`. //| -//| :param pins: The pins to monitor. On some ports, the choice of pins -//| may be limited due to hardware restrictions, particularly for deep-sleep alarms. +//| :param microcontroller.Pin \*pins: The pins to monitor. On some ports, the choice of pins +//| may be limited due to hardware restrictions, particularly for deep-sleep alarms. //| :param bool value: When active, trigger when the pin value is high (``True``) or low (``False``). -//| On some ports, multiple `PinAlarm` objects may need to have coordinated values -//| for deep-sleep alarms. -//| :param bool all_same_value: If ``True``, all pins listed must be at `value` to trigger the alarm. -//| If ``False``, any one of the pins going to `value` will trigger the alarm. +//| On some ports, multiple `PinAlarm` objects may need to have coordinated values +//| for deep-sleep alarms. +//| :param bool all_same_value: If ``True``, all pins listed must be at ``value`` to trigger the alarm. +//| If ``False``, any one of the pins going to ``value`` will trigger the alarm. //| :param bool edge: If ``True``, trigger only when there is a transition to the specified -//| value of `value`. If ``True``, if the alarm becomes active when the pin value already -//| matches `value`, the alarm is not triggered: the pin must transition from ``not value`` -//| to ``value`` to trigger the alarm. On some ports, edge-triggering may not be available, -//| particularly for deep-sleep alarms. -//| :param bool pull: Enable a pull-up or pull-down which pulls the pin to value opposite -//| opposite that of `value`. For instance, if `value` is set to ``True``, setting `pull` -//| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal -//| pulls it high. +//| value of ``value``. If ``True``, if the alarm becomes active when the pin value already +//| matches ``value``, the alarm is not triggered: the pin must transition from ``not value`` +//| to ``value`` to trigger the alarm. On some ports, edge-triggering may not be available, +//| particularly for deep-sleep alarms. +//| :param bool pull: Enable a pull-up or pull-down which pulls the pin to the level opposite +//| opposite that of ``value``. For instance, if ``value`` is set to ``True``, setting ``pull`` +//| to ``True`` will enable a pull-down, to hold the pin low normally until an outside signal +//| pulls it high. //| """ //| ... //| diff --git a/shared-bindings/alarm/time/DurationAlarm.c b/shared-bindings/alarm/time/DurationAlarm.c index c105bbebf..6831aba5d 100644 --- a/shared-bindings/alarm/time/DurationAlarm.c +++ b/shared-bindings/alarm/time/DurationAlarm.c @@ -37,10 +37,10 @@ //| """Trigger an alarm at a specified interval from now.""" //| //| def __init__(self, secs: float) -> None: -//| """Create an alarm that will be triggered in `secs` seconds from the time +//| """Create an alarm that will be triggered in ``secs`` seconds from the time //| sleep starts. The alarm is not active until it is listed in an -//| `alarm`-enabling function, such as `alarm.sleep_until_alarm()` or -//| `alarm.restart_on_alarm()`. +//| `alarm`-enabling function, such as `alarm.sleep_until_alarms()` or +//| `alarm.set_deep_sleep_alarms()`. //| """ //| ... //| diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index ea4368821..90cc02fe3 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -67,8 +67,8 @@ const mp_obj_property_t mcu_processor_frequency_obj = { }, }; -//| reset_reason: `microcontroller.ResetReason` -//| """The reason the microcontroller started up from reset state.""" +//| reset_reason: microcontroller.ResetReason +//| """The reason the microcontroller started up from reset state.""" //| STATIC mp_obj_t mcu_processor_get_reset_reason(mp_obj_t self) { return cp_enum_find(&mcu_reset_reason_type, common_hal_mcu_processor_get_reset_reason()); diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c index 73f62fed6..a2a5fe13e 100644 --- a/shared-bindings/supervisor/RunReason.c +++ b/shared-bindings/supervisor/RunReason.c @@ -37,7 +37,7 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_ //| """The reason that CircuitPython started running.""" //| //| STARTUP: object -//| """CircuitPython started the microcontroller started up. See `microcontroller.cpu.reset_reason` +//| """CircuitPython started the microcontroller started up. See `microcontroller.Processor.reset_reason` //| for more detail on why the microcontroller was started.""" //| //| AUTO_RELOAD: object diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index 1a283b35c..8e0259a3b 100755 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -98,7 +98,7 @@ const mp_obj_property_t supervisor_serial_bytes_available_obj = { //| run_reason: RunReason -//| """Returns why CircuitPython started running this particular time. +//| """Returns why CircuitPython started running this particular time.""" //| STATIC mp_obj_t supervisor_get_run_reason(mp_obj_t self) { return cp_enum_find(&supervisor_run_reason_type, _run_reason); diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index c13b19e48..9a7890a87 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -47,18 +47,19 @@ //| This object is the sole instance of `supervisor.Runtime`.""" //| -//| def allow_deep_sleep(*, when_connected: bool = False, on_error: bool = False): -//| """Configure when CircuitPython can go into deep sleep. Deep sleep can occur -//| after a program has finished running or when `supervisor.deep_sleep_now()` is called. +//| def allow_deep_sleep(*, when_connected: bool = False, on_error: bool = False) -> None: +//| """Configure when CircuitPython can go into deep sleep. Deep sleep can occur +//| after a program has finished running or when `supervisor.exit_and_deep_sleep()` is called. //| -//| :param bool when_connected: If ``True``, CircuitPython will go into deep sleep -//| when a program finishes, even if it is connected to a host computer over USB or other means. -//| It will disconnect from the host before sleeping. -//| If ``False``, deep sleep will not be entered if connected. -//| :param bool on_error: If ``True``, deep sleep will be entered if even a program -//| terminated due to an exception or fatal error. If ``False``, an error will cause -//| CircuitPython to stay awake, flashing error codes on the status RGB LED, if available. -//| ... +//| :param bool when_connected: If ``True``, CircuitPython will go into deep sleep +//| when a program finishes, even if it is connected to a host computer over USB or other means. +//| It will disconnect from the host before sleeping. +//| If ``False``, deep sleep will not be entered if connected. +//| :param bool on_error: If ``True``, deep sleep will be entered if even a program +//| terminated due to an exception or fatal error. If ``False``, an error will cause +//| CircuitPython to stay awake, flashing error codes on the status RGB LED, if available. +//| """ +//| ... //| STATIC mp_obj_t supervisor_allow_deep_sleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_when_connected, ARG_on_error }; @@ -77,16 +78,16 @@ STATIC mp_obj_t supervisor_allow_deep_sleep(size_t n_args, const mp_obj_t *pos_a } MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_allow_deep_sleep_obj, 0, supervisor_allow_deep_sleep); -//| def deep_sleep(): -> None +//| def exit_and_deep_sleep() -> None: //| """Go into deep sleep mode immediately, if not connected to a host computer. -//| But if connected and `supervisor.runtime.allow_deep_sleep(when_connected=true)` -//| has not been called, simply restart. -//| +//| But if connected and ``supervisor.allow_deep_sleep(when_connected=true)`` +//| has not been called, simply restart.""" +//| ... -STATIC mp_obj_t supervisor_deep_sleep(void) { +STATIC mp_obj_t supervisor_exit_and_deep_sleep(void) { common_hal_mcu_deep_sleep(); } -MP_DEFINE_CONST_FUN_OBJ_0(supervisor_deep_sleep_obj, supervisor_deep_sleep); +MP_DEFINE_CONST_FUN_OBJ_0(supervisor_exit_and_deep_sleep_obj, supervisor_exit_and_deep_sleep); //| def enable_autoreload() -> None: //| """Enable autoreload based on USB file write activity.""" @@ -156,7 +157,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(supervisor_set_next_stack_limit_obj, supervisor_set_ne STATIC const mp_rom_map_elem_t supervisor_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) }, { MP_ROM_QSTR(MP_QSTR_allow_deep_sleep), MP_ROM_PTR(&supervisor_allow_deep_sleep_obj) }, - { MP_ROM_QSTR(MP_QSTR_deep_sleep), MP_ROM_PTR(&supervisor_deep_sleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_exit_and_deep_sleep), MP_ROM_PTR(&supervisor_exit_and_deep_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_enable_autoreload), MP_ROM_PTR(&supervisor_enable_autoreload_obj) }, { MP_ROM_QSTR(MP_QSTR_disable_autoreload), MP_ROM_PTR(&supervisor_disable_autoreload_obj) }, { MP_ROM_QSTR(MP_QSTR_set_rgb_status_brightness), MP_ROM_PTR(&supervisor_set_rgb_status_brightness_obj) }, -- cgit v1.2.3