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 --- shared-bindings/ota/__init__.c | 51 ++++++++++++++++++++++++++++++++++++++++++ shared-bindings/ota/__init__.h | 34 ++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 shared-bindings/ota/__init__.c create mode 100644 shared-bindings/ota/__init__.h (limited to 'shared-bindings') 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 dee86a014b783aff61a72f9915a4538a7fc97e4e Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Thu, 10 Dec 2020 14:04:24 +0530 Subject: factor out esp_ota_end --- ports/esp32s2/common-hal/ota/__init__.c | 9 +++++++-- shared-bindings/ota/__init__.c | 7 +++++++ shared-bindings/ota/__init__.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'shared-bindings') diff --git a/ports/esp32s2/common-hal/ota/__init__.c b/ports/esp32s2/common-hal/ota/__init__.c index b83a929a2..2afb1904b 100644 --- a/ports/esp32s2/common-hal/ota/__init__.c +++ b/ports/esp32s2/common-hal/ota/__init__.c @@ -31,6 +31,9 @@ #include "esp_log.h" #include "esp_ota_ops.h" +esp_ota_handle_t update_handle = 0 ; +const esp_partition_t *update_partition = NULL; + static const char *TAG = "OTA"; static void __attribute__((noreturn)) task_fatal_error(void) { @@ -41,8 +44,6 @@ static void __attribute__((noreturn)) task_fatal_error(void) { void common_hal_ota_flash(const void *buf, const size_t len) { esp_err_t err; - esp_ota_handle_t update_handle = 0 ; - const esp_partition_t *update_partition = NULL; update_partition = esp_ota_get_next_update_partition(NULL); const esp_partition_t *running = esp_ota_get_running_partition(); @@ -100,6 +101,10 @@ void common_hal_ota_flash(const void *buf, const size_t len) { ESP_LOGE(TAG, "esp_ota_write failed (%s)", esp_err_to_name(err)); task_fatal_error(); } +} + +void common_hal_ota_finish(void) { + esp_err_t err; err = esp_ota_end(update_handle); if (err != ESP_OK) { diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c index a6c042486..55858a80e 100644 --- a/shared-bindings/ota/__init__.c +++ b/shared-bindings/ota/__init__.c @@ -30,6 +30,12 @@ //| //| The `ota` module implements over-the-air 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); + 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); @@ -41,6 +47,7 @@ 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_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); diff --git a/shared-bindings/ota/__init__.h b/shared-bindings/ota/__init__.h index c4b40b2af..1765c21ad 100644 --- a/shared-bindings/ota/__init__.h +++ b/shared-bindings/ota/__init__.h @@ -29,6 +29,7 @@ #include "py/runtime.h" +extern void common_hal_ota_finish(void); 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 bfa2c604efa213628bb33ad870b851a43f21c877 Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Thu, 10 Dec 2020 15:45:25 +0530 Subject: add ability to flash in discontinuous chunks --- ports/esp32s2/common-hal/ota/__init__.c | 8 ++++++-- shared-bindings/ota/__init__.c | 21 +++++++++++++++++---- shared-bindings/ota/__init__.h | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'shared-bindings') diff --git a/ports/esp32s2/common-hal/ota/__init__.c b/ports/esp32s2/common-hal/ota/__init__.c index 6d0e8f11b..97cc67b76 100644 --- a/ports/esp32s2/common-hal/ota/__init__.c +++ b/ports/esp32s2/common-hal/ota/__init__.c @@ -48,7 +48,7 @@ static void __attribute__((noreturn)) task_fatal_error(void) { mp_raise_RuntimeError(translate("OTA Update Failed")); } -void common_hal_ota_flash(const void *buf, const size_t len) { +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(); @@ -108,7 +108,11 @@ void common_hal_ota_flash(const void *buf, const size_t len) { } } - err = esp_ota_write( update_handle, buf, len); + 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(); diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c index 55858a80e..84a46c83a 100644 --- a/shared-bindings/ota/__init__.c +++ b/shared-bindings/ota/__init__.c @@ -36,14 +36,27 @@ STATIC mp_obj_t ota_finish(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(ota_finish_obj, ota_finish); -STATIC mp_obj_t ota_flash(mp_obj_t program_binary_in) { +STATIC mp_obj_t ota_flash(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_binary, ARG_offset }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_binary, 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 - 1, pos_args + 1, 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(program_binary_in, &bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[ARG_binary].u_obj, &bufinfo, MP_BUFFER_READ); - common_hal_ota_flash(bufinfo.buf, bufinfo.len); + common_hal_ota_flash(bufinfo.buf, bufinfo.len, args[ARG_offset].u_int); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ota_flash_obj, ota_flash); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ota_flash_obj, 1, 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) }, diff --git a/shared-bindings/ota/__init__.h b/shared-bindings/ota/__init__.h index 1765c21ad..9eec604e0 100644 --- a/shared-bindings/ota/__init__.h +++ b/shared-bindings/ota/__init__.h @@ -30,6 +30,6 @@ #include "py/runtime.h" extern void common_hal_ota_finish(void); -extern void common_hal_ota_flash(const void *buf, const size_t len); +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 07015ad527f81d81829190b31569a35a305676ce Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Thu, 10 Dec 2020 16:42:45 +0530 Subject: add ability to switch boot partition --- ports/esp32s2/common-hal/ota/__init__.c | 6 ++++++ shared-bindings/ota/__init__.c | 7 +++++++ shared-bindings/ota/__init__.h | 1 + 3 files changed, 14 insertions(+) (limited to 'shared-bindings') diff --git a/ports/esp32s2/common-hal/ota/__init__.c b/ports/esp32s2/common-hal/ota/__init__.c index 97cc67b76..4ec102131 100644 --- a/ports/esp32s2/common-hal/ota/__init__.c +++ b/ports/esp32s2/common-hal/ota/__init__.c @@ -141,3 +141,9 @@ void common_hal_ota_finish(void) { 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 partition")); + } +} diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c index 84a46c83a..46399dcb2 100644 --- a/shared-bindings/ota/__init__.c +++ b/shared-bindings/ota/__init__.c @@ -30,6 +30,12 @@ //| //| The `ota` module implements over-the-air update.""" +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); + STATIC mp_obj_t ota_finish(void) { common_hal_ota_finish(); return mp_const_none; @@ -60,6 +66,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ota_flash_obj, 1, 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) }, }; diff --git a/shared-bindings/ota/__init__.h b/shared-bindings/ota/__init__.h index 9eec604e0..82273f975 100644 --- a/shared-bindings/ota/__init__.h +++ b/shared-bindings/ota/__init__.h @@ -29,6 +29,7 @@ #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); -- cgit v1.2.3 From cb35abfd04762871283e0323bddf0904d27913ea Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Fri, 11 Dec 2020 01:01:01 +0530 Subject: add docs, update translation & fix ota.flash() --- locale/circuitpython.pot | 10 +++++++++- ports/esp32s2/common-hal/ota/__init__.c | 2 +- shared-bindings/ota/__init__.c | 23 ++++++++++++++++++----- 3 files changed, 28 insertions(+), 7 deletions(-) (limited to 'shared-bindings') diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 5bf95043a..214b7aad1 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-08 10:30+0530\n" +"POT-Creation-Date: 2020-12-10 16:56+0530\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1907,6 +1907,10 @@ 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 "" @@ -3198,6 +3202,10 @@ msgstr "" msgid "offset is too large" msgstr "" +#: shared-bindings/ota/__init__.c +msgid "offset must be >= 0" +msgstr "" + #: py/objstr.c py/objstrunicode.c msgid "offset out of bounds" msgstr "" diff --git a/ports/esp32s2/common-hal/ota/__init__.c b/ports/esp32s2/common-hal/ota/__init__.c index 40cfce676..5ea25fb5d 100644 --- a/ports/esp32s2/common-hal/ota/__init__.c +++ b/ports/esp32s2/common-hal/ota/__init__.c @@ -145,6 +145,6 @@ void common_hal_ota_finish(void) { 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 partition")); + mp_raise_RuntimeError(translate("Unable to switch boot partition")); } } diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c index 46399dcb2..03636779f 100644 --- a/shared-bindings/ota/__init__.c +++ b/shared-bindings/ota/__init__.c @@ -30,39 +30,52 @@ //| //| The `ota` module implements over-the-air update.""" +//| def switch() -> None: +//| """Switches the boot partition. +//| ... +//| 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** `ota.flash()` +//| ... +//| 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: WriteableBuffer, offset: int=0) -> None: +//| """Writes one of two OTA partition at the given offset. +//| ... +//| STATIC mp_obj_t ota_flash(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_binary, ARG_offset }; + enum { ARG_buffer, ARG_offset }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_binary, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { 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 - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, 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_binary].u_obj, &bufinfo, MP_BUFFER_READ); + 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, 1, ota_flash); +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) }, -- cgit v1.2.3 From 08e94e6a204708060860a9ed3b801bf3fb5b5ecc Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Fri, 11 Dec 2020 22:55:22 +0530 Subject: add more docs --- shared-bindings/ota/__init__.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'shared-bindings') diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c index 03636779f..152a8e802 100644 --- a/shared-bindings/ota/__init__.c +++ b/shared-bindings/ota/__init__.c @@ -26,12 +26,26 @@ #include "shared-bindings/ota/__init__.h" -//| """ota module +//| """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""" //| -//| The `ota` module implements over-the-air update.""" //| def switch() -> None: -//| """Switches the boot partition. +//| """Switches the boot partition.""" //| ... //| STATIC mp_obj_t ota_switch(void) { @@ -42,7 +56,7 @@ 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** `ota.flash()` +//| **Must be called after** `ota.flash()`""" //| ... //| STATIC mp_obj_t ota_finish(void) { @@ -52,7 +66,10 @@ STATIC mp_obj_t ota_finish(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(ota_finish_obj, ota_finish); //| def flash(*buffer: WriteableBuffer, offset: int=0) -> None: -//| """Writes one of two OTA partition at the given offset. +//| """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.""" //| ... //| STATIC mp_obj_t ota_flash(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { -- cgit v1.2.3 From 92098ca06b2d119db7810738ed7da262bdea5686 Mon Sep 17 00:00:00 2001 From: microDev <70126934+microDev1@users.noreply.github.com> Date: Sat, 12 Dec 2020 05:15:25 +0530 Subject: update docs, implement suggested changes --- shared-bindings/ota/__init__.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'shared-bindings') diff --git a/shared-bindings/ota/__init__.c b/shared-bindings/ota/__init__.c index 152a8e802..8ecc6d9c4 100644 --- a/shared-bindings/ota/__init__.c +++ b/shared-bindings/ota/__init__.c @@ -41,11 +41,24 @@ //| 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""" +//| 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.""" +//| """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) { @@ -56,7 +69,10 @@ 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** `ota.flash()`""" +//| **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) { @@ -65,11 +81,14 @@ STATIC mp_obj_t ota_finish(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(ota_finish_obj, ota_finish); -//| def flash(*buffer: WriteableBuffer, offset: int=0) -> None: +//| 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.""" +//| 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) { -- cgit v1.2.3 From 210c0ec89c88b50089067f74c2f0893fdd8613b4 Mon Sep 17 00:00:00 2001 From: BennyE Date: Sun, 13 Dec 2020 13:32:12 +0100 Subject: add country(code) to wifi network objects) --- ports/esp32s2/common-hal/wifi/Network.c | 6 ++++++ shared-bindings/wifi/Network.c | 17 +++++++++++++++++ shared-bindings/wifi/Network.h | 1 + shared-bindings/wifi/Radio.c | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) (limited to 'shared-bindings') diff --git a/ports/esp32s2/common-hal/wifi/Network.c b/ports/esp32s2/common-hal/wifi/Network.c index e90b3d552..ab60b98f4 100644 --- a/ports/esp32s2/common-hal/wifi/Network.c +++ b/ports/esp32s2/common-hal/wifi/Network.c @@ -48,3 +48,9 @@ mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self) { mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self) { return mp_obj_new_int(self->record.primary); } + +mp_obj_t common_hal_wifi_network_get_country(wifi_network_obj_t *self) { + const char* cstr = (const char*) self->record.country.cc; + return mp_obj_new_str(cstr, strlen(cstr)); +} + diff --git a/shared-bindings/wifi/Network.c b/shared-bindings/wifi/Network.c index bf970a9c0..009712ad1 100644 --- a/shared-bindings/wifi/Network.c +++ b/shared-bindings/wifi/Network.c @@ -108,12 +108,29 @@ const mp_obj_property_t wifi_network_channel_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| country: str +//| """String id of the country code""" +//| +STATIC mp_obj_t wifi_network_get_country(mp_obj_t self) { + return common_hal_wifi_network_get_country(self); + +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_country_obj, wifi_network_get_country); + +const mp_obj_property_t wifi_network_country_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&wifi_network_get_country_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + STATIC const mp_rom_map_elem_t wifi_network_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ssid), MP_ROM_PTR(&wifi_network_ssid_obj) }, { MP_ROM_QSTR(MP_QSTR_bssid), MP_ROM_PTR(&wifi_network_bssid_obj) }, { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&wifi_network_rssi_obj) }, { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wifi_network_channel_obj) }, + { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&wifi_network_country_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wifi_network_locals_dict, wifi_network_locals_dict_table); diff --git a/shared-bindings/wifi/Network.h b/shared-bindings/wifi/Network.h index c9bbc685e..e672e3108 100644 --- a/shared-bindings/wifi/Network.h +++ b/shared-bindings/wifi/Network.h @@ -39,5 +39,6 @@ extern mp_obj_t common_hal_wifi_network_get_ssid(wifi_network_obj_t *self); extern mp_obj_t common_hal_wifi_network_get_bssid(wifi_network_obj_t *self); extern mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self); extern mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self); +extern mp_obj_t common_hal_wifi_network_get_country(wifi_network_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_NETWORK_H diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index edbd9fd2f..723572a32 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -295,7 +295,7 @@ const mp_obj_property_t wifi_radio_ipv4_dns_obj = { }; //| ap_info: Optional[Network] -//| """Network object containing BSSID, SSID, channel, and RSSI when connected to an access point. None otherwise.""" +//| """Network object containing BSSID, SSID, channel, country and RSSI when connected to an access point. None otherwise.""" //| STATIC mp_obj_t wifi_radio_get_ap_info(mp_obj_t self) { return common_hal_wifi_radio_get_ap_info(self); -- 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 'shared-bindings') 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 'shared-bindings') 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 6c4df5a8b45c6b20e00b5499c5db1d4f5da444a2 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 18 Dec 2020 11:13:28 -0600 Subject: adafruit_bus_device: Don't transmit STOP condition in write_then_readinto Closes #3795 --- shared-bindings/adafruit_bus_device/I2CDevice.c | 8 ++++---- shared-bindings/adafruit_bus_device/I2CDevice.h | 2 +- shared-module/adafruit_bus_device/I2CDevice.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'shared-bindings') diff --git a/shared-bindings/adafruit_bus_device/I2CDevice.c b/shared-bindings/adafruit_bus_device/I2CDevice.c index 4c9086162..a4c04e198 100644 --- a/shared-bindings/adafruit_bus_device/I2CDevice.c +++ b/shared-bindings/adafruit_bus_device/I2CDevice.c @@ -163,7 +163,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_readinto_obj, 2, //| """ //| ... //| -STATIC void write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end) { +STATIC void write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, int32_t start, mp_int_t end, bool transmit_stop_bit) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ); @@ -173,7 +173,7 @@ STATIC void write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, in mp_raise_ValueError(translate("Buffer must be at least length 1")); } - uint8_t status = common_hal_adafruit_bus_device_i2cdevice_write(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length); + uint8_t status = common_hal_adafruit_bus_device_i2cdevice_write(MP_OBJ_TO_PTR(self), ((uint8_t*)bufinfo.buf) + start, length, transmit_stop_bit); if (status != 0) { mp_raise_OSError(status); } @@ -191,7 +191,7 @@ STATIC mp_obj_t adafruit_bus_device_i2cdevice_write(size_t n_args, const mp_obj_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - write(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int); + write(self, args[ARG_buffer].u_obj, args[ARG_start].u_int, args[ARG_end].u_int, true); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_obj, 2, adafruit_bus_device_i2cdevice_write); @@ -233,7 +233,7 @@ STATIC mp_obj_t adafruit_bus_device_i2cdevice_write_then_readinto(size_t n_args, mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - write(self, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int, args[ARG_out_end].u_int); + write(self, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int, args[ARG_out_end].u_int, false); readinto(self, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int, args[ARG_in_end].u_int); diff --git a/shared-bindings/adafruit_bus_device/I2CDevice.h b/shared-bindings/adafruit_bus_device/I2CDevice.h index 7b2182ff0..cf7b1321a 100644 --- a/shared-bindings/adafruit_bus_device/I2CDevice.h +++ b/shared-bindings/adafruit_bus_device/I2CDevice.h @@ -45,7 +45,7 @@ extern const mp_obj_type_t adafruit_bus_device_i2cdevice_type; // Initializes the hardware peripheral. extern void common_hal_adafruit_bus_device_i2cdevice_construct(adafruit_bus_device_i2cdevice_obj_t *self, busio_i2c_obj_t *i2c, uint8_t device_address); extern uint8_t common_hal_adafruit_bus_device_i2cdevice_readinto(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); -extern uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length); +extern uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length, bool transmit_stop_bit); extern void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice_obj_t *self); extern void common_hal_adafruit_bus_device_i2cdevice_unlock(adafruit_bus_device_i2cdevice_obj_t *self); extern void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self); diff --git a/shared-module/adafruit_bus_device/I2CDevice.c b/shared-module/adafruit_bus_device/I2CDevice.c index ee4b4fa55..83abe80d6 100644 --- a/shared-module/adafruit_bus_device/I2CDevice.c +++ b/shared-module/adafruit_bus_device/I2CDevice.c @@ -57,8 +57,8 @@ uint8_t common_hal_adafruit_bus_device_i2cdevice_readinto(adafruit_bus_device_i2 return common_hal_busio_i2c_read(self->i2c, self->device_address, buffer, length); } -uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length) { - return common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, true); +uint8_t common_hal_adafruit_bus_device_i2cdevice_write(adafruit_bus_device_i2cdevice_obj_t *self, mp_obj_t buffer, size_t length, bool transmit_stop_bit) { + return common_hal_busio_i2c_write(self->i2c, self->device_address, buffer, length, transmit_stop_bit); } void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self) { -- cgit v1.2.3 From d4e9eea397c887d9eceb5f4c6aba117a4dc3d03b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 22 Dec 2020 10:06:43 -0500 Subject: mark alarm.wake_alarm during gc sweep --- main.c | 4 ++++ ports/esp32s2/common-hal/alarm/__init__.c | 8 ++++++-- shared-bindings/alarm/__init__.c | 13 ++++++++++++- shared-bindings/alarm/__init__.h | 8 ++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) (limited to 'shared-bindings') diff --git a/main.c b/main.c index d940f93d1..27ed6ff11 100755 --- a/main.c +++ b/main.c @@ -613,6 +613,10 @@ void gc_collect(void) { background_callback_gc_collect(); + #if CIRCUITPY_ALARM + common_hal_alarm_gc_collect(); + #endif + #if CIRCUITPY_DISPLAYIO displayio_gc_collect(); #endif diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 5d1f3e95d..9f19f1afc 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -25,10 +25,12 @@ * THE SOFTWARE. */ +#include "py/gc.h" #include "py/obj.h" #include "py/objtuple.h" #include "py/runtime.h" +#include "shared-bindings/alarm/__init__.h" #include "shared-bindings/alarm/pin/PinAlarm.h" #include "shared-bindings/alarm/SleepMemory.h" #include "shared-bindings/alarm/time/TimeAlarm.h" @@ -38,8 +40,6 @@ #include "supervisor/port.h" #include "supervisor/shared/workflow.h" -#include "common-hal/alarm/__init__.h" - #include "esp_sleep.h" #include "components/soc/soc/esp32s2/include/soc/rtc_cntl_reg.h" @@ -159,3 +159,7 @@ void NORETURN alarm_enter_deep_sleep(void) { // We don't need to worry about resetting them in the interim. esp_deep_sleep_start(); } + +void common_hal_alarm_gc_collect(void) { + gc_collect_ptr(alarm_get_wake_alarm()); +} diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 700fe020e..778674f6d 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -199,7 +199,18 @@ 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) }, }; -STATIC MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); +MP_DEFINE_MUTABLE_DICT(alarm_module_globals, alarm_module_globals_table); + +// Fetch value from module dict. +mp_obj_t alarm_get_wake_alarm(void) { + mp_map_elem_t *elem = + mp_map_lookup(&alarm_module_globals.map, MP_ROM_QSTR(MP_QSTR_wake_alarm), MP_MAP_LOOKUP); + if (elem) { + return elem->value; + } else { + return NULL; + } +} STATIC void alarm_set_wake_alarm(mp_obj_t alarm) { // Equivalent of: diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index 8c4b6cad9..a90405da6 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -31,6 +31,9 @@ #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 @@ -43,6 +46,10 @@ extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj // Deep sleep is entered outside of the VM so we omit the `common_hal_` prefix. extern NORETURN void alarm_enter_deep_sleep(void); +// Fetches value from module dict. +extern mp_obj_t alarm_get_wake_alarm(void); + +extern void common_hal_alarm_gc_collect(void); extern mp_obj_t common_hal_alarm_get_wake_alarm(void); // Used by wake-up code. @@ -52,4 +59,5 @@ void alarm_save_wakeup_alarm(void); // True if an alarm is alerting. This is most useful for pretend deep sleep. extern bool alarm_woken_from_sleep(void); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_ALARM___INIT___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 'shared-bindings') 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 a11ad2572761bc4900994fbf42361efb387cd059 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 21 Dec 2020 22:58:17 -0500 Subject: BLE fixes --- ports/nrf/common-hal/_bleio/Adapter.c | 11 ++++++++++- shared-bindings/_bleio/Adapter.c | 13 ++++++++++--- shared-bindings/_bleio/Characteristic.c | 4 ++-- shared-bindings/_bleio/Descriptor.c | 4 ++-- 4 files changed, 24 insertions(+), 8 deletions(-) (limited to 'shared-bindings') diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 537f43f23..53a40f9a6 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -470,7 +470,16 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* ble_drv_add_event_handler(scan_on_ble_evt, self->scan_results); uint32_t nrf_timeout = SEC_TO_UNITS(timeout, UNIT_10_MS); - if (timeout <= 0.0001) { + if (nrf_timeout > UINT16_MAX) { + // 0xffff / 100 + mp_raise_ValueError(translate("timeout must be < 655.35 secs")); + } + if (nrf_timeout == 0 && timeout > 0.0f) { + // Make sure converted timeout is > 0 if original timeout is > 0. + mp_raise_ValueError(translate("non-zero timeout must be > 0.01")); + } + + if (nrf_timeout) { nrf_timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED; } diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 682177093..7d7076aab 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -33,8 +33,8 @@ #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Adapter.h" -#define ADV_INTERVAL_MIN (0.0020f) -#define ADV_INTERVAL_MIN_STRING "0.0020" +#define ADV_INTERVAL_MIN (0.02001f) +#define ADV_INTERVAL_MIN_STRING "0.02001" #define ADV_INTERVAL_MAX (10.24f) #define ADV_INTERVAL_MAX_STRING "10.24" // 20ms is recommended by Apple @@ -307,7 +307,7 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - mp_float_t timeout = 0; + mp_float_t timeout = 0.0f; if (args[ARG_timeout].u_obj != mp_const_none) { timeout = mp_obj_get_float(args[ARG_timeout].u_obj); } @@ -325,6 +325,13 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + if (timeout != 0.0f && timeout < interval) { + mp_raise_ValueError(translate("non-zero timeout must be >= interval")); + } +#pragma GCC diagnostic pop + const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj); if (window > interval) { mp_raise_ValueError(translate("window must be <= interval")); diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index 5e384a44c..a0751b7e3 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -110,8 +110,8 @@ STATIC mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ common_hal_bleio_attribute_security_mode_check_valid(write_perm); const mp_int_t max_length_int = args[ARG_max_length].u_int; - if (max_length_int <= 0) { - mp_raise_ValueError(translate("max_length must be > 0")); + if (max_length_int < 0) { + mp_raise_ValueError(translate("max_length must be >= 0")); } const size_t max_length = (size_t) max_length_int; const bool fixed_length = args[ARG_fixed_length].u_bool; diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index c313007c6..60f0acf44 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -101,8 +101,8 @@ STATIC mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o common_hal_bleio_attribute_security_mode_check_valid(write_perm); const mp_int_t max_length_int = args[ARG_max_length].u_int; - if (max_length_int <= 0) { - mp_raise_ValueError(translate("max_length must be > 0")); + if (max_length_int < 0) { + mp_raise_ValueError(translate("max_length must be >= 0")); } const size_t max_length = (size_t) max_length_int; const bool fixed_length = args[ARG_fixed_length].u_bool; -- cgit v1.2.3