From bde1c4166d08bd9530b1dc4dcf3bfff7f3e33bca Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sat, 28 Nov 2020 23:09:05 +0100 Subject: Revert "Prevent exceptions from accumulating in REPL" This reverts commit 0cd951fb73198f5c3dd03ea0463382edac0d3d4d. It is not a correct solution because it prevents printing the same exception twice. --- py/obj.c | 1 - 1 file changed, 1 deletion(-) (limited to 'py') diff --git a/py/obj.c b/py/obj.c index d8e34746c..b6462641c 100644 --- a/py/obj.c +++ b/py/obj.c @@ -125,7 +125,6 @@ void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) { mp_printf(print, decompressed_block, block); } } - mp_obj_exception_clear_traceback(exc); } } mp_obj_print_helper(print, exc, PRINT_EXC); -- cgit v1.2.3 From fc23a0cc8ac40115047c2430c700c0832ba979eb Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Tue, 8 Dec 2020 11:30:00 +0530 Subject: implement ota module --- ports/esp32s2/common-hal/ota/__init__.c | 31 ++++++++++++++++++++ ports/esp32s2/mpconfigport.mk | 1 + py/circuitpy_defns.mk | 4 +++ py/circuitpy_mpconfig.h | 8 ++++++ py/circuitpy_mpconfig.mk | 3 ++ shared-bindings/ota/__init__.c | 51 +++++++++++++++++++++++++++++++++ shared-bindings/ota/__init__.h | 34 ++++++++++++++++++++++ 7 files changed, 132 insertions(+) create mode 100644 ports/esp32s2/common-hal/ota/__init__.c create mode 100644 shared-bindings/ota/__init__.c create mode 100644 shared-bindings/ota/__init__.h (limited to 'py') diff --git a/ports/esp32s2/common-hal/ota/__init__.c b/ports/esp32s2/common-hal/ota/__init__.c new file mode 100644 index 000000000..87daffa56 --- /dev/null +++ b/ports/esp32s2/common-hal/ota/__init__.c @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/ota/__init__.h" + +void common_hal_ota_flash(const void *buf, const size_t len) { + +} diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index b3b2a6d70..da231107f 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -23,6 +23,7 @@ CIRCUITPY_FREQUENCYIO = 1 CIRCUITPY_I2CPERIPHERAL = 0 CIRCUITPY_ROTARYIO = 1 CIRCUITPY_NVM = 1 +CIRCUITPY_OTA = 1 # We don't have enough endpoints to include MIDI. CIRCUITPY_USB_MIDI = 0 CIRCUITPY_WIFI = 1 diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index e9253682e..68e806d4b 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -205,6 +205,9 @@ endif ifeq ($(CIRCUITPY_OS),1) SRC_PATTERNS += os/% endif +ifeq ($(CIRCUITPY_OTA),1) +SRC_PATTERNS += ota/% +endif ifeq ($(CIRCUITPY_PIXELBUF),1) SRC_PATTERNS += _pixelbuf/% endif @@ -347,6 +350,7 @@ SRC_COMMON_HAL_ALL = \ nvm/ByteArray.c \ nvm/__init__.c \ os/__init__.c \ + ota/__init__.c \ ps2io/Ps2.c \ ps2io/__init__.c \ pulseio/PulseIn.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index f04112bfc..b432757b3 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -539,6 +539,13 @@ extern const struct _mp_obj_module_t os_module; #define OS_MODULE_ALT_NAME #endif +#if CIRCUITPY_OTA +extern const struct _mp_obj_module_t ota_module; +#define OTA_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_ota), (mp_obj_t)&ota_module }, +#else +#define OTA_MODULE +#endif + #if CIRCUITPY_PEW extern const struct _mp_obj_module_t pew_module; #define PEW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pew),(mp_obj_t)&pew_module }, @@ -827,6 +834,7 @@ extern const struct _mp_obj_module_t wifi_module; NETWORK_MODULE \ SOCKET_MODULE \ WIZNET_MODULE \ + OTA_MODULE \ PEW_MODULE \ PIXELBUF_MODULE \ PS2IO_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 370f13373..09074bf53 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -179,6 +179,9 @@ CFLAGS += -DCIRCUITPY_NVM=$(CIRCUITPY_NVM) CIRCUITPY_OS ?= 1 CFLAGS += -DCIRCUITPY_OS=$(CIRCUITPY_OS) +CIRCUITPY_OTA ?= 0 +CFLAGS += -DCIRCUITPY_OTA=$(CIRCUITPY_OTA) + CIRCUITPY_PIXELBUF ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_PIXELBUF=$(CIRCUITPY_PIXELBUF) diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c new file mode 100644 index 000000000..a6c042486 --- /dev/null +++ b/shared-bindings/ota/__init__.c @@ -0,0 +1,51 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/ota/__init__.h" + +//| """ota module +//| +//| The `ota` module implements over-the-air update.""" + +STATIC mp_obj_t ota_flash(mp_obj_t program_binary_in) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(program_binary_in, &bufinfo, MP_BUFFER_READ); + + common_hal_ota_flash(bufinfo.buf, bufinfo.len); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(ota_flash_obj, ota_flash); + +STATIC const mp_rom_map_elem_t ota_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ota) }, + { MP_ROM_QSTR(MP_QSTR_flash), MP_ROM_PTR(&ota_flash_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(ota_module_globals, ota_module_globals_table); + +const mp_obj_module_t ota_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&ota_module_globals, +}; diff --git a/shared-bindings/ota/__init__.h b/shared-bindings/ota/__init__.h new file mode 100644 index 000000000..c4b40b2af --- /dev/null +++ b/shared-bindings/ota/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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_OTA___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_OTA___INIT___H + +#include "py/runtime.h" + +extern void common_hal_ota_flash(const void *buf, const size_t len); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_OTA___INIT___H -- cgit v1.2.3 From 5964163649e1f4309665dc870861729eba4e0f31 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 10 Dec 2020 13:03:40 -0500 Subject: Initial SleepMemory code --- ports/esp32s2/common-hal/alarm/SleepMemory.c | 62 +++++++++ ports/esp32s2/common-hal/alarm/SleepMemory.h | 63 ++++++++++ ports/esp32s2/common-hal/alarm/__init__.c | 16 ++- ports/esp32s2/common-hal/alarm/__init__.h | 6 +- py/circuitpy_defns.mk | 1 + shared-bindings/alarm/SleepMemory.c | 180 +++++++++++++++++++++++++++ shared-bindings/alarm/SleepMemory.h | 44 +++++++ shared-bindings/alarm/__init__.c | 6 +- 8 files changed, 373 insertions(+), 5 deletions(-) create mode 100644 ports/esp32s2/common-hal/alarm/SleepMemory.c create mode 100644 ports/esp32s2/common-hal/alarm/SleepMemory.h create mode 100644 shared-bindings/alarm/SleepMemory.c create mode 100644 shared-bindings/alarm/SleepMemory.h (limited to 'py') diff --git a/ports/esp32s2/common-hal/alarm/SleepMemory.c b/ports/esp32s2/common-hal/alarm/SleepMemory.c new file mode 100644 index 000000000..2579eb5fc --- /dev/null +++ b/ports/esp32s2/common-hal/alarm/SleepMemory.c @@ -0,0 +1,62 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * 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 + +#include "py/runtime.h" +#include "common-hal/alarm/SleepMemory.h" + +#include "esp_sleep.h" + +void alarm_sleep_memory_reset(void) { + // Power RTC slow memory during deep sleep + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON); +} + +uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self) { + return SLEEP_MEMORY_LENGTH; +} + +bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, + uint32_t start_index, uint8_t* values, uint32_t len) { + + if (start_index + len > SLEEP_MEMORY_LENGTH) { + return false; + } + + memcpy((uint8_t *) (SLEEP_MEMORY_BASE + start_index), values, len); + return true; +} + +void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, + uint32_t start_index, uint32_t len, uint8_t* values) { + + if (start_index + len > SLEEP_MEMORY_LENGTH) { + return; + } + memcpy(values, (uint8_t *) (SLEEP_MEMORY_BASE + start_index), len); +} diff --git a/ports/esp32s2/common-hal/alarm/SleepMemory.h b/ports/esp32s2/common-hal/alarm/SleepMemory.h new file mode 100644 index 000000000..adf7b35ae --- /dev/null +++ b/ports/esp32s2/common-hal/alarm/SleepMemory.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM_SLEEPMEMORY_H +#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM_SLEEPMEMORY_H + +#include "py/obj.h" + +#define SLEEP_MEMORY_LENGTH (8192) + +// There are several places we could store persistent data for SleepMemory: +// +// RTC registers: There are a few 32-bit registers maintained during deep sleep. +// We are already using one for saving sleep information during deep sleep. +// +// RTC Fast Memory: 8kB, also used for deep-sleep power on stub, and for heap +// during normal operation if CONFIG_ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP is set. +// Power-on during deep sleep must be enabled. +// I experimented with using RTC Fast Memory. It seemed to work, but occasionally, +// got smashed for unknown reasons. +// Base of RTC Fast memory on the data bus is 0x3FF9E000. The address is different on the instruction bus. +// +// RTC Slow Memory: 8kB, also used for the ULP (tiny co-processor available during sleep). +// Less likely to be used by ESP-IDF. +// Since we may want to use the ULP in the future, we will use the upper half +// of Slow Memory and reserve the lower half for ULP. +// From ulp.h: +// #define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */ + +// Upper half of RTC_SLOW_MEM. +#define SLEEP_MEMORY_LENGTH (4096) +#define SLEEP_MEMORY_BASE (0x50000000 + 4096) + +typedef struct { + mp_obj_base_t base; +} alarm_sleep_memory_obj_t; + +extern void alarm_sleep_memory_reset(void); + +#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM_SLEEPMEMORY_H diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 529179200..fae921db0 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -1,10 +1,10 @@ - /* +/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * - * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries - * Copyright (c) 2019 Lucian Copeland for Adafruit Industries + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * 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 @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "shared-bindings/alarm/pin/PinAlarm.h" +#include "shared-bindings/alarm/SleepMemory.h" #include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/wifi/__init__.h" @@ -41,8 +42,17 @@ #include "esp_sleep.h" +// Singleton instance of SleepMemory. +const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { + .base = { + .type = &alarm_sleep_memory_type, + }, +}; + + void alarm_reset(void) { alarm_time_timealarm_reset(); + alarm_sleep_memory_reset(); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } diff --git a/ports/esp32s2/common-hal/alarm/__init__.h b/ports/esp32s2/common-hal/alarm/__init__.h index 5678a0e7f..0823ff842 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.h +++ b/ports/esp32s2/common-hal/alarm/__init__.h @@ -27,6 +27,10 @@ #ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM__INIT__H #define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM__INIT__H -void alarm_reset(void); +#include "common-hal/alarm/SleepMemory.h" + +const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; + +extern void alarm_reset(void); #endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_ALARM__INIT__H diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index e9253682e..1eafce259 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -304,6 +304,7 @@ SRC_COMMON_HAL_ALL = \ _bleio/__init__.c \ _pew/PewPew.c \ _pew/__init__.c \ + alarm/SleepMemory.c \ alarm/__init__.c \ alarm/pin/PinAlarm.c \ alarm/time/TimeAlarm.c \ diff --git a/shared-bindings/alarm/SleepMemory.c b/shared-bindings/alarm/SleepMemory.c new file mode 100644 index 000000000..d4a6eb509 --- /dev/null +++ b/shared-bindings/alarm/SleepMemory.c @@ -0,0 +1,180 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * 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/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/runtime0.h" + +#include "shared-bindings/alarm/SleepMemory.h" +#include "supervisor/shared/translate.h" + +//| class SleepMemory: +//| """Store raw bytes in RAM that persists during deep sleep. +//| The class acts as a ``bytearray``. +//| If power is lost, the memory contents are lost. +//| +//| Note that this class can't be imported and used directly. The sole +//| instance of :class:`SleepMemory` is available at +//| :attr:`alarm.sleep_memory`. +//| +//| Usage:: +//| +//| import alarm +//| alarm.sleep_memory[0] = True +//| alarm.sleep_memory[1] = 12 +//| + +//| def __init__(self) -> None: +//| """Not currently dynamically supported. Access the sole instance through `microcontroller.nvm`.""" +//| ... +//| + +//| def __bool__(self) -> bool: +//| """``sleep_memory`` is ``True`` if its length is greater than zero. +//| This is an easy way to check for its existence. +//| """ +//| ... +//| +//| def __len__(self) -> int: +//| """Return the length. This is used by (`len`)""" +//| ... +//| +STATIC mp_obj_t alarm_sleep_memory_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + alarm_sleep_memory_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint16_t len = common_hal_alarm_sleep_memory_get_length(self); + switch (op) { + case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0); + case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len); + default: return MP_OBJ_NULL; // op not supported + } +} + +STATIC const mp_rom_map_elem_t alarm_sleep_memory_locals_dict_table[] = { +}; + +STATIC MP_DEFINE_CONST_DICT(alarm_sleep_memory_locals_dict, alarm_sleep_memory_locals_dict_table); + +//| @overload +//| def __getitem__(self, index: slice) -> bytearray: ... +//| @overload +//| def __getitem__(self, index: int) -> int: +//| """Returns the value at the given index.""" +//| ... +//| +//| @overload +//| def __setitem__(self, index: slice, value: ReadableBuffer) -> None: ... +//| @overload +//| def __setitem__(self, index: int, value: int) -> None: +//| """Set the value at the given index.""" +//| ... +//| +STATIC mp_obj_t alarm_sleep_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { + if (value == MP_OBJ_NULL) { + // delete item + // slice deletion + return MP_OBJ_NULL; // op not supported + } else { + alarm_sleep_memory_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (0) { +#if MICROPY_PY_BUILTINS_SLICE + } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { + mp_bound_slice_t slice; + if (!mp_seq_get_fast_slice_indexes(common_hal_alarm_sleep_memory_get_length(self), index_in, &slice)) { + mp_raise_NotImplementedError(translate("only slices with step=1 (aka None) are supported")); + } + if (value != MP_OBJ_SENTINEL) { + #if MICROPY_PY_ARRAY_SLICE_ASSIGN + // Assign + size_t src_len = slice.stop - slice.start; + uint8_t* src_items; + if (MP_OBJ_IS_TYPE(value, &mp_type_array) || + MP_OBJ_IS_TYPE(value, &mp_type_bytearray) || + MP_OBJ_IS_TYPE(value, &mp_type_memoryview) || + MP_OBJ_IS_TYPE(value, &mp_type_bytes)) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len != src_len) { + mp_raise_ValueError(translate("Slice and value different lengths.")); + } + src_len = bufinfo.len; + src_items = bufinfo.buf; + if (1 != mp_binary_get_size('@', bufinfo.typecode, NULL)) { + mp_raise_ValueError(translate("Array values should be single bytes.")); + } + } else { + mp_raise_NotImplementedError(translate("array/bytes required on right side")); + } + + if (!common_hal_alarm_sleep_memory_set_bytes(self, slice.start, src_items, src_len)) { + mp_raise_RuntimeError(translate("Unable to write to nvm.")); + } + return mp_const_none; + #else + return MP_OBJ_NULL; // op not supported + #endif + } else { + // Read slice. + size_t len = slice.stop - slice.start; + uint8_t *items = m_new(uint8_t, len); + common_hal_alarm_sleep_memory_get_bytes(self, slice.start, len, items); + return mp_obj_new_bytearray_by_ref(len, items); + } +#endif + } else { + // Single index rather than slice. + size_t index = mp_get_index(self->base.type, common_hal_alarm_sleep_memory_get_length(self), + index_in, false); + if (value == MP_OBJ_SENTINEL) { + // load + uint8_t value_out; + common_hal_alarm_sleep_memory_get_bytes(self, index, 1, &value_out); + return MP_OBJ_NEW_SMALL_INT(value_out); + } else { + // store + mp_int_t byte_value = mp_obj_get_int(value); + if (byte_value > 0xff || byte_value < 0) { + mp_raise_ValueError(translate("Bytes must be between 0 and 255.")); + } + uint8_t short_value = byte_value; + if (!common_hal_alarm_sleep_memory_set_bytes(self, index, &short_value, 1)) { + mp_raise_RuntimeError(translate("Unable to write to nvm.")); + } + return mp_const_none; + } + } + } +} + +const mp_obj_type_t alarm_sleep_memory_type = { + { &mp_type_type }, + .name = MP_QSTR_SleepMemory, + .subscr = alarm_sleep_memory_subscr, + .unary_op = alarm_sleep_memory_unary_op, + .print = NULL, + .locals_dict = (mp_obj_t)&alarm_sleep_memory_locals_dict, +}; diff --git a/shared-bindings/alarm/SleepMemory.h b/shared-bindings/alarm/SleepMemory.h new file mode 100644 index 000000000..0015233e0 --- /dev/null +++ b/shared-bindings/alarm/SleepMemory.h @@ -0,0 +1,44 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * 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_SLEEPMEMORY_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_SLEEPMEMORY_H + +#include "common-hal/alarm/SleepMemory.h" + +extern const mp_obj_type_t alarm_sleep_memory_type; + +uint32_t common_hal_alarm_sleep_memory_get_length(alarm_sleep_memory_obj_t *self); + +bool common_hal_alarm_sleep_memory_set_bytes(alarm_sleep_memory_obj_t *self, + uint32_t start_index, uint8_t* values, uint32_t len); +// len and values are intentionally swapped to signify values is an output and +// also leverage the compiler to validate uses are expected. +void common_hal_alarm_sleep_memory_get_bytes(alarm_sleep_memory_obj_t *self, + uint32_t start_index, uint32_t len, uint8_t* values); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_SLEEPMEMORY_H diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 5420b8404..28e34ad6a 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -29,6 +29,7 @@ #include "py/runtime.h" #include "shared-bindings/alarm/__init__.h" +#include "shared-bindings/alarm/SleepMemory.h" #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/supervisor/Runtime.h" @@ -177,6 +178,7 @@ STATIC const mp_obj_module_t alarm_time_module = { .globals = (mp_obj_dict_t*)&alarm_time_globals, }; +// The module table is mutable because .wake_alarm is a mutable attribute. STATIC mp_map_elem_t alarm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) }, @@ -188,8 +190,10 @@ STATIC mp_map_elem_t alarm_module_globals_table[] = { MP_OBJ_FROM_PTR(&alarm_exit_and_deep_sleep_until_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) } + { MP_ROM_QSTR(MP_QSTR_time), MP_OBJ_FROM_PTR(&alarm_time_module) }, + { MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type) }, + { MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) }, }; STATIC MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); -- cgit v1.2.3 From 6abe3cd0ef6c04108b1728797830ebfd1827ecaa Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 14 Dec 2020 18:57:31 -0500 Subject: -Os for SAMD51; fix CSUPEROPT typo --- ports/atmel-samd/Makefile | 6 +++--- py/py.mk | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'py') diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index dc7b4e4c8..c214d56f0 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -94,21 +94,21 @@ endif ifeq ($(CHIP_FAMILY), samd51) PERIPHERALS_CHIP_FAMILY=sam_d5x_e5x -OPTIMIZATION_FLAGS ?= -O2 +OPTIMIZATION_FLAGS ?= -Os # TinyUSB defines CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024 endif ifeq ($(CHIP_FAMILY), same51) PERIPHERALS_CHIP_FAMILY=sam_d5x_e5x -OPTIMIZATION_FLAGS ?= -O2 +OPTIMIZATION_FLAGS ?= -Os # TinyUSB defines CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAME5X -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024 endif ifeq ($(CHIP_FAMILY), same54) PERIPHERALS_CHIP_FAMILY=sam_d5x_e5x -OPTIMIZATION_FLAGS ?= -O2 +OPTIMIZATION_FLAGS ?= -Os # TinyUSB defines CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAME5X -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024 endif diff --git a/py/py.mk b/py/py.mk index 1a8f1219a..3f94aa67a 100644 --- a/py/py.mk +++ b/py/py.mk @@ -19,7 +19,7 @@ endif QSTR_GLOBAL_DEPENDENCIES += $(PY_SRC)/mpconfig.h mpconfigport.h # some code is performance bottleneck and compiled with other optimization options -_CSUPEROPT = -O3 +CSUPEROPT = -O3 # this sets the config file for FatFs CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" -- cgit v1.2.3 From 1ad49d9a18224ecc53d8f49d0675a369274556ce Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 8 Dec 2020 17:13:00 -0800 Subject: Add alarm.pin that wakes on pin level Fixes #3787 --- main.c | 18 +- ports/esp32s2/common-hal/alarm/__init__.c | 47 +++-- ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 260 +++++++++++++++++++++++- ports/esp32s2/common-hal/alarm/pin/PinAlarm.h | 8 +- ports/esp32s2/common-hal/alarm/time/TimeAlarm.c | 25 ++- ports/esp32s2/common-hal/alarm/time/TimeAlarm.h | 2 +- ports/esp32s2/supervisor/esp_port.h | 2 +- ports/esp32s2/supervisor/port.c | 47 +++-- ports/esp32s2/supervisor/usb.c | 7 +- py/obj.c | 6 +- py/vm.c | 2 +- shared-bindings/alarm/pin/PinAlarm.c | 6 +- supervisor/shared/tick.c | 7 +- 13 files changed, 361 insertions(+), 76 deletions(-) (limited to 'py') diff --git a/main.c b/main.c index 378c50657..d940f93d1 100755 --- a/main.c +++ b/main.c @@ -260,10 +260,10 @@ STATIC void print_code_py_status_message(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) { - serial_write("\n"); - print_code_py_status_message(safe_mode); - } + serial_write("\n"); + print_code_py_status_message(safe_mode); + print_safe_mode_message(safe_mode); + serial_write("\n"); #endif pyexec_result_t result; @@ -307,16 +307,14 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { if (result.return_code & PYEXEC_FORCED_EXIT) { return reload_requested; } - } - - // Program has finished running. - // Display a different completion message if the user has no USB attached (cannot save files) - if (!serial_connected_at_start) { + // Display a different completion message if the user has no USB attached (cannot save files) serial_write_compressed(translate("\nCode done running. Waiting for reload.\n")); } - bool serial_connected_before_animation = false; + // Program has finished running. + + bool serial_connected_before_animation = serial_connected(); #if CIRCUITPY_DISPLAYIO bool refreshed_epaper_display = false; #endif diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index fae921db0..5d1f3e95d 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -42,6 +42,9 @@ #include "esp_sleep.h" +#include "components/soc/soc/esp32s2/include/soc/rtc_cntl_reg.h" +#include "components/driver/include/driver/uart.h" + // Singleton instance of SleepMemory. const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { .base = { @@ -49,9 +52,9 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { }, }; - void alarm_reset(void) { alarm_time_timealarm_reset(); + alarm_pin_pin_alarm_reset(); alarm_sleep_memory_reset(); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } @@ -60,6 +63,9 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { if (alarm_time_timealarm_woke_us_up()) { return ESP_SLEEP_WAKEUP_TIMER; } + if (alarm_pin_pin_alarm_woke_us_up()) { + return ESP_SLEEP_WAKEUP_GPIO; + } return esp_sleep_get_wakeup_cause(); } @@ -69,14 +75,16 @@ bool alarm_woken_from_sleep(void) { } STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { - switch (_get_wakeup_cause()) { + esp_sleep_wakeup_cause_t cause = _get_wakeup_cause(); + switch (cause) { case ESP_SLEEP_WAKEUP_TIMER: { return alarm_time_timealarm_get_wakeup_alarm(n_alarms, alarms); } - case ESP_SLEEP_WAKEUP_EXT0: { - // TODO: implement pin alarm wake. - break; + case ESP_SLEEP_WAKEUP_GPIO: + case ESP_SLEEP_WAKEUP_EXT0: + case ESP_SLEEP_WAKEUP_EXT1: { + return alarm_pin_pin_alarm_get_wakeup_alarm(n_alarms, alarms); } case ESP_SLEEP_WAKEUP_TOUCHPAD: @@ -98,24 +106,8 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) { // Set up light sleep or deep sleep alarms. STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { - bool time_alarm_set = false; - alarm_time_time_alarm_obj_t *time_alarm = MP_OBJ_NULL; - - 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 not yet implemented")); - } else if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_time_alarm_type)) { - if (time_alarm_set) { - mp_raise_ValueError(translate("Only one alarm.time alarm can be set.")); - } - time_alarm = MP_OBJ_TO_PTR(alarms[i]); - time_alarm_set = true; - } - } - - if (time_alarm_set) { - alarm_time_timealarm_set_alarm(time_alarm); - } + alarm_pin_pin_alarm_set_alarms(deep_sleep, n_alarms, alarms); + alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms); } STATIC void _idle_until_alarm(void) { @@ -134,7 +126,10 @@ STATIC void _idle_until_alarm(void) { // Is it safe to do a light sleep? Check whether WiFi is on or there are // other ongoing tasks that should not be shut down. STATIC bool _light_sleep_ok(void) { - return !common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) && !supervisor_workflow_active(); + int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL); + return !common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) && + !supervisor_workflow_active() && + connecting_delay_ticks <= 0; } mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { @@ -142,10 +137,13 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj // Light sleep can break some functionality so only do it when possible. Otherwise we idle. if (_light_sleep_ok()) { + // Flush the UART to complete the log line. + uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); esp_light_sleep_start(); } else { _idle_until_alarm(); } + mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); alarm_reset(); return wake_alarm; @@ -156,6 +154,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala } void NORETURN alarm_enter_deep_sleep(void) { + alarm_pin_pin_alarm_prepare_for_deep_sleep(); // The ESP-IDF caches the deep sleep settings and applies them before sleep. // We don't need to worry about resetting them in the interim. esp_deep_sleep_start(); diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index 582a66572..179f34da7 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2020 Dan Halbert for Adafruit Industries + * 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 @@ -24,15 +25,29 @@ * THE SOFTWARE. */ -#include "esp_sleep.h" +#include "py/runtime.h" #include "shared-bindings/alarm/pin/PinAlarm.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" +#include "supervisor/esp_port.h" + +#include "components/driver/include/driver/rtc_io.h" +#include "components/esp_system/include/esp_sleep.h" +#include "components/freertos/include/freertos/FreeRTOS.h" +#include "components/hal/esp32s2/include/hal/gpio_ll.h" +#include "components/xtensa/include/esp_debug_helpers.h" void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { + if (edge) { + mp_raise_ValueError(translate("Cannot wake on pin edge. Only level.")); + } + + if (pull && !GPIO_IS_VALID_OUTPUT_GPIO(pin->number)) { + mp_raise_ValueError(translate("Cannot pull on input-only pin.")); + } self->pin = pin; self->value = value; - self->edge = edge; self->pull = pull; } @@ -45,9 +60,248 @@ bool common_hal_alarm_pin_pin_alarm_get_value(alarm_pin_pin_alarm_obj_t *self) { } bool common_hal_alarm_pin_pin_alarm_get_edge(alarm_pin_pin_alarm_obj_t *self) { - return self->edge; + return false; } bool common_hal_alarm_pin_pin_alarm_get_pull(alarm_pin_pin_alarm_obj_t *self) { return self->pull; } + +gpio_isr_handle_t gpio_interrupt_handle; +// Low and high are relative to pin number. 32+ is high. <32 is low. +static volatile uint32_t low_pin_status = 0; +static volatile uint32_t high_pin_status = 0; +void gpio_interrupt(void *arg) { + (void) arg; + + gpio_ll_get_intr_status(&GPIO, xPortGetCoreID(), (uint32_t*) &low_pin_status); + gpio_ll_clear_intr_status(&GPIO, low_pin_status); + gpio_ll_get_intr_status_high(&GPIO, xPortGetCoreID(), (uint32_t*) &high_pin_status); + gpio_ll_clear_intr_status_high(&GPIO, high_pin_status); + + // disable the interrupts that fired, maybe all of them + for (size_t i = 0; i < 32; i++) { + uint32_t mask = 1 << i; + if ((low_pin_status & mask) != 0) { + gpio_ll_intr_disable(&GPIO, i); + } + if ((high_pin_status & mask) != 0) { + gpio_ll_intr_disable(&GPIO, 32 + i); + } + } + BaseType_t high_task_wakeup; + vTaskNotifyGiveFromISR(circuitpython_task, &high_task_wakeup); + if (high_task_wakeup) { + portYIELD_FROM_ISR(); + } +} + +bool alarm_pin_pin_alarm_woke_us_up(void) { + return low_pin_status != 0 || high_pin_status != 0; +} + +mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { + // First, check to see if we match any given alarms. + uint64_t pin_status = ((uint64_t) high_pin_status) << 32 | low_pin_status; + for (size_t i = 0; i < n_alarms; i++) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) { + continue; + } + alarm_pin_pin_alarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + if ((pin_status & (1ull << alarm->pin->number)) != 0) { + return alarms[i]; + } + } + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + size_t pin_number = 64; + if (cause == ESP_SLEEP_WAKEUP_EXT0) { + pin_number = REG_GET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL); + } else { + if (cause == ESP_SLEEP_WAKEUP_EXT1) { + pin_status = esp_sleep_get_ext1_wakeup_status(); + } + // If the cause is GPIO, we've already snagged pin_status in the interrupt. + // We'll only get here if we pretended to deep sleep. Light sleep will + // pass in existing objects. + for (size_t i = 0; i < 64; i++) { + if ((pin_status & (1ull << i)) != 0) { + pin_number = i; + break; + } + } + } + + alarm_pin_pin_alarm_obj_t *alarm = m_new_obj(alarm_pin_pin_alarm_obj_t); + alarm->base.type = &alarm_pin_pin_alarm_type; + alarm->pin = NULL; + // Map the pin number back to a pin object. + for (size_t i = 0; i < mcu_pin_globals.map.used; i++) { + const mcu_pin_obj_t* pin_obj = MP_OBJ_TO_PTR(mcu_pin_globals.map.table[i].value); + if ((size_t) pin_obj->number == pin_number) { + alarm->pin = mcu_pin_globals.map.table[i].value; + break; + } + } + return alarm; +} + +// These must be static because we need to configure pulls later, right before +// deep sleep. +static uint64_t high_alarms = 0; +static uint64_t low_alarms = 0; +static uint64_t pull_pins = 0; + +void alarm_pin_pin_alarm_reset(void) { + if (gpio_interrupt_handle != NULL) { + esp_intr_free(gpio_interrupt_handle); + gpio_interrupt_handle = NULL; + } + for (size_t i = 0; i < 64; i++) { + uint64_t mask = 1ull << i; + bool high = (high_alarms & mask) != 0; + bool low = (low_alarms & mask) != 0; + if (!(high || low)) { + continue; + } + reset_pin_number(i); + } + high_alarms = 0; + low_alarms = 0; + pull_pins = 0; + high_pin_status = 0; + low_pin_status = 0; +} + +void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { + // Bitmask of wake up settings. + size_t high_count = 0; + size_t low_count = 0; + + for (size_t i = 0; i < n_alarms; i++) { + // TODO: Check for ULP or touch alarms because they can't coexist with GPIO alarms. + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) { + continue; + } + alarm_pin_pin_alarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + + gpio_num_t pin_number = alarm->pin->number; + if (alarm->value) { + high_alarms |= 1ull << pin_number; + high_count++; + } else { + low_alarms |= 1ull << pin_number; + low_count++; + } + if (alarm->pull) { + pull_pins |= 1ull << pin_number; + } + } + if (high_count == 0 && low_count == 0) { + return; + } + if (deep_sleep && low_count > 2 && high_count == 0) { + mp_raise_ValueError(translate("Can only alarm on two low pins from deep sleep.")); + } + if (deep_sleep && low_count > 1 && high_count > 0) { + mp_raise_ValueError(translate("Can only alarm on one low pin while others alarm high from deep sleep.")); + } + // Only use ext0 and ext1 during deep sleep. + if (deep_sleep) { + if (high_count > 0) { + if (esp_sleep_enable_ext1_wakeup(high_alarms, ESP_EXT1_WAKEUP_ANY_HIGH) != ESP_OK) { + mp_raise_ValueError(translate("Can only alarm on RTC IO from deep sleep.")); + } + } + size_t low_pins[2]; + size_t j = 0; + for (size_t i = 0; i < 64; i++) { + uint64_t mask = 1ull << i; + if ((low_alarms & mask) != 0) { + low_pins[j++] = i; + } + if (j == 2) { + break; + } + } + if (low_count > 1) { + if (esp_sleep_enable_ext1_wakeup(1ull << low_pins[1], ESP_EXT1_WAKEUP_ALL_LOW) != ESP_OK) { + mp_raise_ValueError(translate("Can only alarm on RTC IO from deep sleep.")); + } + } + if (low_count > 0) { + if (esp_sleep_enable_ext0_wakeup(low_pins[0], 0) != ESP_OK) { + mp_raise_ValueError(translate("Can only alarm on RTC IO from deep sleep.")); + } + } + } else { + // Enable GPIO wake up if we're sleeping. + esp_sleep_enable_gpio_wakeup(); + } + // Set GPIO interrupts so they wake us from light sleep or from idle via the + // interrupt handler above. + low_pin_status = 0; + high_pin_status = 0; + if (gpio_isr_register(gpio_interrupt, NULL, 0, &gpio_interrupt_handle) != ESP_OK) { + mp_raise_ValueError(translate("Can only alarm on RTC IO from deep sleep.")); + } + for (size_t i = 0; i < 64; i++) { + uint64_t mask = 1ull << i; + bool high = (high_alarms & mask) != 0; + bool low = (low_alarms & mask) != 0; + bool pull = (pull_pins & mask) != 0; + if (!(high || low)) { + continue; + } + if (rtc_gpio_is_valid_gpio(i)) { + rtc_gpio_deinit(i); + } + gpio_int_type_t interrupt_mode = GPIO_INTR_DISABLE; + gpio_pull_mode_t pull_mode = GPIO_FLOATING; + if (high) { + interrupt_mode = GPIO_INTR_HIGH_LEVEL; + pull_mode = GPIO_PULLDOWN_ONLY; + } + if (low) { + interrupt_mode = GPIO_INTR_LOW_LEVEL; + pull_mode = GPIO_PULLUP_ONLY; + } + gpio_set_direction(i, GPIO_MODE_DEF_INPUT); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[i], PIN_FUNC_GPIO); + if (pull) { + gpio_set_pull_mode(i, pull_mode); + size_t j = 0; + while (gpio_get_level(i) == false) { + j++; + } + } + never_reset_pin_number(i); + // Sets interrupt type and wakeup bits. + gpio_wakeup_enable(i, interrupt_mode); + gpio_intr_enable(i); + } +} + + +void alarm_pin_pin_alarm_prepare_for_deep_sleep(void) { + if (pull_pins == 0) { + return; + } + for (size_t i = 0; i < 64; i++) { + uint64_t mask = 1ull << i; + bool pull = (pull_pins & mask) != 0; + if (!pull) { + continue; + } + bool high = (high_alarms & mask) != 0; + bool low = (low_alarms & mask) != 0; + // The pull direction is opposite from alarm value. + if (high) { + rtc_gpio_pullup_dis(i); + rtc_gpio_pulldown_en(i); + } + if (low) { + rtc_gpio_pullup_en(i); + rtc_gpio_pulldown_dis(i); + } + } +} diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h index 0eaa7777f..8b14931ca 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h @@ -31,7 +31,11 @@ typedef struct { mp_obj_base_t base; mcu_pin_obj_t *pin; bool value; - bool all_same_value; - bool edge; bool pull; } alarm_pin_pin_alarm_obj_t; + +void alarm_pin_pin_alarm_reset(void); +void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); +void alarm_pin_pin_alarm_prepare_for_deep_sleep(void); +mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms); +bool alarm_pin_pin_alarm_woke_us_up(void); diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c index 4d0bba238..a7abde6a4 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c @@ -63,9 +63,7 @@ STATIC bool woke_up = false; void timer_callback(void *arg) { (void) arg; woke_up = true; - if (sleeping_circuitpython_task) { - xTaskNotifyGive(sleeping_circuitpython_task); - } + xTaskNotifyGive(circuitpython_task); } bool alarm_time_timealarm_woke_us_up(void) { @@ -79,7 +77,24 @@ void alarm_time_timealarm_reset(void) { woke_up = false; } -void alarm_time_timealarm_set_alarm(alarm_time_time_alarm_obj_t *self) { +void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { + bool time_alarm_set = false; + alarm_time_time_alarm_obj_t *time_alarm = MP_OBJ_NULL; + + for (size_t i = 0; i < n_alarms; i++) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_time_alarm_type)) { + continue; + } + if (time_alarm_set) { + mp_raise_ValueError(translate("Only one alarm.time alarm can be set.")); + } + time_alarm = MP_OBJ_TO_PTR(alarms[i]); + time_alarm_set = true; + } + if (!time_alarm_set) { + return; + } + if (pretend_sleep_timer != NULL) { esp_timer_stop(pretend_sleep_timer); } else { @@ -94,7 +109,7 @@ void alarm_time_timealarm_set_alarm(alarm_time_time_alarm_obj_t *self) { // Compute how long to actually sleep, considering the time now. mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f; - mp_float_t wakeup_in_secs = MAX(0.0f, self->monotonic_time - now_secs); + mp_float_t wakeup_in_secs = MAX(0.0f, time_alarm->monotonic_time - now_secs); const uint64_t sleep_for_us = (uint64_t) (wakeup_in_secs * 1000000); esp_sleep_enable_timer_wakeup(sleep_for_us); diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h index 04c553009..277ababc2 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h @@ -36,5 +36,5 @@ typedef struct { mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms); // Check for the wake up alarm from pretend deep sleep. bool alarm_time_timealarm_woke_us_up(void); -void alarm_time_timealarm_set_alarm(alarm_time_time_alarm_obj_t *self); +void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); void alarm_time_timealarm_reset(void); diff --git a/ports/esp32s2/supervisor/esp_port.h b/ports/esp32s2/supervisor/esp_port.h index 1164666cd..8b9e13829 100644 --- a/ports/esp32s2/supervisor/esp_port.h +++ b/ports/esp32s2/supervisor/esp_port.h @@ -30,6 +30,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" -extern TaskHandle_t sleeping_circuitpython_task; +extern TaskHandle_t circuitpython_task; #endif // MICROPY_INCLUDED_ESP32S2_SUPERVISOR_PORT_H diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index 7037b4f05..7d8aac4d5 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -66,6 +66,9 @@ uint32_t* heap; uint32_t heap_size; STATIC esp_timer_handle_t _tick_timer; +STATIC esp_timer_handle_t _sleep_timer; + +TaskHandle_t circuitpython_task = NULL; extern void esp_restart(void) NORETURN; @@ -73,6 +76,8 @@ void tick_timer_cb(void* arg) { supervisor_tick(); } +void sleep_timer_cb(void* arg); + safe_mode_t port_init(void) { esp_timer_create_args_t args; args.callback = &tick_timer_cb; @@ -81,10 +86,14 @@ safe_mode_t port_init(void) { args.name = "CircuitPython Tick"; esp_timer_create(&args, &_tick_timer); - #ifdef DEBUG + args.callback = &sleep_timer_cb; + args.arg = NULL; + args.dispatch_method = ESP_TIMER_TASK; + args.name = "CircuitPython Sleep"; + esp_timer_create(&args, &_sleep_timer); + // Send the ROM output out of the UART. This includes early logs. esp_rom_install_channel_putc(1, esp_rom_uart_putc); - #endif heap = NULL; never_reset_module_internal_pins(); @@ -106,10 +115,14 @@ safe_mode_t port_init(void) { if (reason == ESP_RST_BROWNOUT) { return BROWNOUT; } - if (reason == ESP_RST_PANIC) { + if (reason == ESP_RST_PANIC || + reason == ESP_RST_INT_WDT || + reason == ESP_RST_WDT) { return HARD_CRASH; } + circuitpython_task = xTaskGetCurrentTaskHandle(); + return NO_SAFE_MODE; } @@ -250,29 +263,25 @@ void port_disable_tick(void) { // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB. // Tick disable can happen via auto-reload so poke the main task here. - if (sleeping_circuitpython_task != NULL) { - xTaskNotifyGive(sleeping_circuitpython_task); - } + xTaskNotifyGive(circuitpython_task); } -TickType_t sleep_time_duration; +void sleep_timer_cb(void* arg) { + xTaskNotifyGive(circuitpython_task); +} void port_interrupt_after_ticks(uint32_t ticks) { - sleep_time_duration = (ticks * 100)/1024; + uint64_t timeout_us = ticks * 1000000ull / 1024; + if (esp_timer_start_once(_sleep_timer, timeout_us) != ESP_OK) { + esp_timer_stop(_sleep_timer); + esp_timer_start_once(_sleep_timer, timeout_us); + } } +// On the ESP we use FreeRTOS notifications instead of interrupts so this is a +// bit of a misnomer. void port_idle_until_interrupt(void) { - uint32_t notify_value = 0; - - if (sleep_time_duration == 0) { - return; - } - sleeping_circuitpython_task = xTaskGetCurrentTaskHandle(); - xTaskNotifyWait(0x01, 0x01, ¬ify_value, sleep_time_duration ); - sleeping_circuitpython_task = NULL; - if (notify_value == 1) { - mp_handle_pending(); - } + xTaskNotifyWait(0x01, 0x01, NULL, portMAX_DELAY); } // Wrap main in app_main that the IDF expects. diff --git a/ports/esp32s2/supervisor/usb.c b/ports/esp32s2/supervisor/usb.c index 2bfcdfb12..6c92f7253 100644 --- a/ports/esp32s2/supervisor/usb.c +++ b/ports/esp32s2/supervisor/usb.c @@ -26,6 +26,7 @@ */ #include "supervisor/usb.h" +#include "supervisor/esp_port.h" #include "lib/utils/interrupt_char.h" #include "lib/mp-readline/readline.h" @@ -52,8 +53,6 @@ StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; -TaskHandle_t sleeping_circuitpython_task = NULL; - // USB Device Driver task // This top level thread process all usb events and invoke callbacks void usb_device_task(void* param) @@ -131,8 +130,6 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) mp_keyboard_interrupt(); // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB. // So, we must notify the other task when a CTRL-C is received. - if (sleeping_circuitpython_task != NULL) { - xTaskNotifyGive(sleeping_circuitpython_task); - } + xTaskNotifyGive(circuitpython_task); } } diff --git a/py/obj.c b/py/obj.c index b6462641c..218fb4321 100644 --- a/py/obj.c +++ b/py/obj.c @@ -29,6 +29,7 @@ #include #include +#include "lib/utils/interrupt_char.h" #include "py/obj.h" #include "py/objtype.h" #include "py/objint.h" @@ -67,7 +68,10 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t #ifdef RUN_BACKGROUND_TASKS RUN_BACKGROUND_TASKS; #endif - mp_handle_pending(); + // Stop printing if we've been interrupted. + if (mp_hal_is_interrupted()) { + return; + } #ifndef NDEBUG if (o_in == MP_OBJ_NULL) { diff --git a/py/vm.c b/py/vm.c index 9b3354b09..13a9980aa 100644 --- a/py/vm.c +++ b/py/vm.c @@ -1015,7 +1015,7 @@ unwind_jump:; } #endif SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp)); - DISPATCH(); + DISPATCH_WITH_PEND_EXC_CHECK(); } ENTRY(MP_BC_CALL_METHOD_VAR_KW): { diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index 7a5617142..83ccc0d76 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -89,7 +89,11 @@ STATIC mp_obj_t alarm_pin_pin_alarm_make_new(const mp_obj_type_t *type, mp_uint_ //| STATIC mp_obj_t alarm_pin_pin_alarm_obj_get_pin(mp_obj_t self_in) { alarm_pin_pin_alarm_obj_t *self = MP_OBJ_TO_PTR(self_in); - return common_hal_alarm_pin_pin_alarm_get_pin(self); + mcu_pin_obj_t* pin = common_hal_alarm_pin_pin_alarm_get_pin(self); + if (pin == NULL) { + return mp_const_none; + } + return MP_OBJ_FROM_PTR(pin); } MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pin_alarm_get_pin_obj, alarm_pin_pin_alarm_obj_get_pin); diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index d37a585eb..5d75a5395 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -145,10 +145,11 @@ void mp_hal_delay_ms(mp_uint_t delay) { delay = delay * 1024 / 1000; uint64_t end_tick = start_tick + delay; int64_t remaining = delay; - while (remaining > 0) { + + // Loop until we've waited long enough or we've been CTRL-Ced by autoreload + // or the user. + while (remaining > 0 && !mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; - // Check to see if we've been CTRL-Ced by autoreload or the user. - mp_handle_pending(); remaining = end_tick - port_get_raw_ticks(NULL); // We break a bit early so we don't risk setting the alarm before the time when we call // sleep. -- cgit v1.2.3 From 4863413bc9aa3104f2c983efa43bf3afa028b80b Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Fri, 18 Dec 2020 00:34:56 +0530 Subject: rename ota to dualbank --- locale/circuitpython.pot | 20 ++-- ports/esp32s2/common-hal/dualbank/__init__.c | 139 +++++++++++++++++++++++++ ports/esp32s2/common-hal/dualbank/__init__.h | 32 ++++++ ports/esp32s2/common-hal/ota/__init__.c | 150 --------------------------- ports/esp32s2/common-hal/ota/__init__.h | 32 ------ ports/esp32s2/mpconfigport.mk | 2 +- ports/esp32s2/supervisor/port.c | 6 +- py/circuitpy_defns.mk | 6 +- py/circuitpy_mpconfig.h | 10 +- py/circuitpy_mpconfig.mk | 4 +- shared-bindings/dualbank/__init__.c | 115 ++++++++++++++++++++ shared-bindings/dualbank/__init__.h | 35 +++++++ shared-bindings/ota/__init__.c | 127 ----------------------- shared-bindings/ota/__init__.h | 36 ------- 14 files changed, 345 insertions(+), 369 deletions(-) create mode 100644 ports/esp32s2/common-hal/dualbank/__init__.c create mode 100644 ports/esp32s2/common-hal/dualbank/__init__.h delete mode 100644 ports/esp32s2/common-hal/ota/__init__.c delete mode 100644 ports/esp32s2/common-hal/ota/__init__.h create mode 100644 shared-bindings/dualbank/__init__.c create mode 100644 shared-bindings/dualbank/__init__.h delete mode 100644 shared-bindings/ota/__init__.c delete mode 100644 shared-bindings/ota/__init__.h (limited to 'py') diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 6ee4d816a..d7f95091c 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-12-10 16:56+0530\n" +"POT-Creation-Date: 2020-12-17 19:42+0530\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -936,6 +936,10 @@ msgstr "" msgid "Filters too complex" msgstr "" +#: ports/esp32s2/common-hal/dualbank/__init__.c +msgid "Firmware image is invalid" +msgstr "" + #: ports/cxd56/common-hal/camera/Camera.c msgid "Format not supported" msgstr "" @@ -1420,10 +1424,6 @@ msgstr "" msgid "Not settable" msgstr "" -#: ports/esp32s2/common-hal/ota/__init__.c -msgid "OTA Update Failed" -msgstr "" - #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." @@ -1911,10 +1911,6 @@ msgstr "" msgid "Unable to read color palette data" msgstr "" -#: ports/esp32s2/common-hal/ota/__init__.c -msgid "Unable to switch boot partition" -msgstr "" - #: shared-bindings/nvm/ByteArray.c msgid "Unable to write to nvm." msgstr "" @@ -1983,6 +1979,10 @@ msgstr "" msgid "Unsupported pull value." msgstr "" +#: ports/esp32s2/common-hal/dualbank/__init__.c +msgid "Update Failed" +msgstr "" + #: ports/nrf/common-hal/_bleio/Characteristic.c #: ports/nrf/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" @@ -3210,7 +3210,7 @@ msgstr "" msgid "offset is too large" msgstr "" -#: shared-bindings/ota/__init__.c +#: shared-bindings/dualbank/__init__.c msgid "offset must be >= 0" msgstr "" diff --git a/ports/esp32s2/common-hal/dualbank/__init__.c b/ports/esp32s2/common-hal/dualbank/__init__.c new file mode 100644 index 000000000..0f468a036 --- /dev/null +++ b/ports/esp32s2/common-hal/dualbank/__init__.c @@ -0,0 +1,139 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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 "common-hal/dualbank/__init__.h" +#include "shared-bindings/dualbank/__init__.h" + +#include + +#include "esp_log.h" +#include "esp_ota_ops.h" + +static const esp_partition_t *update_partition = NULL; +static esp_ota_handle_t update_handle = 0; + +static const char *TAG = "dualbank"; + +void dualbank_reset(void) { + // should use `abort` instead of `end` + // but not in idf v4.2 + // esp_ota_abort(update_handle); + if (esp_ota_end(update_handle) == ESP_OK) { + update_handle = 0; + update_partition = NULL; + } +} + +static void __attribute__((noreturn)) task_fatal_error(void) { + ESP_LOGE(TAG, "Exiting task due to fatal error..."); + mp_raise_RuntimeError(translate("Update Failed")); +} + +void common_hal_dualbank_flash(const void *buf, const size_t len, const size_t offset) { + esp_err_t err; + + const esp_partition_t *running = esp_ota_get_running_partition(); + const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition(); + + if (update_partition == NULL) { + update_partition = esp_ota_get_next_update_partition(NULL); + + ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", + running->type, running->subtype, running->address); + + ESP_LOGI(TAG, "Writing partition type %d subtype %d (offset 0x%08x)\n", + update_partition->type, update_partition->subtype, update_partition->address); + + assert(update_partition != NULL); + } + + if (update_handle == 0) { + if (len > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { + esp_app_desc_t new_app_info; + memcpy(&new_app_info, &((char *)buf)[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); + ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); + + esp_app_desc_t running_app_info; + if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) { + ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version); + } + + esp_app_desc_t invalid_app_info; + if (esp_ota_get_partition_description(last_invalid, &invalid_app_info) == ESP_OK) { + ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); + } + + // check new version with running version + if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { + ESP_LOGW(TAG, "New version is the same as running version."); + task_fatal_error(); + } + + // check new version with last invalid partition + if (last_invalid != NULL) { + if (memcmp(new_app_info.version, invalid_app_info.version, sizeof(new_app_info.version)) == 0) { + ESP_LOGW(TAG, "New version is the same as invalid version."); + task_fatal_error(); + } + } + + err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); + task_fatal_error(); + } + } else { + ESP_LOGE(TAG, "received package is not fit len"); + task_fatal_error(); + } + } + + if (offset == 0) { + err = esp_ota_write(update_handle, buf, len); + } else { + err = esp_ota_write_with_offset(update_handle, buf, len, offset); + } + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ota_write failed (%s)", esp_err_to_name(err)); + task_fatal_error(); + } +} + +void common_hal_dualbank_switch(void) { + if (esp_ota_end(update_handle) == ESP_OK) { + update_handle = 0; + update_partition = NULL; + } + esp_err_t err = esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL)); + if (err != ESP_OK) { + if (err == ESP_ERR_OTA_VALIDATE_FAILED) { + ESP_LOGE(TAG, "Image validation failed, image is corrupted"); + mp_raise_RuntimeError(translate("Firmware image is invalid")); + } + ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); + task_fatal_error(); + } +} diff --git a/ports/esp32s2/common-hal/dualbank/__init__.h b/ports/esp32s2/common-hal/dualbank/__init__.h new file mode 100644 index 000000000..8b18336c9 --- /dev/null +++ b/ports/esp32s2/common-hal/dualbank/__init__.h @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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_ESP32S2_COMMON_HAL_DUALBANK___INIT___H +#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DUALBANK___INIT___H + +extern void dualbank_reset(void); + +#endif //MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DUALBANK___INIT___H diff --git a/ports/esp32s2/common-hal/ota/__init__.c b/ports/esp32s2/common-hal/ota/__init__.c deleted file mode 100644 index 5ea25fb5d..000000000 --- a/ports/esp32s2/common-hal/ota/__init__.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 microDev - * - * 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 "common-hal/ota/__init__.h" -#include "shared-bindings/ota/__init__.h" - -#include - -#include "esp_log.h" -#include "esp_ota_ops.h" - -static const esp_partition_t *update_partition = NULL; -static esp_ota_handle_t update_handle = 0; - -static bool ota_inited = false; -static const char *TAG = "OTA"; - -void ota_reset(void) { - update_handle = 0; - update_partition = NULL; - ota_inited = false; -} - -static void __attribute__((noreturn)) task_fatal_error(void) { - ESP_LOGE(TAG, "Exiting task due to fatal error..."); - mp_raise_RuntimeError(translate("OTA Update Failed")); -} - -void common_hal_ota_flash(const void *buf, const size_t len, const int32_t offset) { - esp_err_t err; - - const esp_partition_t *running = esp_ota_get_running_partition(); - const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition(); - - if (update_partition == NULL) { - update_partition = esp_ota_get_next_update_partition(NULL); - - ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", - running->type, running->subtype, running->address); - - ESP_LOGI(TAG, "Writing partition type %d subtype %d (offset 0x%08x)\n", - update_partition->type, update_partition->subtype, update_partition->address); - - assert(update_partition != NULL); - } - - if (!ota_inited) { - if (len > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { - esp_app_desc_t new_app_info; - memcpy(&new_app_info, &((char *)buf)[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); - ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); - - esp_app_desc_t running_app_info; - if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) { - ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version); - } - - esp_app_desc_t invalid_app_info; - if (esp_ota_get_partition_description(last_invalid, &invalid_app_info) == ESP_OK) { - ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); - } - - // check new version with running version - if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { - ESP_LOGW(TAG, "New version is the same as running version."); - task_fatal_error(); - } - - // check new version with last invalid partition - if (last_invalid != NULL) { - if (memcmp(new_app_info.version, invalid_app_info.version, sizeof(new_app_info.version)) == 0) { - ESP_LOGW(TAG, "New version is the same as invalid version."); - task_fatal_error(); - } - } - - err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); - task_fatal_error(); - } - ota_inited = true; - } else { - ESP_LOGE(TAG, "received package is not fit len"); - task_fatal_error(); - } - } - - if (offset == -1) { - err = esp_ota_write(update_handle, buf, len); - } else { - err = esp_ota_write_with_offset(update_handle, buf, len, offset); - } - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_write failed (%s)", esp_err_to_name(err)); - task_fatal_error(); - } -} - -void common_hal_ota_finish(void) { - if (ota_inited) { - esp_err_t err; - - err = esp_ota_end(update_handle); - if (err != ESP_OK) { - if (err == ESP_ERR_OTA_VALIDATE_FAILED) { - ESP_LOGE(TAG, "Image validation failed, image is corrupted"); - } - ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err)); - task_fatal_error(); - } - - err = esp_ota_set_boot_partition(update_partition); - if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); - task_fatal_error(); - } - - ota_reset(); - } -} - -void common_hal_ota_switch(void) { - if (esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL)) != ESP_OK) { - mp_raise_RuntimeError(translate("Unable to switch boot partition")); - } -} diff --git a/ports/esp32s2/common-hal/ota/__init__.h b/ports/esp32s2/common-hal/ota/__init__.h deleted file mode 100644 index 983b57e3f..000000000 --- a/ports/esp32s2/common-hal/ota/__init__.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 microDev - * - * 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_ESP32S2_COMMON_HAL_OTA___INIT___H -#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_OTA___INIT___H - -extern void ota_reset(void); - -#endif //MICROPY_INCLUDED_ESP32S2_COMMON_HAL_OTA___INIT___H diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index da231107f..2ad8afb51 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -19,11 +19,11 @@ CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_AUDIOIO = 0 CIRCUITPY_CANIO = 1 CIRCUITPY_COUNTIO = 1 +CIRCUITPY_DUALBANK = 1 CIRCUITPY_FREQUENCYIO = 1 CIRCUITPY_I2CPERIPHERAL = 0 CIRCUITPY_ROTARYIO = 1 CIRCUITPY_NVM = 1 -CIRCUITPY_OTA = 1 # We don't have enough endpoints to include MIDI. CIRCUITPY_USB_MIDI = 0 CIRCUITPY_WIFI = 1 diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index 201d9962e..a56ac61c8 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -41,7 +41,7 @@ #include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" #include "common-hal/busio/UART.h" -#include "common-hal/ota/__init__.h" +#include "common-hal/dualbank/__init__.h" #include "common-hal/ps2io/Ps2.h" #include "common-hal/pulseio/PulseIn.h" #include "common-hal/pwmio/PWMOut.h" @@ -124,8 +124,8 @@ void reset_port(void) { analogout_reset(); #endif -#if CIRCUITPY_OTA - ota_reset(); +#if CIRCUITPY_DUALBANK + dualbank_reset(); #endif #if CIRCUITPY_PS2IO diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 68e806d4b..a87147914 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -205,8 +205,8 @@ endif ifeq ($(CIRCUITPY_OS),1) SRC_PATTERNS += os/% endif -ifeq ($(CIRCUITPY_OTA),1) -SRC_PATTERNS += ota/% +ifeq ($(CIRCUITPY_DUALBANK),1) +SRC_PATTERNS += dualbank/% endif ifeq ($(CIRCUITPY_PIXELBUF),1) SRC_PATTERNS += _pixelbuf/% @@ -350,7 +350,7 @@ SRC_COMMON_HAL_ALL = \ nvm/ByteArray.c \ nvm/__init__.c \ os/__init__.c \ - ota/__init__.c \ + dualbank/__init__.c \ ps2io/Ps2.c \ ps2io/__init__.c \ pulseio/PulseIn.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 6a0daa7e9..08c92a77e 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -539,11 +539,11 @@ extern const struct _mp_obj_module_t os_module; #define OS_MODULE_ALT_NAME #endif -#if CIRCUITPY_OTA -extern const struct _mp_obj_module_t ota_module; -#define OTA_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_ota), (mp_obj_t)&ota_module }, +#if CIRCUITPY_DUALBANK +extern const struct _mp_obj_module_t dualbank_module; +#define DUALBANK_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_dualbank), (mp_obj_t)&dualbank_module }, #else -#define OTA_MODULE +#define DUALBANK_MODULE #endif #if CIRCUITPY_PEW @@ -834,7 +834,7 @@ extern const struct _mp_obj_module_t wifi_module; NETWORK_MODULE \ SOCKET_MODULE \ WIZNET_MODULE \ - OTA_MODULE \ + DUALBANK_MODULE \ PEW_MODULE \ PIXELBUF_MODULE \ PS2IO_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 09074bf53..af1dccf02 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -179,8 +179,8 @@ CFLAGS += -DCIRCUITPY_NVM=$(CIRCUITPY_NVM) CIRCUITPY_OS ?= 1 CFLAGS += -DCIRCUITPY_OS=$(CIRCUITPY_OS) -CIRCUITPY_OTA ?= 0 -CFLAGS += -DCIRCUITPY_OTA=$(CIRCUITPY_OTA) +CIRCUITPY_DUALBANK ?= 0 +CFLAGS += -DCIRCUITPY_DUALBANK=$(CIRCUITPY_DUALBANK) CIRCUITPY_PIXELBUF ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_PIXELBUF=$(CIRCUITPY_PIXELBUF) diff --git a/shared-bindings/dualbank/__init__.c b/shared-bindings/dualbank/__init__.c new file mode 100644 index 000000000..8021ab18b --- /dev/null +++ b/shared-bindings/dualbank/__init__.c @@ -0,0 +1,115 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/dualbank/__init__.h" + +//| """DUALBANK Module +//| +//| The `dualbank` module adds ability to update and switch +//| between the two app partitions. +//| +//| There are two identical partitions, these contain different +//| firmware versions. +//| Having two partitions enables rollback functionality. +//| +//| The two partitions are defined as boot partition and +//| next-update partition. Calling `dualbank.flash()` writes +//| the next-update partition. +//| +//| After the next-update partition is written a validation +//| check is performed and on a successful validation this +//| partition is set as the boot partition. On next reset, +//| firmware will be loaded from this partition. +//| +//| Here is the sequence of commands to follow: +//| +//| .. code-block:: python +//| +//| import dualbank +//| +//| dualbank.flash(buffer, offset) +//| dualbank.switch() +//| """ +//| ... +//| + +//| def flash(*buffer: ReadableBuffer, offset: int=0) -> None: +//| """Writes one of two app partitions at the given offset. +//| +//| This can be called multiple times when flashing the firmware +//| in small chunks. +//| """ +//| ... +//| +STATIC mp_obj_t dualbank_flash(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer, ARG_offset }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_offset, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, + }; + + 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); + + if (args[ARG_offset].u_int < 0) { + mp_raise_ValueError(translate("offset must be >= 0")); + } + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); + + common_hal_dualbank_flash(bufinfo.buf, bufinfo.len, args[ARG_offset].u_int); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(dualbank_flash_obj, 0, dualbank_flash); + +//| def switch() -> None: +//| """Switches the boot partition. +//| +//| On next reset, firmware will be loaded from the partition +//| just switched over to. +//| """ +//| ... +//| +STATIC mp_obj_t dualbank_switch(void) { + common_hal_dualbank_switch(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(dualbank_switch_obj, dualbank_switch); + +STATIC const mp_rom_map_elem_t dualbank_module_globals_table[] = { + // module name + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_dualbank) }, + // module functions + { MP_ROM_QSTR(MP_QSTR_flash), MP_ROM_PTR(&dualbank_flash_obj) }, + { MP_ROM_QSTR(MP_QSTR_switch), MP_ROM_PTR(&dualbank_switch_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(dualbank_module_globals, dualbank_module_globals_table); + +const mp_obj_module_t dualbank_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&dualbank_module_globals, +}; diff --git a/shared-bindings/dualbank/__init__.h b/shared-bindings/dualbank/__init__.h new file mode 100644 index 000000000..7edbc6d68 --- /dev/null +++ b/shared-bindings/dualbank/__init__.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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_DUALBANK___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_DUALBANK___INIT___H + +#include "py/runtime.h" + +extern void common_hal_dualbank_switch(void); +extern void common_hal_dualbank_flash(const void *buf, const size_t len, const size_t offset); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_DUALBANK___INIT___H diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c deleted file mode 100644 index 8ecc6d9c4..000000000 --- a/shared-bindings/ota/__init__.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 microDev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "shared-bindings/ota/__init__.h" - -//| """OTA Module -//| -//| The `ota` module implements over-the-air update. -//| -//| There are two identical ota partitions ota_0/1, these -//| contain different firmware versions. -//| Having two partitions enables rollback functionality. -//| -//| The two partitions are defined as boot partition and -//| next-update partition. Calling `ota.flash()` writes the -//| next-update partition. -//| -//| After the next-update partition is written a validation -//| check is performed and on a successful validation this -//| partition is set as the boot partition. On next reset, -//| firmware will be loaded from this partition. -//| -//| Here is the sequence of commands to follow: -//| -//| .. code-block:: python -//| -//| import ota -//| -//| ota.flash(buffer, offset) -//| ota.finish() -//| """ -//| ... -//| - -//| def switch() -> None: -//| """Switches the boot partition. On next reset, -//| firmware will be loaded from the partition -//| just switched over to.""" -//| ... -//| -STATIC mp_obj_t ota_switch(void) { - common_hal_ota_switch(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(ota_switch_obj, ota_switch); - -//| def finish() -> None: -//| """Validates flashed firmware, sets next boot partition. -//| **Must be called** after the firmware has been -//| completely written into the flash using `ota.flash()`. -//| -//| This is to be called only once per update.""" -//| ... -//| -STATIC mp_obj_t ota_finish(void) { - common_hal_ota_finish(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(ota_finish_obj, ota_finish); - -//| def flash(*buffer: ReadableBuffer, offset: int=0) -> None: -//| """Writes one of two OTA partitions at the given offset. -//| -//| The default offset is 0. It is necessary to provide the -//| offset when writing in discontinous chunks. -//| -//| This can be called multiple times when flashing the firmware -//| in small chunks.""" -//| ... -//| -STATIC mp_obj_t ota_flash(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_buffer, ARG_offset }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_buffer, MP_ARG_OBJ | MP_ARG_REQUIRED }, - { MP_QSTR_offset, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = -1} }, - }; - - 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); - - if (args[ARG_offset].u_int < -1) { - mp_raise_ValueError(translate("offset must be >= 0")); - } - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); - - common_hal_ota_flash(bufinfo.buf, bufinfo.len, args[ARG_offset].u_int); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ota_flash_obj, 0, ota_flash); - -STATIC const mp_rom_map_elem_t ota_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ota) }, - { MP_ROM_QSTR(MP_QSTR_switch), MP_ROM_PTR(&ota_switch_obj) }, - { MP_ROM_QSTR(MP_QSTR_finish), MP_ROM_PTR(&ota_finish_obj) }, - { MP_ROM_QSTR(MP_QSTR_flash), MP_ROM_PTR(&ota_flash_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(ota_module_globals, ota_module_globals_table); - -const mp_obj_module_t ota_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&ota_module_globals, -}; diff --git a/shared-bindings/ota/__init__.h b/shared-bindings/ota/__init__.h deleted file mode 100644 index 82273f975..000000000 --- a/shared-bindings/ota/__init__.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020 microDev - * - * 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_OTA___INIT___H -#define MICROPY_INCLUDED_SHARED_BINDINGS_OTA___INIT___H - -#include "py/runtime.h" - -extern void common_hal_ota_switch(void); -extern void common_hal_ota_finish(void); -extern void common_hal_ota_flash(const void *buf, const size_t len, const int32_t offset); - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_OTA___INIT___H -- cgit v1.2.3 From 8eaf2b0c1933fa4d0bef2786647b0eb0a586f605 Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Fri, 18 Dec 2020 12:54:36 +0530 Subject: implement touch alarm --- locale/circuitpython.pot | 3 +- ports/esp32s2/common-hal/alarm/__init__.c | 18 ++++--- ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c | 49 +++++++++++++++++ ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h | 45 ++++++++++++++++ py/circuitpy_defns.mk | 1 + shared-bindings/alarm/__init__.c | 17 +++++- shared-bindings/alarm/touch/TouchAlarm.c | 64 +++++++++++++++++++++++ shared-bindings/alarm/touch/TouchAlarm.h | 40 ++++++++++++++ 8 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c create mode 100644 ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h create mode 100644 shared-bindings/alarm/touch/TouchAlarm.c create mode 100644 shared-bindings/alarm/touch/TouchAlarm.h (limited to 'py') diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index d64cff185..63407f52b 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-12-14 12:59-0500\n" +"POT-Creation-Date: 2020-12-18 12:42+0530\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1144,6 +1144,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/atmel-samd/common-hal/touchio/TouchIn.c +#: ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c #: ports/esp32s2/common-hal/touchio/TouchIn.c shared-bindings/pwmio/PWMOut.c #: shared-module/rgbmatrix/RGBMatrix.c msgid "Invalid pin" diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index fae921db0..6fbad952f 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -29,11 +29,13 @@ #include "py/objtuple.h" #include "py/runtime.h" -#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/SleepMemory.h" +#include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h" -#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/alarm/touch/TouchAlarm.h" + #include "shared-bindings/wifi/__init__.h" +#include "shared-bindings/microcontroller/__init__.h" #include "supervisor/port.h" #include "supervisor/shared/workflow.h" @@ -49,10 +51,10 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { }, }; - void alarm_reset(void) { - alarm_time_timealarm_reset(); alarm_sleep_memory_reset(); + alarm_time_timealarm_reset(); + alarm_touch_touchalarm_reset(); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } @@ -60,6 +62,9 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { if (alarm_time_timealarm_woke_us_up()) { return ESP_SLEEP_WAKEUP_TIMER; } + if (alarm_touch_touchalarm_woke_us_up()) { + return ESP_SLEEP_WAKEUP_TOUCHPAD; + } return esp_sleep_get_wakeup_cause(); } @@ -80,8 +85,7 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { } case ESP_SLEEP_WAKEUP_TOUCHPAD: - // TODO: implement TouchIO - // Wake up from touch on pad, esp_sleep_get_touchpad_wakeup_status() + return alarm_touch_touchalarm_get_wakeup_alarm(n_alarms, alarms); break; case ESP_SLEEP_WAKEUP_UNDEFINED: @@ -110,6 +114,8 @@ STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t } time_alarm = MP_OBJ_TO_PTR(alarms[i]); time_alarm_set = true; + } else if (MP_OBJ_IS_TYPE(alarms[i], &alarm_touch_touchalarm_type)) { + alarm_touch_touchalarm_set_alarm(MP_OBJ_TO_PTR(alarms[i])); } } diff --git a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c new file mode 100644 index 000000000..b660e90c0 --- /dev/null +++ b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.c @@ -0,0 +1,49 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/alarm/touch/TouchAlarm.h" + +#include "esp_sleep.h" + +void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { + +} + +mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { + return mp_const_none; +} + +void alarm_touch_touchalarm_set_alarm(alarm_touch_touchalarm_obj_t *self) { + +} + +bool alarm_touch_touchalarm_woke_us_up(void) { + return false; +} + +void alarm_touch_touchalarm_reset(void) { + +} diff --git a/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h new file mode 100644 index 000000000..11643945d --- /dev/null +++ b/ports/esp32s2/common-hal/alarm/touch/TouchAlarm.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H +#define MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H + +#include "py/obj.h" +#include "common-hal/microcontroller/Pin.h" + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; +} alarm_touch_touchalarm_obj_t; + +// Find the alarm object that caused us to wake up or create an equivalent one. +mp_obj_t alarm_touch_touchalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms); +// Check for the wake up alarm from pretend deep sleep. +void alarm_touch_touchalarm_set_alarm(alarm_touch_touchalarm_obj_t *self); +bool alarm_touch_touchalarm_woke_us_up(void); +void alarm_touch_touchalarm_reset(void); + +#endif // MICROPY_INCLUDED_COMMON_HAL_ALARM_TOUCH_TOUCHALARM_H diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 1eafce259..a36600d62 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -308,6 +308,7 @@ SRC_COMMON_HAL_ALL = \ alarm/__init__.c \ alarm/pin/PinAlarm.c \ alarm/time/TimeAlarm.c \ + alarm/touch/TouchAlarm.c \ analogio/AnalogIn.c \ analogio/AnalogOut.c \ analogio/__init__.c \ diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 700fe020e..526f5453d 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -32,6 +32,7 @@ #include "shared-bindings/alarm/SleepMemory.h" #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/time/TimeAlarm.h" +#include "shared-bindings/alarm/touch/TouchAlarm.h" #include "shared-bindings/supervisor/Runtime.h" #include "shared-bindings/time/__init__.h" #include "supervisor/shared/autoreload.h" @@ -72,7 +73,8 @@ 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_time_alarm_type)) { + MP_OBJ_IS_TYPE(objs[i], &alarm_time_time_alarm_type) || + MP_OBJ_IS_TYPE(objs[i], &alarm_touch_touchalarm_type)) { continue; } mp_raise_TypeError_varg(translate("Expected an alarm")); @@ -182,6 +184,18 @@ STATIC const mp_obj_module_t alarm_time_module = { .globals = (mp_obj_dict_t*)&alarm_time_globals, }; +STATIC const mp_map_elem_t alarm_touch_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_touch) }, + { MP_ROM_QSTR(MP_QSTR_TouchAlarm), MP_OBJ_FROM_PTR(&alarm_touch_touchalarm_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(alarm_touch_globals, alarm_touch_globals_table); + +STATIC const mp_obj_module_t alarm_touch_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&alarm_touch_globals, +}; + // The module table is mutable because .wake_alarm is a mutable attribute. STATIC mp_map_elem_t alarm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_alarm) }, @@ -195,6 +209,7 @@ STATIC mp_map_elem_t alarm_module_globals_table[] = { { 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) }, + { MP_ROM_QSTR(MP_QSTR_touch), MP_OBJ_FROM_PTR(&alarm_touch_module) }, { MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type) }, { MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) }, diff --git a/shared-bindings/alarm/touch/TouchAlarm.c b/shared-bindings/alarm/touch/TouchAlarm.c new file mode 100644 index 000000000..8ee1bc75a --- /dev/null +++ b/shared-bindings/alarm/touch/TouchAlarm.c @@ -0,0 +1,64 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/alarm/touch/TouchAlarm.h" +#include "shared-bindings/board/__init__.h" + +//| class TouchAlarm: +//| """Trigger an alarm when touch is detected.""" +//| +//| def __init__(self, *pin: microcontroller.Pin) -> None: +//| """Create an alarm that will be triggered when the +//| given pin is touched. +//| +//| """ +//| ... +//| +STATIC mp_obj_t alarm_touch_touchalarm_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_touch_touchalarm_obj_t *self = m_new_obj(alarm_touch_touchalarm_obj_t); + self->base.type = &alarm_touch_touchalarm_type; + + enum { ARG_pin }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + + 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); + + const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); + + common_hal_alarm_touch_touchalarm_construct(self, pin); + + return MP_OBJ_FROM_PTR(self); +} + +const mp_obj_type_t alarm_touch_touchalarm_type = { + { &mp_type_type }, + .name = MP_QSTR_TouchAlarm, + .make_new = alarm_touch_touchalarm_make_new, +}; diff --git a/shared-bindings/alarm/touch/TouchAlarm.h b/shared-bindings/alarm/touch/TouchAlarm.h new file mode 100644 index 000000000..1b70d4dae --- /dev/null +++ b/shared-bindings/alarm/touch/TouchAlarm.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 microDev + * + * 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_TOUCH_TOUCHALARM_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TOUCH_TOUCHALARM_H + +#include "py/obj.h" +#include "py/runtime.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/alarm/touch/TouchAlarm.h" + +extern const mp_obj_type_t alarm_touch_touchalarm_type; + +extern void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TOUCH_TOUCHALARM_H -- cgit v1.2.3 From 1fca297a2d2bfefb1cdef3ecbac05f54d15e08eb Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 22 Dec 2020 16:13:02 -0800 Subject: A couple sleep fixes * Better messaging when code is stopped by an auto-reload. * Auto-reload works during sleeps on ESP32-S2. Ticks wake up the main task each time. * Made internal naming consistent. CamelCase Python names are NOT separated by an underscore. --- main.c | 9 ++-- ports/esp32s2/common-hal/alarm/__init__.c | 31 +++++-------- ports/esp32s2/common-hal/alarm/pin/PinAlarm.c | 60 ++++++++++++------------- ports/esp32s2/common-hal/alarm/pin/PinAlarm.h | 12 ++--- ports/esp32s2/common-hal/alarm/time/TimeAlarm.c | 26 +++++------ ports/esp32s2/common-hal/alarm/time/TimeAlarm.h | 2 +- ports/esp32s2/supervisor/port.c | 28 ++++++------ py/obj.c | 2 + shared-bindings/alarm/__init__.c | 10 ++--- shared-bindings/alarm/__init__.h | 3 -- shared-bindings/alarm/pin/PinAlarm.c | 46 +++++++++---------- shared-bindings/alarm/pin/PinAlarm.h | 18 ++++---- shared-bindings/alarm/time/TimeAlarm.c | 32 ++++++------- shared-bindings/alarm/time/TimeAlarm.h | 12 ++--- 14 files changed, 142 insertions(+), 149 deletions(-) (limited to 'py') diff --git a/main.c b/main.c index 27ed6ff11..9c4055a28 100755 --- a/main.c +++ b/main.c @@ -308,8 +308,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { return reload_requested; } - // Display a different completion message if the user has no USB attached (cannot save files) - serial_write_compressed(translate("\nCode done running. Waiting for reload.\n")); + if (reload_requested && result.return_code == PYEXEC_EXCEPTION) { + serial_write_compressed(translate("\nCode stopped by auto-reload.\n")); + } else { + serial_write_compressed(translate("\nCode done running.\n")); + } } // Program has finished running. @@ -407,7 +410,7 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { alarm_enter_deep_sleep(); // Does not return. } else { - serial_write_compressed(translate("Pretending to deep sleep until alarm, any key or file write.\n")); + serial_write_compressed(translate("Pretending to deep sleep until alarm, CTRL-C or file write.\n")); } } } diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 9f19f1afc..f2686cf18 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -54,7 +54,7 @@ const alarm_sleep_memory_obj_t alarm_sleep_memory_obj = { void alarm_reset(void) { alarm_time_timealarm_reset(); - alarm_pin_pin_alarm_reset(); + alarm_pin_pinalarm_reset(); alarm_sleep_memory_reset(); esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL); } @@ -63,7 +63,7 @@ STATIC esp_sleep_wakeup_cause_t _get_wakeup_cause(void) { if (alarm_time_timealarm_woke_us_up()) { return ESP_SLEEP_WAKEUP_TIMER; } - if (alarm_pin_pin_alarm_woke_us_up()) { + if (alarm_pin_pinalarm_woke_us_up()) { return ESP_SLEEP_WAKEUP_GPIO; } @@ -84,7 +84,7 @@ STATIC mp_obj_t _get_wake_alarm(size_t n_alarms, const mp_obj_t *alarms) { case ESP_SLEEP_WAKEUP_GPIO: case ESP_SLEEP_WAKEUP_EXT0: case ESP_SLEEP_WAKEUP_EXT1: { - return alarm_pin_pin_alarm_get_wakeup_alarm(n_alarms, alarms); + return alarm_pin_pinalarm_get_wakeup_alarm(n_alarms, alarms); } case ESP_SLEEP_WAKEUP_TOUCHPAD: @@ -106,7 +106,7 @@ mp_obj_t common_hal_alarm_get_wake_alarm(void) { // Set up light sleep or deep sleep alarms. STATIC void _setup_sleep_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { - alarm_pin_pin_alarm_set_alarms(deep_sleep, n_alarms, alarms); + alarm_pin_pinalarm_set_alarms(deep_sleep, n_alarms, alarms); alarm_time_timealarm_set_alarms(deep_sleep, n_alarms, alarms); } @@ -123,25 +123,14 @@ STATIC void _idle_until_alarm(void) { } } -// Is it safe to do a light sleep? Check whether WiFi is on or there are -// other ongoing tasks that should not be shut down. -STATIC bool _light_sleep_ok(void) { - int64_t connecting_delay_ticks = CIRCUITPY_USB_CONNECTED_SLEEP_DELAY * 1024 - port_get_raw_ticks(NULL); - return !common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) && - !supervisor_workflow_active() && - connecting_delay_ticks <= 0; -} - mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms) { _setup_sleep_alarms(false, n_alarms, alarms); - // Light sleep can break some functionality so only do it when possible. Otherwise we idle. - if (_light_sleep_ok()) { - // Flush the UART to complete the log line. - uart_wait_tx_idle_polling(CONFIG_ESP_CONSOLE_UART_NUM); - esp_light_sleep_start(); - } else { - _idle_until_alarm(); + // We cannot esp_light_sleep_start() here because it shuts down all non-RTC peripherals. + _idle_until_alarm(); + + if (mp_hal_is_interrupted()) { + return mp_const_none; // Shouldn't be given to python code because exception handling should kick in. } mp_obj_t wake_alarm = _get_wake_alarm(n_alarms, alarms); @@ -154,7 +143,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala } void NORETURN alarm_enter_deep_sleep(void) { - alarm_pin_pin_alarm_prepare_for_deep_sleep(); + alarm_pin_pinalarm_prepare_for_deep_sleep(); // The ESP-IDF caches the deep sleep settings and applies them before sleep. // We don't need to worry about resetting them in the interim. esp_deep_sleep_start(); diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c index 01e2faeb8..df8d10ef9 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.c @@ -38,7 +38,7 @@ #include "components/soc/src/esp32s2/include/hal/gpio_ll.h" #include "components/xtensa/include/esp_debug_helpers.h" -void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull) { if (edge) { mp_raise_ValueError(translate("Cannot wake on pin edge. Only level.")); } @@ -51,41 +51,41 @@ void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, m self->pull = pull; } -mcu_pin_obj_t *common_hal_alarm_pin_pin_alarm_get_pin(alarm_pin_pin_alarm_obj_t *self) { +mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self) { return self->pin; } -bool common_hal_alarm_pin_pin_alarm_get_value(alarm_pin_pin_alarm_obj_t *self) { +bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self) { return self->value; } -bool common_hal_alarm_pin_pin_alarm_get_edge(alarm_pin_pin_alarm_obj_t *self) { +bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self) { return false; } -bool common_hal_alarm_pin_pin_alarm_get_pull(alarm_pin_pin_alarm_obj_t *self) { +bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self) { return self->pull; } gpio_isr_handle_t gpio_interrupt_handle; // Low and high are relative to pin number. 32+ is high. <32 is low. -static volatile uint32_t low_pin_status = 0; -static volatile uint32_t high_pin_status = 0; +static volatile uint32_t pin_31_0_status = 0; +static volatile uint32_t pin_63_32_status = 0; void gpio_interrupt(void *arg) { (void) arg; - gpio_ll_get_intr_status(&GPIO, xPortGetCoreID(), (uint32_t*) &low_pin_status); - gpio_ll_clear_intr_status(&GPIO, low_pin_status); - gpio_ll_get_intr_status_high(&GPIO, xPortGetCoreID(), (uint32_t*) &high_pin_status); - gpio_ll_clear_intr_status_high(&GPIO, high_pin_status); + gpio_ll_get_intr_status(&GPIO, xPortGetCoreID(), (uint32_t*) &pin_31_0_status); + gpio_ll_clear_intr_status(&GPIO, pin_31_0_status); + gpio_ll_get_intr_status_high(&GPIO, xPortGetCoreID(), (uint32_t*) &pin_63_32_status); + gpio_ll_clear_intr_status_high(&GPIO, pin_63_32_status); // disable the interrupts that fired, maybe all of them for (size_t i = 0; i < 32; i++) { uint32_t mask = 1 << i; - if ((low_pin_status & mask) != 0) { + if ((pin_31_0_status & mask) != 0) { gpio_ll_intr_disable(&GPIO, i); } - if ((high_pin_status & mask) != 0) { + if ((pin_63_32_status & mask) != 0) { gpio_ll_intr_disable(&GPIO, 32 + i); } } @@ -96,18 +96,18 @@ void gpio_interrupt(void *arg) { } } -bool alarm_pin_pin_alarm_woke_us_up(void) { - return low_pin_status != 0 || high_pin_status != 0; +bool alarm_pin_pinalarm_woke_us_up(void) { + return pin_31_0_status != 0 || pin_63_32_status != 0; } -mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { +mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { // First, check to see if we match any given alarms. - uint64_t pin_status = ((uint64_t) high_pin_status) << 32 | low_pin_status; + uint64_t pin_status = ((uint64_t) pin_63_32_status) << 32 | pin_31_0_status; for (size_t i = 0; i < n_alarms; i++) { - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { continue; } - alarm_pin_pin_alarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); if ((pin_status & (1ull << alarm->pin->number)) != 0) { return alarms[i]; } @@ -131,8 +131,8 @@ mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *a } } - alarm_pin_pin_alarm_obj_t *alarm = m_new_obj(alarm_pin_pin_alarm_obj_t); - alarm->base.type = &alarm_pin_pin_alarm_type; + alarm_pin_pinalarm_obj_t *alarm = m_new_obj(alarm_pin_pinalarm_obj_t); + alarm->base.type = &alarm_pin_pinalarm_type; alarm->pin = NULL; // Map the pin number back to a pin object. for (size_t i = 0; i < mcu_pin_globals.map.used; i++) { @@ -151,7 +151,7 @@ static uint64_t high_alarms = 0; static uint64_t low_alarms = 0; static uint64_t pull_pins = 0; -void alarm_pin_pin_alarm_reset(void) { +void alarm_pin_pinalarm_reset(void) { if (gpio_interrupt_handle != NULL) { esp_intr_free(gpio_interrupt_handle); gpio_interrupt_handle = NULL; @@ -168,21 +168,21 @@ void alarm_pin_pin_alarm_reset(void) { high_alarms = 0; low_alarms = 0; pull_pins = 0; - high_pin_status = 0; - low_pin_status = 0; + pin_63_32_status = 0; + pin_31_0_status = 0; } -void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { +void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { // Bitmask of wake up settings. size_t high_count = 0; size_t low_count = 0; for (size_t i = 0; i < n_alarms; i++) { // TODO: Check for ULP or touch alarms because they can't coexist with GPIO alarms. - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pin_alarm_type)) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_pin_pinalarm_type)) { continue; } - alarm_pin_pin_alarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); + alarm_pin_pinalarm_obj_t *alarm = MP_OBJ_TO_PTR(alarms[i]); gpio_num_t pin_number = alarm->pin->number; if (alarm->value) { @@ -239,8 +239,8 @@ void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_o } // Set GPIO interrupts so they wake us from light sleep or from idle via the // interrupt handler above. - low_pin_status = 0; - high_pin_status = 0; + pin_31_0_status = 0; + pin_63_32_status = 0; if (gpio_isr_register(gpio_interrupt, NULL, 0, &gpio_interrupt_handle) != ESP_OK) { mp_raise_ValueError(translate("Can only alarm on RTC IO from deep sleep.")); } @@ -282,7 +282,7 @@ void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_o } -void alarm_pin_pin_alarm_prepare_for_deep_sleep(void) { +void alarm_pin_pinalarm_prepare_for_deep_sleep(void) { if (pull_pins == 0) { return; } diff --git a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h index 8b14931ca..93672c1f2 100644 --- a/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h +++ b/ports/esp32s2/common-hal/alarm/pin/PinAlarm.h @@ -32,10 +32,10 @@ typedef struct { mcu_pin_obj_t *pin; bool value; bool pull; -} alarm_pin_pin_alarm_obj_t; +} alarm_pin_pinalarm_obj_t; -void alarm_pin_pin_alarm_reset(void); -void alarm_pin_pin_alarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); -void alarm_pin_pin_alarm_prepare_for_deep_sleep(void); -mp_obj_t alarm_pin_pin_alarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms); -bool alarm_pin_pin_alarm_woke_us_up(void); +void alarm_pin_pinalarm_reset(void); +void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms); +void alarm_pin_pinalarm_prepare_for_deep_sleep(void); +mp_obj_t alarm_pin_pinalarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms); +bool alarm_pin_pinalarm_woke_us_up(void); diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c index a7abde6a4..bcde0ab3c 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.c @@ -34,23 +34,23 @@ #include "shared-bindings/alarm/time/TimeAlarm.h" #include "shared-bindings/time/__init__.h" -void common_hal_alarm_time_time_alarm_construct(alarm_time_time_alarm_obj_t *self, mp_float_t monotonic_time) { +void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time) { self->monotonic_time = monotonic_time; } -mp_float_t common_hal_alarm_time_time_alarm_get_monotonic_time(alarm_time_time_alarm_obj_t *self) { +mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timealarm_obj_t *self) { return self->monotonic_time; } mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms) { // First, check to see if we match for (size_t i = 0; i < n_alarms; i++) { - if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_time_alarm_type)) { + if (MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { return alarms[i]; } } - alarm_time_time_alarm_obj_t *timer = m_new_obj(alarm_time_time_alarm_obj_t); - timer->base.type = &alarm_time_time_alarm_type; + alarm_time_timealarm_obj_t *timer = m_new_obj(alarm_time_timealarm_obj_t); + timer->base.type = &alarm_time_timealarm_type; // TODO: Set monotonic_time based on the RTC state. timer->monotonic_time = 0.0f; return timer; @@ -78,20 +78,20 @@ void alarm_time_timealarm_reset(void) { } void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_obj_t *alarms) { - bool time_alarm_set = false; - alarm_time_time_alarm_obj_t *time_alarm = MP_OBJ_NULL; + bool timealarm_set = false; + alarm_time_timealarm_obj_t *timealarm = MP_OBJ_NULL; for (size_t i = 0; i < n_alarms; i++) { - if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_time_alarm_type)) { + if (!MP_OBJ_IS_TYPE(alarms[i], &alarm_time_timealarm_type)) { continue; } - if (time_alarm_set) { + if (timealarm_set) { mp_raise_ValueError(translate("Only one alarm.time alarm can be set.")); } - time_alarm = MP_OBJ_TO_PTR(alarms[i]); - time_alarm_set = true; + timealarm = MP_OBJ_TO_PTR(alarms[i]); + timealarm_set = true; } - if (!time_alarm_set) { + if (!timealarm_set) { return; } @@ -109,7 +109,7 @@ void alarm_time_timealarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ // Compute how long to actually sleep, considering the time now. mp_float_t now_secs = uint64_to_float(common_hal_time_monotonic_ms()) / 1000.0f; - mp_float_t wakeup_in_secs = MAX(0.0f, time_alarm->monotonic_time - now_secs); + mp_float_t wakeup_in_secs = MAX(0.0f, timealarm->monotonic_time - now_secs); const uint64_t sleep_for_us = (uint64_t) (wakeup_in_secs * 1000000); esp_sleep_enable_timer_wakeup(sleep_for_us); diff --git a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h index 277ababc2..dfd75524f 100644 --- a/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h +++ b/ports/esp32s2/common-hal/alarm/time/TimeAlarm.h @@ -30,7 +30,7 @@ typedef struct { mp_obj_base_t base; mp_float_t monotonic_time; // values compatible with time.monotonic_time() -} alarm_time_time_alarm_obj_t; +} alarm_time_timealarm_obj_t; // Find the alarm object that caused us to wake up or create an equivalent one. mp_obj_t alarm_time_timealarm_get_wakeup_alarm(size_t n_alarms, const mp_obj_t *alarms); diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index 8a87180cd..17a413a2e 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -74,6 +74,10 @@ extern void esp_restart(void) NORETURN; void tick_timer_cb(void* arg) { supervisor_tick(); + + // CircuitPython's VM is run in a separate FreeRTOS task from timer callbacks. So, we have to + // notify the main task every time in case it's waiting for us. + xTaskNotifyGive(circuitpython_task); } void sleep_timer_cb(void* arg); @@ -92,6 +96,8 @@ safe_mode_t port_init(void) { args.name = "CircuitPython Sleep"; esp_timer_create(&args, &_sleep_timer); + circuitpython_task = xTaskGetCurrentTaskHandle(); + // Send the ROM output out of the UART. This includes early logs. #ifdef DEBUG ets_install_uart_printf(); @@ -114,17 +120,17 @@ safe_mode_t port_init(void) { } esp_reset_reason_t reason = esp_reset_reason(); - if (reason == ESP_RST_BROWNOUT) { - return BROWNOUT; - } - if (reason == ESP_RST_PANIC || - reason == ESP_RST_INT_WDT || - reason == ESP_RST_WDT) { - return HARD_CRASH; + switch (reason) { + case ESP_RST_BROWNOUT: + return BROWNOUT; + case ESP_RST_PANIC: + case ESP_RST_INT_WDT: + case ESP_RST_WDT: + return HARD_CRASH; + default: + break; } - circuitpython_task = xTaskGetCurrentTaskHandle(); - return NO_SAFE_MODE; } @@ -262,10 +268,6 @@ void port_enable_tick(void) { // Disable 1/1024 second tick. void port_disable_tick(void) { esp_timer_stop(_tick_timer); - - // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB. - // Tick disable can happen via auto-reload so poke the main task here. - xTaskNotifyGive(circuitpython_task); } void sleep_timer_cb(void* arg) { diff --git a/py/obj.c b/py/obj.c index 218fb4321..5f19089e8 100644 --- a/py/obj.c +++ b/py/obj.c @@ -68,10 +68,12 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t #ifdef RUN_BACKGROUND_TASKS RUN_BACKGROUND_TASKS; #endif + #if MICROPY_KBD_EXCEPTION // Stop printing if we've been interrupted. if (mp_hal_is_interrupted()) { return; } + #endif #ifndef NDEBUG if (o_in == MP_OBJ_NULL) { diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 778674f6d..dc5309353 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -71,8 +71,8 @@ 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_time_alarm_type)) { + if (MP_OBJ_IS_TYPE(objs[i], &alarm_pin_pinalarm_type) || + MP_OBJ_IS_TYPE(objs[i], &alarm_time_timealarm_type)) { continue; } mp_raise_TypeError_varg(translate("Expected an alarm")); @@ -159,7 +159,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_exit_and_deep_sleep_until_alarms_obj, STATIC const mp_map_elem_t alarm_pin_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pin) }, - { MP_ROM_QSTR(MP_QSTR_PinAlarm), MP_OBJ_FROM_PTR(&alarm_pin_pin_alarm_type) }, + { MP_ROM_QSTR(MP_QSTR_PinAlarm), MP_OBJ_FROM_PTR(&alarm_pin_pinalarm_type) }, }; STATIC MP_DEFINE_CONST_DICT(alarm_pin_globals, alarm_pin_globals_table); @@ -172,7 +172,7 @@ STATIC const mp_obj_module_t alarm_pin_module = { STATIC const mp_map_elem_t alarm_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) }, - { MP_ROM_QSTR(MP_QSTR_TimeAlarm), MP_OBJ_FROM_PTR(&alarm_time_time_alarm_type) }, + { MP_ROM_QSTR(MP_QSTR_TimeAlarm), MP_OBJ_FROM_PTR(&alarm_time_timealarm_type) }, }; STATIC MP_DEFINE_CONST_DICT(alarm_time_globals, alarm_time_globals_table); @@ -199,7 +199,7 @@ STATIC mp_map_elem_t alarm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SleepMemory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_type) }, { MP_ROM_QSTR(MP_QSTR_sleep_memory), MP_OBJ_FROM_PTR(&alarm_sleep_memory_obj) }, }; -MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); +STATIC MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); // Fetch value from module dict. mp_obj_t alarm_get_wake_alarm(void) { diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index a90405da6..4c12e0e70 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -31,9 +31,6 @@ #include "common-hal/alarm/__init__.h" -// Make module dict available elsewhere, so we can fetch -extern mp_obj_dict_t alarm_module_globals; - extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj_t *alarms); // Deep sleep is a two step process. Alarms are set when the VM is valid but diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index 83ccc0d76..89de016bc 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -60,9 +60,9 @@ //| """ //| ... //| -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; +STATIC mp_obj_t alarm_pin_pinalarm_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_pinalarm_obj_t *self = m_new_obj(alarm_pin_pinalarm_obj_t); + self->base.type = &alarm_pin_pinalarm_type; enum { ARG_pin, ARG_value, ARG_edge, ARG_pull }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -75,7 +75,7 @@ STATIC mp_obj_t alarm_pin_pin_alarm_make_new(const mp_obj_type_t *type, mp_uint_ mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); - common_hal_alarm_pin_pin_alarm_construct(self, + common_hal_alarm_pin_pinalarm_construct(self, pin, args[ARG_value].u_bool, args[ARG_edge].u_bool, @@ -87,19 +87,19 @@ STATIC mp_obj_t alarm_pin_pin_alarm_make_new(const mp_obj_type_t *type, mp_uint_ //| pin: microcontroller.Pin //| """The trigger pin.""" //| -STATIC mp_obj_t alarm_pin_pin_alarm_obj_get_pin(mp_obj_t self_in) { - alarm_pin_pin_alarm_obj_t *self = MP_OBJ_TO_PTR(self_in); - mcu_pin_obj_t* pin = common_hal_alarm_pin_pin_alarm_get_pin(self); +STATIC mp_obj_t alarm_pin_pinalarm_obj_get_pin(mp_obj_t self_in) { + alarm_pin_pinalarm_obj_t *self = MP_OBJ_TO_PTR(self_in); + mcu_pin_obj_t* pin = common_hal_alarm_pin_pinalarm_get_pin(self); if (pin == NULL) { return mp_const_none; } return MP_OBJ_FROM_PTR(pin); } -MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pin_alarm_get_pin_obj, alarm_pin_pin_alarm_obj_get_pin); +MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pinalarm_get_pin_obj, alarm_pin_pinalarm_obj_get_pin); -const mp_obj_property_t alarm_pin_pin_alarm_pin_obj = { +const mp_obj_property_t alarm_pin_pinalarm_pin_obj = { .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&alarm_pin_pin_alarm_get_pin_obj, + .proxy = {(mp_obj_t)&alarm_pin_pinalarm_get_pin_obj, (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj}, }; @@ -107,29 +107,29 @@ const mp_obj_property_t alarm_pin_pin_alarm_pin_obj = { //| value: bool //| """The value on which to trigger.""" //| -STATIC mp_obj_t alarm_pin_pin_alarm_obj_get_value(mp_obj_t self_in) { - alarm_pin_pin_alarm_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_bool(common_hal_alarm_pin_pin_alarm_get_value(self)); +STATIC mp_obj_t alarm_pin_pinalarm_obj_get_value(mp_obj_t self_in) { + alarm_pin_pinalarm_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_alarm_pin_pinalarm_get_value(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pin_alarm_get_value_obj, alarm_pin_pin_alarm_obj_get_value); +MP_DEFINE_CONST_FUN_OBJ_1(alarm_pin_pinalarm_get_value_obj, alarm_pin_pinalarm_obj_get_value); -const mp_obj_property_t alarm_pin_pin_alarm_value_obj = { +const mp_obj_property_t alarm_pin_pinalarm_value_obj = { .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&alarm_pin_pin_alarm_get_value_obj, + .proxy = {(mp_obj_t)&alarm_pin_pinalarm_get_value_obj, (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj}, }; -STATIC const mp_rom_map_elem_t alarm_pin_pin_alarm_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&alarm_pin_pin_alarm_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&alarm_pin_pin_alarm_value_obj) }, +STATIC const mp_rom_map_elem_t alarm_pin_pinalarm_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&alarm_pin_pinalarm_pin_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&alarm_pin_pinalarm_value_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(alarm_pin_pin_alarm_locals_dict, alarm_pin_pin_alarm_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(alarm_pin_pinalarm_locals_dict, alarm_pin_pinalarm_locals_dict_table); -const mp_obj_type_t alarm_pin_pin_alarm_type = { +const mp_obj_type_t alarm_pin_pinalarm_type = { { &mp_type_type }, .name = MP_QSTR_PinAlarm, - .make_new = alarm_pin_pin_alarm_make_new, - .locals_dict = (mp_obj_t)&alarm_pin_pin_alarm_locals_dict, + .make_new = alarm_pin_pinalarm_make_new, + .locals_dict = (mp_obj_t)&alarm_pin_pinalarm_locals_dict, }; diff --git a/shared-bindings/alarm/pin/PinAlarm.h b/shared-bindings/alarm/pin/PinAlarm.h index 49ba71089..48865009c 100644 --- a/shared-bindings/alarm/pin/PinAlarm.h +++ b/shared-bindings/alarm/pin/PinAlarm.h @@ -24,20 +24,20 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PIN_ALARM_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PIN_ALARM_H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PINALARM_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PINALARM_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 const mp_obj_type_t alarm_pin_pinalarm_type; -void common_hal_alarm_pin_pin_alarm_construct(alarm_pin_pin_alarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull); -extern mcu_pin_obj_t *common_hal_alarm_pin_pin_alarm_get_pin(alarm_pin_pin_alarm_obj_t *self); -extern bool common_hal_alarm_pin_pin_alarm_get_value(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); +void common_hal_alarm_pin_pinalarm_construct(alarm_pin_pinalarm_obj_t *self, mcu_pin_obj_t *pin, bool value, bool edge, bool pull); +extern mcu_pin_obj_t *common_hal_alarm_pin_pinalarm_get_pin(alarm_pin_pinalarm_obj_t *self); +extern bool common_hal_alarm_pin_pinalarm_get_value(alarm_pin_pinalarm_obj_t *self); +extern bool common_hal_alarm_pin_pinalarm_get_edge(alarm_pin_pinalarm_obj_t *self); +extern bool common_hal_alarm_pin_pinalarm_get_pull(alarm_pin_pinalarm_obj_t *self); -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PIN_ALARM_H +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_PIN_PINALARM_H diff --git a/shared-bindings/alarm/time/TimeAlarm.c b/shared-bindings/alarm/time/TimeAlarm.c index 1c4d976ad..1c9b8d37c 100644 --- a/shared-bindings/alarm/time/TimeAlarm.c +++ b/shared-bindings/alarm/time/TimeAlarm.c @@ -56,10 +56,10 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) { //| """ //| ... //| -STATIC mp_obj_t alarm_time_time_alarm_make_new(const mp_obj_type_t *type, +STATIC mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - alarm_time_time_alarm_obj_t *self = m_new_obj(alarm_time_time_alarm_obj_t); - self->base.type = &alarm_time_time_alarm_type; + alarm_time_timealarm_obj_t *self = m_new_obj(alarm_time_timealarm_obj_t); + self->base.type = &alarm_time_timealarm_type; enum { ARG_monotonic_time, ARG_epoch_time }; static const mp_arg_t allowed_args[] = { @@ -105,7 +105,7 @@ STATIC mp_obj_t alarm_time_time_alarm_make_new(const mp_obj_type_t *type, mp_raise_ValueError(translate("Time is in the past.")); } - common_hal_alarm_time_time_alarm_construct(self, monotonic_time); + common_hal_alarm_time_timealarm_construct(self, monotonic_time); return MP_OBJ_FROM_PTR(self); } @@ -116,28 +116,28 @@ STATIC mp_obj_t alarm_time_time_alarm_make_new(const mp_obj_type_t *type, //| by this property only as a `time.monotonic()` time. //| """ //| -STATIC mp_obj_t alarm_time_time_alarm_obj_get_monotonic_time(mp_obj_t self_in) { - alarm_time_time_alarm_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_float(common_hal_alarm_time_time_alarm_get_monotonic_time(self)); +STATIC mp_obj_t alarm_time_timealarm_obj_get_monotonic_time(mp_obj_t self_in) { + alarm_time_timealarm_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_float(common_hal_alarm_time_timealarm_get_monotonic_time(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(alarm_time_time_alarm_get_monotonic_time_obj, alarm_time_time_alarm_obj_get_monotonic_time); +MP_DEFINE_CONST_FUN_OBJ_1(alarm_time_timealarm_get_monotonic_time_obj, alarm_time_timealarm_obj_get_monotonic_time); -const mp_obj_property_t alarm_time_time_alarm_monotonic_time_obj = { +const mp_obj_property_t alarm_time_timealarm_monotonic_time_obj = { .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&alarm_time_time_alarm_get_monotonic_time_obj, + .proxy = {(mp_obj_t)&alarm_time_timealarm_get_monotonic_time_obj, (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj}, }; -STATIC const mp_rom_map_elem_t alarm_time_time_alarm_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_monotonic_time), MP_ROM_PTR(&alarm_time_time_alarm_monotonic_time_obj) }, +STATIC const mp_rom_map_elem_t alarm_time_timealarm_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_monotonic_time), MP_ROM_PTR(&alarm_time_timealarm_monotonic_time_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(alarm_time_time_alarm_locals_dict, alarm_time_time_alarm_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(alarm_time_timealarm_locals_dict, alarm_time_timealarm_locals_dict_table); -const mp_obj_type_t alarm_time_time_alarm_type = { +const mp_obj_type_t alarm_time_timealarm_type = { { &mp_type_type }, .name = MP_QSTR_TimeAlarm, - .make_new = alarm_time_time_alarm_make_new, - .locals_dict = (mp_obj_t)&alarm_time_time_alarm_locals_dict, + .make_new = alarm_time_timealarm_make_new, + .locals_dict = (mp_obj_t)&alarm_time_timealarm_locals_dict, }; diff --git a/shared-bindings/alarm/time/TimeAlarm.h b/shared-bindings/alarm/time/TimeAlarm.h index ceb3291c9..0a4b9caf4 100644 --- a/shared-bindings/alarm/time/TimeAlarm.h +++ b/shared-bindings/alarm/time/TimeAlarm.h @@ -24,16 +24,16 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_MONOTONIC_TIME_ALARM_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_MONOTINIC_TIME_ALARM_H +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_TIMEALARM_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_TIMEALARM_H #include "py/obj.h" #include "common-hal/alarm/time/TimeAlarm.h" -extern const mp_obj_type_t alarm_time_time_alarm_type; +extern const mp_obj_type_t alarm_time_timealarm_type; -extern void common_hal_alarm_time_time_alarm_construct(alarm_time_time_alarm_obj_t *self, mp_float_t monotonic_time); -extern mp_float_t common_hal_alarm_time_time_alarm_get_monotonic_time(alarm_time_time_alarm_obj_t *self); +extern void common_hal_alarm_time_timealarm_construct(alarm_time_timealarm_obj_t *self, mp_float_t monotonic_time); +extern mp_float_t common_hal_alarm_time_timealarm_get_monotonic_time(alarm_time_timealarm_obj_t *self); -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_MONOTONIC_TIME_ALARM_H +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM_TIME_TIMEALARM_H -- cgit v1.2.3 From 42a229c08b6b5d64af8d4bc5ec99f3e285befd14 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 23 Dec 2020 10:43:04 -0600 Subject: circuitpy_mpconfig.mk: Unconditionally disable CIRCUITPY_BUSDEVICE Several issues have been found in the implementation. While they're unresolved, it may be better to disable the built-in module. (This means that to work on fixing the module, it'll be necessary to revert this commit) --- py/circuitpy_mpconfig.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py') diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index af1dccf02..e588c41e0 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -96,7 +96,7 @@ CFLAGS += -DCIRCUITPY_BLEIO=$(CIRCUITPY_BLEIO) CIRCUITPY_BOARD ?= 1 CFLAGS += -DCIRCUITPY_BOARD=$(CIRCUITPY_BOARD) -CIRCUITPY_BUSDEVICE ?= $(CIRCUITPY_FULL_BUILD) +CIRCUITPY_BUSDEVICE = 0 CFLAGS += -DCIRCUITPY_BUSDEVICE=$(CIRCUITPY_BUSDEVICE) CIRCUITPY_BUILTINS_POW3 ?= $(CIRCUITPY_FULL_BUILD) -- cgit v1.2.3