From 1ae7e0e561134c39471e3000eced33da732b4103 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Tue, 31 Mar 2020 16:03:01 -0700 Subject: [PATCH] esp32: Consolidate check_esp_err functions and add IDF error string. This commit consolidates a number of check_esp_err functions that check whether an ESP-IDF return code is OK and raises an exception if not. The exception raised is an OSError with the error code as the first argument (negative if it's ESP-IDF specific) and the ESP-IDF error string as the second argument. This commit also fixes esp32.Partition.set_boot to use check_esp_err, and uses that function for a unit test. --- ports/esp32/esp32_partition.c | 9 ++----- ports/esp32/esp32_rmt.c | 11 -------- ports/esp32/machine_sdcard.c | 18 ------------- ports/esp32/machine_timer.c | 8 ------ ports/esp32/mphalport.c | 33 ++++++++++++++++++++++++ ports/esp32/mphalport.h | 3 +++ tests/esp32/check_err_str.py | 43 ++++++++++++++++++++++++++++++++ tests/esp32/check_err_str.py.exp | 4 +++ 8 files changed, 85 insertions(+), 44 deletions(-) create mode 100644 tests/esp32/check_err_str.py create mode 100644 tests/esp32/check_err_str.py.exp diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c index a1aa8c9dde..cbb62206fa 100644 --- a/ports/esp32/esp32_partition.c +++ b/ports/esp32/esp32_partition.c @@ -29,6 +29,7 @@ #include "py/runtime.h" #include "py/mperrno.h" #include "extmod/vfs.h" +#include "mphalport.h" #include "modesp32.h" #include "esp_ota_ops.h" @@ -47,12 +48,6 @@ typedef struct _esp32_partition_obj_t { const esp_partition_t *part; } esp32_partition_obj_t; -static inline void check_esp_err(esp_err_t e) { - if (e != ESP_OK) { - mp_raise_OSError(-e); - } -} - STATIC esp32_partition_obj_t *esp32_partition_new(const esp_partition_t *part) { if (part == NULL) { mp_raise_OSError(MP_ENOENT); @@ -203,7 +198,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_partition_ioctl_obj, esp32_partition_ioct STATIC mp_obj_t esp32_partition_set_boot(mp_obj_t self_in) { esp32_partition_obj_t *self = MP_OBJ_TO_PTR(self_in); - esp_ota_set_boot_partition(self->part); + check_esp_err(esp_ota_set_boot_partition(self->part)); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_partition_set_boot_obj, esp32_partition_set_boot); diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c index 7998752661..25b7b38089 100644 --- a/ports/esp32/esp32_rmt.c +++ b/ports/esp32/esp32_rmt.c @@ -56,17 +56,6 @@ typedef struct _esp32_rmt_obj_t { rmt_item32_t *items; } esp32_rmt_obj_t; -// Defined in machine_time.c; simply added the error message -// Fixme: Should use this updated error hadline more widely in the ESP32 port. -// At least update the method in machine_time.c. -STATIC esp_err_t check_esp_err(esp_err_t code) { - if (code) { - mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t)esp_err_to_name(code)); - } - - return code; -} - STATIC mp_obj_t esp32_rmt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} }, diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c index 6383728ced..0fd4e86211 100644 --- a/ports/esp32/machine_sdcard.c +++ b/ports/esp32/machine_sdcard.c @@ -71,24 +71,6 @@ typedef struct _sdcard_obj_t { #define _SECTOR_SIZE(self) (self->card.csd.sector_size) -STATIC esp_err_t check_esp_err(esp_err_t code) { - switch (code) { - case ESP_OK: - return ESP_OK; - case ESP_ERR_NO_MEM: - code = MP_ENOMEM; - break; - case ESP_ERR_TIMEOUT: - code = MP_ETIMEDOUT; - break; - case ESP_ERR_NOT_SUPPORTED: - code = MP_EOPNOTSUPP; - break; - } - - mp_raise_OSError(code); -} - STATIC gpio_num_t pin_or_int(const mp_obj_t arg) { if (mp_obj_is_small_int(arg)) { return MP_OBJ_SMALL_INT_VALUE(arg); diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c index a4662c3c72..6e5824094e 100644 --- a/ports/esp32/machine_timer.c +++ b/ports/esp32/machine_timer.c @@ -64,14 +64,6 @@ const mp_obj_type_t machine_timer_type; STATIC void machine_timer_disable(machine_timer_obj_t *self); -STATIC esp_err_t check_esp_err(esp_err_t code) { - if (code) { - mp_raise_OSError(code); - } - - return code; -} - void machine_timer_deinit_all(void) { // Disable, deallocate and remove all timers from list machine_timer_obj_t **t = &MP_STATE_PORT(machine_timer_obj_head); diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c index c701cb4bcb..4f7785f24e 100644 --- a/ports/esp32/mphalport.c +++ b/ports/esp32/mphalport.c @@ -39,6 +39,7 @@ #endif #include "py/obj.h" +#include "py/objstr.h" #include "py/stream.h" #include "py/mpstate.h" #include "py/mphal.h" @@ -51,6 +52,38 @@ TaskHandle_t mp_main_task_handle; STATIC uint8_t stdin_ringbuf_array[256]; ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array)}; +// Check the ESP-IDF error code and raise an OSError if it's not ESP_OK. +void check_esp_err(esp_err_t code) { + if (code != ESP_OK) { + // map esp-idf error code to posix error code + uint32_t pcode = -code; + switch (code) { + case ESP_ERR_NO_MEM: + pcode = MP_ENOMEM; + break; + case ESP_ERR_TIMEOUT: + pcode = MP_ETIMEDOUT; + break; + case ESP_ERR_NOT_SUPPORTED: + pcode = MP_EOPNOTSUPP; + break; + } + // construct string object + mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); + if (o_str == NULL) { + mp_raise_OSError(pcode); + return; + } + o_str->base.type = &mp_type_str; + o_str->data = (const byte *)esp_err_to_name(code); // esp_err_to_name ret's ptr to const str + o_str->len = strlen((char *)o_str->data); + o_str->hash = qstr_compute_hash(o_str->data, o_str->len); + // raise + mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(pcode), MP_OBJ_FROM_PTR(o_str)}; + nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args)); + } +} + uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t ret = 0; if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) { diff --git a/ports/esp32/mphalport.h b/ports/esp32/mphalport.h index 7cee3fb8a4..1f78d820a3 100644 --- a/ports/esp32/mphalport.h +++ b/ports/esp32/mphalport.h @@ -42,6 +42,9 @@ extern TaskHandle_t mp_main_task_handle; extern ringbuf_t stdin_ringbuf; +// Check the ESP-IDF error code and raise an OSError if it's not ESP_OK. +void check_esp_err(esp_err_t code); + uint32_t mp_hal_ticks_us(void); __attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) { uint32_t ccount; diff --git a/tests/esp32/check_err_str.py b/tests/esp32/check_err_str.py new file mode 100644 index 0000000000..055eecf747 --- /dev/null +++ b/tests/esp32/check_err_str.py @@ -0,0 +1,43 @@ +try: + from esp32 import Partition as p + import micropython +except ImportError: + print("SKIP") + raise SystemExit + +# try some vanilla OSError to get std error code +try: + open("this filedoesnotexist", "r") + print("FAILED TO RAISE") +except OSError as e: + print(e) + +# try to make nvs partition bootable, which ain't gonna work +part = p.find(type=p.TYPE_DATA)[0] +fun = p.set_boot +try: + fun(part) + print("FAILED TO RAISE") +except OSError as e: + print(e) + +# same but with out of memory condition by locking the heap +exc = "FAILED TO RAISE" +micropython.heap_lock() +try: + fun(part) +except OSError as e: + exc = e +micropython.heap_unlock() +print("exc:", exc) # exc empty due to no memory + +# same again but having an emergency buffer +micropython.alloc_emergency_exception_buf(256) +exc = "FAILED TO RAISE" +micropython.heap_lock() +try: + fun(part) +except Exception as e: + exc = e +micropython.heap_unlock() +print(exc) diff --git a/tests/esp32/check_err_str.py.exp b/tests/esp32/check_err_str.py.exp new file mode 100644 index 0000000000..d4162d1be0 --- /dev/null +++ b/tests/esp32/check_err_str.py.exp @@ -0,0 +1,4 @@ +[Errno 2] ENOENT +(-5379, 'ESP_ERR_OTA_VALIDATE_FAILED') +exc: +-5379