From 27c7807693954ade239814c3a02a8ac10be7bb7b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 13 Aug 2023 19:05:09 -0400 Subject: [PATCH] silabs build needs work; other builds are working --- extmod/misc.h | 48 +++ extmod/ulab | 2 +- ports/atmel-samd/Makefile | 5 - ports/broadcom/Makefile | 6 - ports/cxd56/Makefile | 5 - ports/espressif/Makefile | 5 - ports/litex/Makefile | 5 - ports/mimxrt10xx/Makefile | 5 - ports/nrf/Makefile | 5 - ports/nrf/common-hal/busio/UART.c | 2 +- ports/raspberrypi/Makefile | 5 - ports/silabs/Makefile | 48 +-- .../boards/devkit_xg24_brd2601b/sensor.c | 3 +- ports/silabs/common-hal/_bleio/__init__.c | 2 +- ports/silabs/common-hal/busio/UART.c | 2 +- ports/stm/Makefile | 5 - ports/unix/main.c | 3 + ports/unix/modffi.c | 25 +- ports/unix/modos.c | 395 ++++++++++++++++++ ports/unix/moduos_vfs.c | 98 +++++ ports/unix/mpconfigport.h | 14 + ports/unix/mpconfigport.mk | 6 +- ports/unix/unix_mphal.c | 54 +++ py/mkrules.mk | 5 + py/modsys.c | 3 +- py/objexcept.c | 169 ++++++++ supervisor/shared/background_callback.c | 2 +- 27 files changed, 834 insertions(+), 93 deletions(-) create mode 100644 extmod/misc.h create mode 100644 ports/unix/modos.c create mode 100644 ports/unix/moduos_vfs.c diff --git a/extmod/misc.h b/extmod/misc.h new file mode 100644 index 0000000000..a9392aa10b --- /dev/null +++ b/extmod/misc.h @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014-2016 Damien P. George + * Copyright (c) 2016 Paul Sokolovsky + * + * 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_EXTMOD_MISC_H +#define MICROPY_INCLUDED_EXTMOD_MISC_H + +// This file contains cumulative declarations for extmod/ . + +#include +#include "py/runtime.h" + +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj); + +#if MICROPY_PY_OS_DUPTERM +bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream); +void mp_uos_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached); +uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags); +int mp_uos_dupterm_rx_chr(void); +void mp_uos_dupterm_tx_strn(const char *str, size_t len); +void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc); +#else +#define mp_uos_dupterm_tx_strn(s, l) +#endif + +#endif // MICROPY_INCLUDED_EXTMOD_MISC_H diff --git a/extmod/ulab b/extmod/ulab index 6619c20b3b..a05ec05351 160000 --- a/extmod/ulab +++ b/extmod/ulab @@ -1 +1 @@ -Subproject commit 6619c20b3b75864554fcee5f88846fac27df5701 +Subproject commit a05ec05351260cf48fefc347265b8d8bf29c03f1 diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index d732e7a9b2..0f01c789c6 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -387,8 +387,3 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(Q)$(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^ include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/broadcom/Makefile b/ports/broadcom/Makefile index 9af0503fbb..bbafa26751 100644 --- a/ports/broadcom/Makefile +++ b/ports/broadcom/Makefile @@ -172,9 +172,3 @@ $(BUILD)/firmware.disk.img.zip: $(BUILD)/kernel$(SUFFIX).img $(Q)rm $(BUILD)/circuitpython-disk.img include $(TOP)/py/mkrules.mk - - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/cxd56/Makefile b/ports/cxd56/Makefile index 2fbb599c25..0e3a34af99 100644 --- a/ports/cxd56/Makefile +++ b/ports/cxd56/Makefile @@ -200,8 +200,3 @@ flash-bootloader: $(SPRESENSE_SDK) $(FIRMWARE) tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $(BOOTLOADER_FILES) include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index 10ac738cac..288c24f1f5 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -484,8 +484,3 @@ monitor: $(BUILD)/firmware.elf idf.py monitor -p $(PORT) include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/litex/Makefile b/ports/litex/Makefile index 47a18781f9..ce7805d067 100644 --- a/ports/litex/Makefile +++ b/ports/litex/Makefile @@ -157,8 +157,3 @@ $(BUILD)/firmware.dfu: $(BUILD)/firmware.bin $(PYTHON) $(TOP)/tools/dfu.py -b $^ -D 0x1209:0x5bf0 "$(BUILD)/firmware.dfu" include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/mimxrt10xx/Makefile b/ports/mimxrt10xx/Makefile index c591cf189e..ddf51413a9 100644 --- a/ports/mimxrt10xx/Makefile +++ b/ports/mimxrt10xx/Makefile @@ -224,11 +224,6 @@ $(BUILD)/firmware.hex: $(BUILD)/firmware.elf include $(TOP)/py/mkrules.mk -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) - ifeq ($(CHIP_FAMILY), MIMXRT1062) PYOCD_TARGET = mimxrt1060 endif diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 8a8625bd95..5829b465a6 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -313,8 +313,3 @@ $(BUILD)/firmware.espruino.zip: $(BUILD)/firmware.hex espruino-dfu-gen: $(BUILD)/firmware.espruino.zip include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 012ca894fe..4bd5807fc0 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -346,7 +346,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, if (!nrfx_is_in_ram(data)) { // Allocate long strings on the heap. if (len > 128 && gc_alloc_possible()) { - tx_buf = (uint8_t *)m_m_alloc(len); + tx_buf = (uint8_t *)m_malloc(len); } else { tx_buf = alloca(len); } diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index 7eb67b77ba..062c65e491 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -453,8 +453,3 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(Q)$(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xe48bff56 -b 0x10000000 -c -o $@ $^ include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/silabs/Makefile b/ports/silabs/Makefile index 66749b4320..8fd43067f1 100644 --- a/ports/silabs/Makefile +++ b/ports/silabs/Makefile @@ -38,8 +38,6 @@ PY_GEN_PINS_SRC ?= tools/make_pins.py # SLC tool path SLC_PATH = $(realpath $(CURDIR))/tools/slc_cli_linux -BUILD_VERBOSE ?= 1 - CFLAGS = $(INCLUDES) $(C_DEFS) $(C_FLAGS) \ -Wno-expansion-to-defined \ -Wno-unused-parameter \ @@ -95,23 +93,18 @@ endif SRC_S = boards/mp_efr32xg24_gchelper.s SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) + $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ + $(addprefix common-hal/, $(SRC_COMMON_HAL)) SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) + $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ + $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) # There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, # because a few modules have files both in common-hal/ and shared-module/. # Doing a $(sort ...) removes duplicates as part of sorting. SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) -ifneq ($(FROZEN_MPY_DIR),) -FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') -FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) -endif - OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) ifeq ($(INTERNAL_LIBM),1) @@ -181,38 +174,37 @@ endif @sed -i 's/ autogen\// $(SILABS_BUILD)\/autogen\//g' $(SILABS_BUILD)/circuitpython_efr32.project.mak @sed -i 's/-T"autogen\//-T"$(SILABS_BUILD)\/autogen\//g' $(SILABS_BUILD)/circuitpython_efr32.project.mak -#Override ECHO +# tools/slc_cli_linux/bin/slc-cli/developer/exporter_templates/arm_gcc/arm_gcc.Makefile defines +# ECHO = @ +# which is not compatible with py/mkenv.mk: +# ECHO = @echo +# so override ECHO $(OBJS): ECHO = -$(OBJS): +#$(OBJS): $(OUTPUT_DIR)/%.o: %.c - @echo 'Building $<' + #@echo 'Building $<' @$(MKDIR_P) $(@D) - $(ECHO)$(CC) $(CFLAGS) -c -o $@ $< + @$(CC) $(CFLAGS) -c -o $@ $< $(OUTPUT_DIR)/%.o: %.cpp - @echo 'Building $<' + #@echo 'Building $<' @$(MKDIR_P) $(@D) - $(ECHO)$(CXX) $(CXXFLAGS) -c -o $@ $< + @$(CXX) $(CXXFLAGS) -c -o $@ $< $(OUTPUT_DIR)/%.o: %.cc - @echo 'Building $<' + #@echo 'Building $<' @$(MKDIR_P) $(@D) - $(ECHO)$(CXX) $(CXXFLAGS) -c -o $@ $< + @$(CXX) $(CXXFLAGS) -c -o $@ $< $(OUTPUT_DIR)/%.o: %.s - @echo 'Building $<' + #@echo 'Building $<' @$(MKDIR_P) $(@D) - $(ECHO)$(CC) $(ASMFLAGS) -c -o $@ $< + @$(CC) $(ASMFLAGS) -c -o $@ $< $(OUTPUT_DIR)/%.o: %.S - @echo 'Building $<' + #@echo 'Building $<' @$(MKDIR_P) $(@D) - $(ECHO)$(CC) $(ASMFLAGS) -c -o $@ $< + @$(CC) $(ASMFLAGS) -c -o $@ $< include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c b/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c index 55011e556a..2b0bf9b0bd 100644 --- a/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c +++ b/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c @@ -37,7 +37,8 @@ #include "sl_sensor_hall.h" #include "sl_sensor_pressure.h" -STATIC mp_obj_t sensor_init(busio_i2c_obj_t *i2c) { +STATIC mp_obj_t sensor_init(mp_obj_t i2c_in) { + // busio_i2c_obj_t *i2c = MP_OBJ_TO_PTR(i2c_in); sl_status_t sc; if (!common_hal_mcu_pin_is_free(&pin_PC9)) { diff --git a/ports/silabs/common-hal/_bleio/__init__.c b/ports/silabs/common-hal/_bleio/__init__.c index 8b85f9ed6b..a1f8927c8f 100644 --- a/ports/silabs/common-hal/_bleio/__init__.c +++ b/ports/silabs/common-hal/_bleio/__init__.c @@ -183,7 +183,7 @@ void sl_bt_on_event(sl_bt_msg_t *evt) { osMutexAcquire(bluetooth_connection_mutex_id, osWaitForever); connection = bleio_conn_handle_to_connection( evt->data.evt_gatt_service.connection); - service = m_new_obj(bleio_service_obj_t, &bleio_service_type); + service = mp_obj_malloc(bleio_service_obj_t, &bleio_service_type); bleio_service_from_connection(service, bleio_connection_new_from_internal(connection)); service->is_remote = true; diff --git a/ports/silabs/common-hal/busio/UART.c b/ports/silabs/common-hal/busio/UART.c index 8b1883d906..e066d3f732 100644 --- a/ports/silabs/common-hal/busio/UART.c +++ b/ports/silabs/common-hal/busio/UART.c @@ -123,7 +123,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, if (receiver_buffer != NULL) { ringbuf_init(&self->ringbuf, receiver_buffer, receiver_buffer_size); } else { - if (!ringbuf_alloc(&self->ringbuf, receiver_buffer_size, true)) { + if (!ringbuf_alloc(&self->ringbuf, receiver_buffer_size)) { m_malloc_fail(receiver_buffer_size); } } diff --git a/ports/stm/Makefile b/ports/stm/Makefile index b9709d0c2e..f8ac985ab9 100755 --- a/ports/stm/Makefile +++ b/ports/stm/Makefile @@ -291,8 +291,3 @@ flash: $(BUILD)/firmware.bin dfu-util -a 0 --dfuse-address $(BOOTLOADER_OFFSET) -D $(BUILD)/firmware.bin include $(TOP)/py/mkrules.mk - -# Print out the value of a make variable. -# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -print-%: - @echo $* = $($*) diff --git a/ports/unix/main.c b/ports/unix/main.c index 959640dc8c..28a733d191 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -67,6 +67,9 @@ STATIC void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t ret; MP_HAL_RETRY_SYSCALL(ret, write(STDERR_FILENO, str, len), {}); + #if MICROPY_PY_OS_DUPTERM + mp_uos_dupterm_tx_strn(str, len); + #endif } const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index 6ea3d29fd2..468006ba5d 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -505,19 +505,22 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } else if (mp_obj_is_str(a)) { const char *s = mp_obj_str_get_str(a); values[i].ffi = (ffi_arg)(intptr_t)s; - } else if (((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type->buffer_p.get_buffer != NULL) { - mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(a); - mp_buffer_info_t bufinfo; - int ret = o->type->buffer_p.get_buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? - if (ret != 0) { + } else { + mp_getbuffer_fun_t get_buffer = mp_type_get_getbuffer_slot(((mp_obj_base_t *)MP_OBJ_TO_PTR(a))->type); + if (get_buffer != NULL) { + mp_obj_base_t *o = (mp_obj_base_t *)MP_OBJ_TO_PTR(a); + mp_buffer_info_t bufinfo; + int ret = get_buffer(MP_OBJ_FROM_PTR(o), &bufinfo, MP_BUFFER_READ); // TODO: MP_BUFFER_READ? + if (ret != 0) { + goto error; + } + values[i].ffi = (ffi_arg)(intptr_t)bufinfo.buf; + } else if (mp_obj_is_type(a, &fficallback_type)) { + mp_obj_fficallback_t *p = MP_OBJ_TO_PTR(a); + values[i].ffi = (ffi_arg)(intptr_t)p->func; + } else { goto error; } - values[i].ffi = (ffi_arg)(intptr_t)bufinfo.buf; - } else if (mp_obj_is_type(a, &fficallback_type)) { - mp_obj_fficallback_t *p = MP_OBJ_TO_PTR(a); - values[i].ffi = (ffi_arg)(intptr_t)p->func; - } else { - goto error; } valueptrs[i] = &values[i]; } diff --git a/ports/unix/modos.c b/ports/unix/modos.c new file mode 100644 index 0000000000..8373c07a5c --- /dev/null +++ b/ports/unix/modos.c @@ -0,0 +1,395 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2018 Paul Sokolovsky + * SPDX-FileCopyrightText: Copyright (c) 2014-2018 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _MSC_VER +#include // For mkdir +#endif +#include "py/mpconfig.h" + +#include "py/runtime.h" +#include "py/objtuple.h" +#include "py/mphal.h" +#include "py/mpthread.h" +#include "extmod/vfs.h" + +#ifdef __ANDROID__ +#define USE_STATFS 1 +#endif + +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 25) +#include +#define _HAVE_GETRANDOM +#endif +#endif + +#if defined(MICROPY_UNIX_COVERAGE) +#include "py/objstr.h" +typedef int os_getenv_err_t; +mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_); +os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); +os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value); +#endif + +STATIC mp_obj_t mod_os_urandom(mp_obj_t num) { + mp_int_t n = mp_obj_get_int(num); + vstr_t vstr; + vstr_init_len(&vstr, n); + #ifdef _HAVE_GETRANDOM + RAISE_ERRNO(getrandom(vstr.buf, n, 0), errno); + #else + int fd = open("/dev/urandom", O_RDONLY); + RAISE_ERRNO(fd, errno); + RAISE_ERRNO(read(fd, vstr.buf, n), errno); + close(fd); + #endif + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_urandom_obj, mod_os_urandom); + +STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) { + struct stat sb; + const char *path = mp_obj_str_get_str(path_in); + + int res; + MP_HAL_RETRY_SYSCALL(res, stat(path, &sb), mp_raise_OSError(err)); + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.st_mode); + t->items[1] = mp_obj_new_int_from_uint(sb.st_ino); + t->items[2] = mp_obj_new_int_from_uint(sb.st_dev); + t->items[3] = mp_obj_new_int_from_uint(sb.st_nlink); + t->items[4] = mp_obj_new_int_from_uint(sb.st_uid); + t->items[5] = mp_obj_new_int_from_uint(sb.st_gid); + t->items[6] = mp_obj_new_int_from_uint(sb.st_size); + t->items[7] = mp_obj_new_int_from_uint(sb.st_atime); + t->items[8] = mp_obj_new_int_from_uint(sb.st_mtime); + t->items[9] = mp_obj_new_int_from_uint(sb.st_ctime); + return MP_OBJ_FROM_PTR(t); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat); + +#if MICROPY_PY_OS_STATVFS + +#if USE_STATFS +#include +#define STRUCT_STATVFS struct statfs +#define STATVFS statfs +#define F_FAVAIL sb.f_ffree +#define F_NAMEMAX sb.f_namelen +#define F_FLAG sb.f_flags +#else +#include +#define STRUCT_STATVFS struct statvfs +#define STATVFS statvfs +#define F_FAVAIL sb.f_favail +#define F_NAMEMAX sb.f_namemax +#define F_FLAG sb.f_flag +#endif + +STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) { + STRUCT_STATVFS sb; + const char *path = mp_obj_str_get_str(path_in); + + int res; + MP_HAL_RETRY_SYSCALL(res, STATVFS(path, &sb), mp_raise_OSError(err)); + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize); + t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.f_frsize); + t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.f_blocks); + t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.f_bfree); + t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.f_bavail); + t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.f_files); + t->items[6] = MP_OBJ_NEW_SMALL_INT(sb.f_ffree); + t->items[7] = MP_OBJ_NEW_SMALL_INT(F_FAVAIL); + t->items[8] = MP_OBJ_NEW_SMALL_INT(F_FLAG); + t->items[9] = MP_OBJ_NEW_SMALL_INT(F_NAMEMAX); + return MP_OBJ_FROM_PTR(t); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_statvfs_obj, mod_os_statvfs); +#endif + +STATIC mp_obj_t mod_os_remove(mp_obj_t path_in) { + const char *path = mp_obj_str_get_str(path_in); + + // Note that POSIX requires remove() to be able to delete a directory + // too (act as rmdir()). This is POSIX extension to ANSI C semantics + // of that function. But Python remove() follows ANSI C, and explicitly + // required to raise exception on attempt to remove a directory. Thus, + // call POSIX unlink() here. + MP_THREAD_GIL_EXIT(); + int r = unlink(path); + MP_THREAD_GIL_ENTER(); + + RAISE_ERRNO(r, errno); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_remove_obj, mod_os_remove); + +STATIC mp_obj_t mod_os_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) { + const char *old_path = mp_obj_str_get_str(old_path_in); + const char *new_path = mp_obj_str_get_str(new_path_in); + + MP_THREAD_GIL_EXIT(); + int r = rename(old_path, new_path); + MP_THREAD_GIL_ENTER(); + + RAISE_ERRNO(r, errno); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_os_rename_obj, mod_os_rename); + +STATIC mp_obj_t mod_os_rmdir(mp_obj_t path_in) { + const char *path = mp_obj_str_get_str(path_in); + + MP_THREAD_GIL_EXIT(); + int r = rmdir(path); + MP_THREAD_GIL_ENTER(); + + RAISE_ERRNO(r, errno); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_rmdir_obj, mod_os_rmdir); + +STATIC mp_obj_t mod_os_system(mp_obj_t cmd_in) { + const char *cmd = mp_obj_str_get_str(cmd_in); + + MP_THREAD_GIL_EXIT(); + int r = system(cmd); + MP_THREAD_GIL_ENTER(); + + RAISE_ERRNO(r, errno); + + return MP_OBJ_NEW_SMALL_INT(r); +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_os_system_obj, mod_os_system); + +STATIC mp_obj_t mod_os_getenv(mp_obj_t var_in) { + #if defined(MICROPY_UNIX_COVERAGE) + mp_obj_t result = common_hal_os_getenv(mp_obj_str_get_str(var_in), mp_const_none); + if (result != mp_const_none) { + return result; + } + #endif + const char *s = getenv(mp_obj_str_get_str(var_in)); + if (s == NULL) { + return mp_const_none; + } + return mp_obj_new_str(s, strlen(s)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_obj, mod_os_getenv); + +#if defined(MICROPY_UNIX_COVERAGE) +STATIC mp_obj_t mod_os_getenv_int(mp_obj_t var_in) { + mp_int_t value; + os_getenv_err_t result = common_hal_os_getenv_int(mp_obj_str_get_str(var_in), &value); + if (result == 0) { + return mp_obj_new_int(value); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_int_obj, mod_os_getenv_int); + +STATIC mp_obj_t mod_os_getenv_str(mp_obj_t var_in) { + char buf[4096]; + os_getenv_err_t result = common_hal_os_getenv_str(mp_obj_str_get_str(var_in), buf, sizeof(buf)); + if (result == 0) { + return mp_obj_new_str_copy(&mp_type_str, (byte *)buf, strlen(buf)); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_str_obj, mod_os_getenv_str); +#endif + +STATIC mp_obj_t mod_os_putenv(mp_obj_t key_in, mp_obj_t value_in) { + const char *key = mp_obj_str_get_str(key_in); + const char *value = mp_obj_str_get_str(value_in); + int ret; + + #if _WIN32 + ret = _putenv_s(key, value); + #else + ret = setenv(key, value, 1); + #endif + + if (ret == -1) { + mp_raise_OSError(errno); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(mod_os_putenv_obj, mod_os_putenv); + +STATIC mp_obj_t mod_os_unsetenv(mp_obj_t key_in) { + const char *key = mp_obj_str_get_str(key_in); + int ret; + + #if _WIN32 + ret = _putenv_s(key, ""); + #else + ret = unsetenv(key); + #endif + + if (ret == -1) { + mp_raise_OSError(errno); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_os_unsetenv_obj, mod_os_unsetenv); + +STATIC mp_obj_t mod_os_mkdir(mp_obj_t path_in) { + // TODO: Accept mode param + const char *path = mp_obj_str_get_str(path_in); + MP_THREAD_GIL_EXIT(); + #ifdef _WIN32 + int r = mkdir(path); + #else + int r = mkdir(path, 0777); + #endif + MP_THREAD_GIL_ENTER(); + RAISE_ERRNO(r, errno); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_mkdir_obj, mod_os_mkdir); + +typedef struct _mp_obj_listdir_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + DIR *dir; +} mp_obj_listdir_t; + +STATIC mp_obj_t listdir_next(mp_obj_t self_in) { + mp_obj_listdir_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->dir == NULL) { + goto done; + } + MP_THREAD_GIL_EXIT(); + struct dirent *dirent = readdir(self->dir); + if (dirent == NULL) { + closedir(self->dir); + MP_THREAD_GIL_ENTER(); + self->dir = NULL; + done: + return MP_OBJ_STOP_ITERATION; + } + MP_THREAD_GIL_ENTER(); + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); + t->items[0] = mp_obj_new_str(dirent->d_name, strlen(dirent->d_name)); + + #ifdef _DIRENT_HAVE_D_TYPE + #ifdef DTTOIF + t->items[1] = MP_OBJ_NEW_SMALL_INT(DTTOIF(dirent->d_type)); + #else + if (dirent->d_type == DT_DIR) { + t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); + } else if (dirent->d_type == DT_REG) { + t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); + } else { + t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type); + } + #endif + #else + // DT_UNKNOWN should have 0 value on any reasonable system + t->items[1] = MP_OBJ_NEW_SMALL_INT(0); + #endif + + #ifdef _DIRENT_HAVE_D_INO + t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino); + #else + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); + #endif + return MP_OBJ_FROM_PTR(t); +} + +STATIC mp_obj_t mod_os_ilistdir(size_t n_args, const mp_obj_t *args) { + const char *path = "."; + if (n_args > 0) { + path = mp_obj_str_get_str(args[0]); + } + mp_obj_listdir_t *o = m_new_obj(mp_obj_listdir_t); + o->base.type = &mp_type_polymorph_iter; + MP_THREAD_GIL_EXIT(); + o->dir = opendir(path); + MP_THREAD_GIL_ENTER(); + o->iternext = listdir_next; + return MP_OBJ_FROM_PTR(o); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_ilistdir_obj, 0, 1, mod_os_ilistdir); + +STATIC mp_obj_t mod_os_errno(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + return MP_OBJ_NEW_SMALL_INT(errno); + } + + errno = mp_obj_get_int(args[0]); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_errno_obj, 0, 1, mod_os_errno); + +STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, + { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mod_os_errno_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mod_os_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mod_os_urandom_obj) }, + #if MICROPY_PY_OS_STATVFS + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mod_os_statvfs_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mod_os_system_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mod_os_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mod_os_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mod_os_rmdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, + #if defined(MICROPY_UNIX_COVERAGE) + { MP_ROM_QSTR(MP_QSTR_getenv_int), MP_ROM_PTR(&mod_os_getenv_int_obj) }, + { MP_ROM_QSTR(MP_QSTR_getenv_str), MP_ROM_PTR(&mod_os_getenv_str_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mod_os_putenv_obj) }, + { MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mod_os_unsetenv_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_os_globals, mp_module_os_globals_table); + +const mp_obj_module_t mp_module_os = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mp_module_os_globals, +}; diff --git a/ports/unix/moduos_vfs.c b/ports/unix/moduos_vfs.c new file mode 100644 index 0000000000..495679290a --- /dev/null +++ b/ports/unix/moduos_vfs.c @@ -0,0 +1,98 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * SPDX-FileCopyrightText: Copyright (c) 2017 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "extmod/vfs.h" +#include "extmod/vfs_posix.h" +#include "extmod/vfs_fat.h" +#include "extmod/vfs_lfs.h" + +#if MICROPY_VFS + +// These are defined in modos.c +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_errno_obj); +MP_DECLARE_CONST_FUN_OBJ_1(mod_os_getenv_obj); +#if defined(MICROPY_UNIX_COVERAGE) +MP_DECLARE_CONST_FUN_OBJ_1(mod_os_getenv_int_obj); +MP_DECLARE_CONST_FUN_OBJ_1(mod_os_getenv_str_obj); +#endif +MP_DECLARE_CONST_FUN_OBJ_1(mod_os_putenv_obj); +MP_DECLARE_CONST_FUN_OBJ_1(mod_os_unsetenv_obj); +MP_DECLARE_CONST_FUN_OBJ_1(mod_os_system_obj); + +STATIC const mp_rom_map_elem_t uos_vfs_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos_vfs) }, + { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, + + { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mod_os_errno_obj) }, + { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, + #if defined(MICROPY_UNIX_COVERAGE) + { MP_ROM_QSTR(MP_QSTR_getenv_int), MP_ROM_PTR(&mod_os_getenv_int_obj) }, + { MP_ROM_QSTR(MP_QSTR_getenv_str), MP_ROM_PTR(&mod_os_getenv_str_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mod_os_putenv_obj) }, + { MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mod_os_unsetenv_obj) }, + { MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mod_os_system_obj) }, + + { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, + + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_vfs_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, + { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove + + #if MICROPY_VFS_POSIX + { MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) }, + #endif + #if MICROPY_VFS_FAT + { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, + #endif + #if MICROPY_VFS_LFS1 + { MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) }, + #endif + #if MICROPY_VFS_LFS2 + { MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) }, + #endif +}; + +STATIC MP_DEFINE_CONST_DICT(uos_vfs_module_globals, uos_vfs_module_globals_table); + +const mp_obj_module_t mp_module_uos_vfs = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&uos_vfs_module_globals, +}; + +#endif // MICROPY_VFS diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index b1733f9c1a..58a214178a 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -34,6 +34,9 @@ // If we're building the minimal variant, ignore the rest of this file. #ifndef MICROPY_UNIX_MINIMAL +//CIRCUITPY +#define CIRCUITPY_MICROPYTHON_ADVANCED (1) + // If the variant did not set a feature level then configure a set of features. #ifndef MICROPY_CONFIG_ROM_LEVEL #define MICROPY_COMP_MODULE_CONST (1) @@ -104,6 +107,17 @@ #define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_PERSISTENT_CODE_LOAD (1) + +//CIRCUITPY: native emitters not supported +#define MICROPY_EMIT_X64 (!CIRCUITPY) +#define MICROPY_EMIT_X86 (!CIRCUITPY) +#define MICROPY_EMIT_THUMB (!CIRCUITPY) +#define MICROPY_EMIT_INLINE_THUMB (!CIRCUITPY) +#define MICROPY_EMIT_ARM (!CIRCUITPY) +#define MICROPY_EMIT_XTENSA (!CIRCUITPY) +#define MICROPY_EMIT_INLINE_XTENSA (!CIRCUITPY) +#define MICROPY_EMIT_XTENSAWIN (!CIRCUITPY) + #if !defined(MICROPY_EMIT_X64) && defined(__x86_64__) #define MICROPY_EMIT_X64 (1) #endif diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index 78a758b769..a0f654597b 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -9,7 +9,8 @@ MICROPY_FORCE_32BIT = 0 MICROPY_USE_READLINE = 1 # btree module using Berkeley DB 1.xx -MICROPY_PY_BTREE = 1 +# CIRCUITPY: not present +MICROPY_PY_BTREE = 0 # _thread module using pthreads MICROPY_PY_THREAD = 1 @@ -39,4 +40,7 @@ MICROPY_PY_JNI = 0 # as submodules (currently affects only libffi). MICROPY_STANDALONE = 0 +# CIRCUITPY CIRCUITPY_ULAB = 1 +MICROPY_EMIT_NATIVE = 0 +CFLAGS += -DCIRCUITPY=1 diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 08d5d35723..665d038c0d 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -126,7 +126,58 @@ void mp_hal_stdio_mode_orig(void) { #endif +#if MICROPY_PY_OS_DUPTERM +static int call_dupterm_read(size_t idx) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t read_m[3]; + mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_read, read_m); + read_m[2] = MP_OBJ_NEW_SMALL_INT(1); + mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); + if (res == mp_const_none) { + return -2; + } + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len == 0) { + mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); + MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL; + return -1; + } + nlr_pop(); + return *(byte *)bufinfo.buf; + } else { + // Temporarily disable dupterm to avoid infinite recursion + mp_obj_t save_term = MP_STATE_VM(dupterm_objs[idx]); + MP_STATE_VM(dupterm_objs[idx]) = NULL; + mp_printf(&mp_plat_print, "dupterm: "); + mp_obj_print_exception(&mp_plat_print, nlr.ret_val); + MP_STATE_VM(dupterm_objs[idx]) = save_term; + } + + return -1; +} +#endif + int mp_hal_stdin_rx_chr(void) { + #if MICROPY_PY_OS_DUPTERM + // TODO only support dupterm one slot at the moment + if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) { + int c; + do { + c = call_dupterm_read(0); + } while (c == -2); + if (c == -1) { + goto main_term; + } + if (c == '\n') { + c = '\r'; + } + return c; + } +main_term:; + #endif + unsigned char c; ssize_t ret; MP_HAL_RETRY_SYSCALL(ret, read(STDIN_FILENO, &c, 1), {}); @@ -141,6 +192,9 @@ int mp_hal_stdin_rx_chr(void) { void mp_hal_stdout_tx_strn(const char *str, size_t len) { ssize_t ret; MP_HAL_RETRY_SYSCALL(ret, write(STDOUT_FILENO, str, len), {}); + #if MICROPY_PY_OS_DUPTERM + mp_uos_dupterm_tx_strn(str, len); + #endif } // cooked is same as uncooked because the terminal does some postprocessing diff --git a/py/mkrules.mk b/py/mkrules.mk index 730ac9704f..5b871af62b 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -236,3 +236,8 @@ print-def: @$(RM) -f __empty__.c -include $(OBJ:.o=.P) + +# Print out the value of a make variable. +# https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile +print-%: + @echo $* = $($*) diff --git a/py/modsys.c b/py/modsys.c index 92779914b0..63fb654f05 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -36,6 +36,7 @@ #include "py/smallint.h" #include "py/runtime.h" #include "py/persistentcode.h" +#include "extmod/moduplatform.h" #include "genhdr/mpversion.h" #if MICROPY_PY_SYS_SETTRACE diff --git a/py/objexcept.c b/py/objexcept.c index b19844c0ad..4aaa9ec592 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -659,3 +659,172 @@ void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values *values = self->traceback->data; } } + +#if MICROPY_PY_SYS_EXC_INFO +STATIC const mp_obj_namedtuple_type_t code_type_obj = { + .base = { + .base = { + .type = &mp_type_type + }, + .flags = MP_TYPE_FLAG_EXTENDED, + .name = MP_QSTR_code, + .print = namedtuple_print, + .make_new = namedtuple_make_new, + .parent = &mp_type_tuple, + .attr = namedtuple_attr, + MP_TYPE_EXTENDED_FIELDS( + .unary_op = mp_obj_tuple_unary_op, + .binary_op = mp_obj_tuple_binary_op, + .subscr = mp_obj_tuple_subscr, + .getiter = mp_obj_tuple_getiter, + ), + }, + .n_fields = 15, + .fields = { + MP_QSTR_co_argcount, + MP_QSTR_co_kwonlyargcount, + MP_QSTR_co_nlocals, + MP_QSTR_co_stacksize, + MP_QSTR_co_flags, + MP_QSTR_co_code, + MP_QSTR_co_consts, + MP_QSTR_co_names, + MP_QSTR_co_varnames, + MP_QSTR_co_freevars, + MP_QSTR_co_cellvars, + MP_QSTR_co_filename, + MP_QSTR_co_name, + MP_QSTR_co_firstlineno, + MP_QSTR_co_lnotab, + }, +}; + +STATIC mp_obj_t code_make_new(qstr file, qstr block) { + mp_obj_t elems[15] = { + mp_obj_new_int(0), // co_argcount + mp_obj_new_int(0), // co_kwonlyargcount + mp_obj_new_int(0), // co_nlocals + mp_obj_new_int(0), // co_stacksize + mp_obj_new_int(0), // co_flags + mp_obj_new_bytearray(0, NULL), // co_code + mp_obj_new_tuple(0, NULL), // co_consts + mp_obj_new_tuple(0, NULL), // co_names + mp_obj_new_tuple(0, NULL), // co_varnames + mp_obj_new_tuple(0, NULL), // co_freevars + mp_obj_new_tuple(0, NULL), // co_cellvars + MP_OBJ_NEW_QSTR(file), // co_filename + MP_OBJ_NEW_QSTR(block), // co_name + mp_obj_new_int(1), // co_firstlineno + mp_obj_new_bytearray(0, NULL), // co_lnotab + }; + + return namedtuple_make_new((const mp_obj_type_t *)&code_type_obj, 15, 0, elems); +} + +STATIC const mp_obj_namedtuple_type_t frame_type_obj = { + .base = { + .base = { + .type = &mp_type_type + }, + .name = MP_QSTR_frame, + .print = namedtuple_print, + .make_new = namedtuple_make_new, + .parent = &mp_type_tuple, + .attr = namedtuple_attr, + MP_TYPE_EXTENDED_FIELDS( + .unary_op = mp_obj_tuple_unary_op, + .binary_op = mp_obj_tuple_binary_op, + .subscr = mp_obj_tuple_subscr, + .getiter = mp_obj_tuple_getiter, + ), + }, + .n_fields = 8, + .fields = { + MP_QSTR_f_back, + MP_QSTR_f_builtins, + MP_QSTR_f_code, + MP_QSTR_f_globals, + MP_QSTR_f_lasti, + MP_QSTR_f_lineno, + MP_QSTR_f_locals, + MP_QSTR_f_trace, + }, +}; + +STATIC mp_obj_t frame_make_new(mp_obj_t f_code, int f_lineno) { + mp_obj_t elems[8] = { + mp_const_none, // f_back + mp_obj_new_dict(0), // f_builtins + f_code, // f_code + mp_obj_new_dict(0), // f_globals + mp_obj_new_int(0), // f_lasti + mp_obj_new_int(f_lineno), // f_lineno + mp_obj_new_dict(0), // f_locals + mp_const_none, // f_trace + }; + + return namedtuple_make_new((const mp_obj_type_t *)&frame_type_obj, 8, 0, elems); +} + +STATIC const mp_obj_namedtuple_type_t traceback_type_obj = { + .base = { + .base = { + .type = &mp_type_type + }, + .flags = MP_TYPE_FLAG_EXTENDED, + .name = MP_QSTR_traceback, + .print = namedtuple_print, + .make_new = namedtuple_make_new, + .parent = &mp_type_tuple, + .attr = namedtuple_attr, + MP_TYPE_EXTENDED_FIELDS( + .unary_op = mp_obj_tuple_unary_op, + .binary_op = mp_obj_tuple_binary_op, + .subscr = mp_obj_tuple_subscr, + .getiter = mp_obj_tuple_getiter, + ), + }, + .n_fields = 4, + .fields = { + MP_QSTR_tb_frame, + MP_QSTR_tb_lasti, + MP_QSTR_tb_lineno, + MP_QSTR_tb_next, + }, +}; + +STATIC mp_obj_t traceback_from_values(size_t *values, mp_obj_t tb_next) { + int lineno = values[1]; + + mp_obj_t elems[4] = { + frame_make_new(code_make_new(values[0], values[2]), lineno), + mp_obj_new_int(0), + mp_obj_new_int(lineno), + tb_next, + }; + + return namedtuple_make_new((const mp_obj_type_t *)&traceback_type_obj, 4, 0, elems); +}; + +mp_obj_t mp_obj_exception_get_traceback_obj(mp_obj_t self_in) { + mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); + + if (!mp_obj_is_exception_instance(self)) { + return mp_const_none; + } + + size_t n, *values; + mp_obj_exception_get_traceback(self, &n, &values); + if (n == 0) { + return mp_const_none; + } + + mp_obj_t tb_next = mp_const_none; + + for (size_t i = 0; i < n; i += 3) { + tb_next = traceback_from_values(&values[i], tb_next); + } + + return tb_next; +} +#endif diff --git a/supervisor/shared/background_callback.c b/supervisor/shared/background_callback.c index 80f70b528a..cbfdec4797 100644 --- a/supervisor/shared/background_callback.c +++ b/supervisor/shared/background_callback.c @@ -68,7 +68,7 @@ void PLACE_IN_ITCM(background_callback_add)(background_callback_t * cb, backgrou background_callback_add_core(cb); } -bool inline background_callback_pending(void) { +inline bool background_callback_pending(void) { return callback_head != NULL; }