diff --git a/docs/shared_bindings_matrix.py b/docs/shared_bindings_matrix.py index 5b9b63d8fd..761e3e29f2 100644 --- a/docs/shared_bindings_matrix.py +++ b/docs/shared_bindings_matrix.py @@ -27,6 +27,7 @@ import pathlib import re import subprocess import sys +import functools from concurrent.futures import ThreadPoolExecutor @@ -80,12 +81,11 @@ This is the same list as in the preprocess_frozen_modules script.""" repository_urls = {} """Cache of repository URLs for frozen modules.""" +root_dir = pathlib.Path(__file__).resolve().parent.parent + def get_circuitpython_root_dir(): """ The path to the root './circuitpython' directory. """ - file_path = pathlib.Path(__file__).resolve() - root_dir = file_path.parent.parent - return root_dir def get_shared_bindings(): @@ -102,7 +102,7 @@ def get_board_mapping(): """ boards = {} for port in SUPPORTED_PORTS: - board_path = os.path.join("../ports", port, "boards") + board_path = root_dir / "ports" / port / "boards" for board_path in os.scandir(board_path): if board_path.is_dir(): board_files = os.listdir(board_path.path) @@ -276,6 +276,7 @@ def lookup_setting(settings, key, default=''): key = value[2:-1] return value +@functools.cache def all_ports_all_boards(ports=SUPPORTED_PORTS): for port in ports: diff --git a/extmod/moduselect.c b/extmod/moduselect.c index c8f5e57363..5744d2839c 100644 --- a/extmod/moduselect.c +++ b/extmod/moduselect.c @@ -9,7 +9,7 @@ #include -#include "py/ioctl.h" +#include "py/stream.h" #include "py/runtime.h" #include "py/obj.h" #include "py/objlist.h" diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 880eef7740..2a00566317 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -400,6 +400,35 @@ STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); +STATIC mp_obj_t vfs_fat_utime(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t times_in) { + mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); + const char *path = mp_obj_str_get_str(path_in); + if (!mp_obj_is_tuple_compatible(times_in)) { + mp_raise_type_arg(&mp_type_TypeError, times_in); + } + + mp_obj_t *otimes; + mp_obj_get_array_fixed_n(times_in, 2, &otimes); + + // Validate that both elements of the tuple are int and discard the second one + int time[2]; + time[0] = mp_obj_get_int(otimes[0]); + time[1] = mp_obj_get_int(otimes[1]); + timeutils_struct_time_t tm; + timeutils_seconds_since_epoch_to_struct_time(time[0], &tm); + + FILINFO fno; + fno.fdate = (WORD)(((tm.tm_year - 1980) * 512U) | tm.tm_mon * 32U | tm.tm_mday); + fno.ftime = (WORD)(tm.tm_hour * 2048U | tm.tm_min * 32U | tm.tm_sec / 2U); + FRESULT res = f_utime(&self->fatfs, path, &fno); + if (res != FR_OK) { + mp_raise_OSError_fresult(res); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_utime_obj, vfs_fat_utime); + #if MICROPY_FATFS_USE_LABEL STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); @@ -451,6 +480,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) }, + { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&fat_vfs_utime_obj) }, #if MICROPY_FATFS_USE_LABEL { MP_ROM_QSTR(MP_QSTR_label), MP_ROM_PTR(&fat_vfs_label_obj) }, #endif diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index b6e0c7468c..6c5e5ee585 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -117,6 +117,10 @@ msgstr "" msgid "%q init failed" msgstr "" +#: shared-bindings/dualbank/__init__.c +msgid "%q is %q" +msgstr "" + #: py/argcheck.c msgid "%q length must be %d" msgstr "" @@ -211,7 +215,7 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "" -#: py/objint.c +#: py/objint.c shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "" @@ -1001,7 +1005,15 @@ msgid "Filters too complex" msgstr "" #: ports/espressif/common-hal/dualbank/__init__.c -msgid "Firmware image is invalid" +msgid "Firmware is duplicate" +msgstr "" + +#: ports/espressif/common-hal/dualbank/__init__.c +msgid "Firmware is invalid" +msgstr "" + +#: ports/espressif/common-hal/dualbank/__init__.c +msgid "Firmware is too big" msgstr "" #: shared-bindings/bitmaptools/__init__.c @@ -4151,7 +4163,7 @@ msgstr "" msgid "unexpected keyword argument" msgstr "" -#: py/bc.c py/objnamedtuple.c +#: py/bc.c py/objnamedtuple.c shared-bindings/traceback/__init__.c msgid "unexpected keyword argument '%q'" msgstr "" diff --git a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk index 261e30d7e5..5d02fe3824 100644 --- a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk +++ b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk @@ -11,3 +11,5 @@ CIRCUITPY_BUILD_EXTENSIONS = bin,uf2 INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 + +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk index de9819a895..7ef2af6ddb 100644 --- a/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk +++ b/ports/atmel-samd/boards/arduino_nano_33_iot/mpconfigboard.mk @@ -11,4 +11,5 @@ CIRCUITPY_BUILD_EXTENSIONS = bin,uf2 INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 + CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk index a1891f972e..aa9055a5e3 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk @@ -15,12 +15,13 @@ CIRCUITPY_FULL_BUILD = 0 # A number of modules are removed for RFM69 to make room for frozen libraries. # Many I/O functions are not available. CIRCUITPY_ANALOGIO = 1 +CIRCUITPY_BUSDEVICE = 1 +CIRCUITPY_RAINBOWIO = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 +CIRCUITPY_TOUCHIO = 0 CIRCUITPY_USB_MIDI = 0 CIRCUITPY_USB_HID = 0 -CIRCUITPY_TOUCHIO = 0 -CIRCUITPY_BUSDEVICE = 1 # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_RFM69 diff --git a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk index bcf3e132d3..32be4805d7 100644 --- a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk @@ -20,11 +20,13 @@ CIRCUITPY_BITBANG_APA102 = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CTARGET = 0 CIRCUITPY_NEOPIXEL_WRITE = 0 +CIRCUITPY_ONEWIREIO = 0 CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_PIXELBUF = 0 CIRCUITPY_PS2IO = 0 CIRCUITPY_PULSEIO = 0 CIRCUITPY_PWMIO = 0 +CIRCUITPY_RAINBOWIO = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 CIRCUITPY_SAMD = 0 diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk index 70ece9b9fc..ef23e56022 100755 --- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk +++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk @@ -9,3 +9,5 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32FV" LONGINT_IMPL = MPZ + +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c index 29d6612ad8..d720399b98 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Processor.c +++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c @@ -73,46 +73,37 @@ #include "peripheral_clk_config.h" #define ADC_TEMP_SAMPLE_LENGTH 4 -#define INT1V_VALUE_FLOAT 1.0 -#define INT1V_DIVIDER_1000 1000.0 -#define ADC_12BIT_FULL_SCALE_VALUE_FLOAT 4095.0 +#define INT1V_VALUE_FLOAT MICROPY_FLOAT_CONST(1.0) +#define INT1V_DIVIDER_1000 MICROPY_FLOAT_CONST(1000.0) +#define ADC_12BIT_FULL_SCALE_VALUE_FLOAT MICROPY_FLOAT_CONST(4095.0) // channel argument (ignored in calls below) #define IGNORED_CHANNEL 0 -// Decimal to fraction conversion. (adapted from ASF sample). -STATIC float convert_dec_to_frac(uint8_t val) { - float float_val = (float)val; - if (val < 10) { - return float_val / 10.0; - } else if (val < 100) { - return float_val / 100.0; - } else { - return float_val / 1000.0; - } -} // Extract the production calibration data information from NVM (adapted from ASF sample), // then calculate the temperature +// +// This code performs almost all operations with scaled integers. For +// instance, tempR is in units of 1/10°C, INT1VR is in units of 1mV, etc, +// This is important to reduce the code size of the function. The effect on +// precision is a ~.9°C difference vs the floating point algorithm on an +// approximate 0..60°C range with a difference of ~.5°C at 25°C. When the fine +// calculation step is skipped, the additional error approximately doubles. +// +// To save code size, rounding is neglected. However, trying to add back rounding +// (by computing (a + b/2) / b instead of just a / b) actually didn't help +// accuracy anyway. #ifdef SAMD21 STATIC float calculate_temperature(uint16_t raw_value) { - volatile uint32_t val1; /* Temperature Log Row Content first 32 bits */ - volatile uint32_t val2; /* Temperature Log Row Content another 32 bits */ - uint8_t room_temp_val_int; /* Integer part of room temperature in °C */ - uint8_t room_temp_val_dec; /* Decimal part of room temperature in °C */ - uint8_t hot_temp_val_int; /* Integer part of hot temperature in °C */ - uint8_t hot_temp_val_dec; /* Decimal part of hot temperature in °C */ - int8_t room_int1v_val; /* internal 1V reference drift at room temperature */ - int8_t hot_int1v_val; /* internal 1V reference drift at hot temperature*/ - - float tempR; // Production Room temperature - float tempH; // Production Hot temperature - float INT1VR; // Room temp 2's complement of the internal 1V reference value - float INT1VH; // Hot temp 2's complement of the internal 1V reference value - uint16_t ADCR; // Production Room temperature ADC value - uint16_t ADCH; // Production Hot temperature ADC value - float VADCR; // Room temperature ADC voltage - float VADCH; // Hot temperature ADC voltage + uint32_t val1; /* Temperature Log Row Content first 32 bits */ + uint32_t val2; /* Temperature Log Row Content another 32 bits */ + int room_temp_val_int; /* Integer part of room temperature in °C */ + int room_temp_val_dec; /* Decimal part of room temperature in °C */ + int hot_temp_val_int; /* Integer part of hot temperature in °C */ + int hot_temp_val_dec; /* Decimal part of hot temperature in °C */ + int room_int1v_val; /* internal 1V reference drift at room temperature */ + int hot_int1v_val; /* internal 1V reference drift at hot temperature*/ uint32_t *temp_log_row_ptr = (uint32_t *)NVMCTRL_TEMP_LOG; @@ -120,32 +111,29 @@ STATIC float calculate_temperature(uint16_t raw_value) { temp_log_row_ptr++; val2 = *temp_log_row_ptr; - room_temp_val_int = (uint8_t)((val1 & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos); - room_temp_val_dec = (uint8_t)((val1 & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos); + room_temp_val_int = ((val1 & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos); + room_temp_val_dec = ((val1 & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos); - hot_temp_val_int = (uint8_t)((val1 & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos); - hot_temp_val_dec = (uint8_t)((val1 & FUSES_HOT_TEMP_VAL_DEC_Msk) >> FUSES_HOT_TEMP_VAL_DEC_Pos); + hot_temp_val_int = ((val1 & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos); + hot_temp_val_dec = ((val1 & FUSES_HOT_TEMP_VAL_DEC_Msk) >> FUSES_HOT_TEMP_VAL_DEC_Pos); + // necessary casts: must interpret 8 bits as signed room_int1v_val = (int8_t)((val1 & FUSES_ROOM_INT1V_VAL_Msk) >> FUSES_ROOM_INT1V_VAL_Pos); hot_int1v_val = (int8_t)((val2 & FUSES_HOT_INT1V_VAL_Msk) >> FUSES_HOT_INT1V_VAL_Pos); - ADCR = (uint16_t)((val2 & FUSES_ROOM_ADC_VAL_Msk) >> FUSES_ROOM_ADC_VAL_Pos); - ADCH = (uint16_t)((val2 & FUSES_HOT_ADC_VAL_Msk) >> FUSES_HOT_ADC_VAL_Pos); + int ADCR = ((val2 & FUSES_ROOM_ADC_VAL_Msk) >> FUSES_ROOM_ADC_VAL_Pos); + int ADCH = ((val2 & FUSES_HOT_ADC_VAL_Msk) >> FUSES_HOT_ADC_VAL_Pos); - tempR = room_temp_val_int + convert_dec_to_frac(room_temp_val_dec); - tempH = hot_temp_val_int + convert_dec_to_frac(hot_temp_val_dec); + int tempR = 10 * room_temp_val_int + room_temp_val_dec; + int tempH = 10 * hot_temp_val_int + hot_temp_val_dec; - INT1VR = 1 - ((float)room_int1v_val / INT1V_DIVIDER_1000); - INT1VH = 1 - ((float)hot_int1v_val / INT1V_DIVIDER_1000); + int INT1VR = 1000 - room_int1v_val; + int INT1VH = 1000 - hot_int1v_val; - VADCR = ((float)ADCR * INT1VR) / ADC_12BIT_FULL_SCALE_VALUE_FLOAT; - VADCH = ((float)ADCH * INT1VH) / ADC_12BIT_FULL_SCALE_VALUE_FLOAT; + int VADCR = ADCR * INT1VR; + int VADCH = ADCH * INT1VH; - float VADC; /* Voltage calculation using ADC result for Coarse Temp calculation */ - float VADCM; /* Voltage calculation using ADC result for Fine Temp calculation. */ - float INT1VM; /* Voltage calculation for reality INT1V value during the ADC conversion */ - - VADC = ((float)raw_value * INT1V_VALUE_FLOAT) / ADC_12BIT_FULL_SCALE_VALUE_FLOAT; + int VADC = raw_value * 1000; // Hopefully compiler will remove common subepxressions here. @@ -153,21 +141,31 @@ STATIC float calculate_temperature(uint16_t raw_value) { // 1b as mentioned in data sheet section "Temperature Sensor Characteristics" // of Electrical Characteristics. (adapted from ASF sample code). // Coarse Temp Calculation by assume INT1V=1V for this ADC conversion - float coarse_temp = tempR + (((tempH - tempR) / (VADCH - VADCR)) * (VADC - VADCR)); + int coarse_temp = tempR + (tempH - tempR) * (VADC - VADCR) / (VADCH - VADCR); + #if CIRCUITPY_FULL_BUILD // Calculation to find the real INT1V value during the ADC conversion + int INT1VM; /* Voltage calculation for reality INT1V value during the ADC conversion */ + INT1VM = INT1VR + (((INT1VH - INT1VR) * (coarse_temp - tempR)) / (tempH - tempR)); - VADCM = ((float)raw_value * INT1VM) / ADC_12BIT_FULL_SCALE_VALUE_FLOAT; + int VADCM = raw_value * INT1VM; // Fine Temp Calculation by replace INT1V=1V by INT1V = INT1Vm for ADC conversion - float fine_temp = tempR + (((tempH - tempR) / (VADCH - VADCR)) * (VADCM - VADCR)); + float fine_temp = tempR + (((tempH - tempR) * (VADCM - VADCR)) / (VADCH - VADCR)); - return fine_temp; + return fine_temp / 10; + #else + return coarse_temp / 10.; + #endif } #endif // SAMD21 #ifdef SAM_D5X_E5X +// Decimal to fraction conversion. (adapted from ASF sample). +STATIC float convert_dec_to_frac(uint8_t val) { + return val / MICROPY_FLOAT_CONST(10.); +} STATIC float calculate_temperature(uint16_t TP, uint16_t TC) { uint32_t TLI = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_INT_ADDR & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos; uint32_t TLD = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_DEC_ADDR & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos; diff --git a/ports/espressif/boards/cytron_maker_feather_aiot_s3/pins.c b/ports/espressif/boards/cytron_maker_feather_aiot_s3/pins.c index b8ed298596..cca5f2617d 100644 --- a/ports/espressif/boards/cytron_maker_feather_aiot_s3/pins.c +++ b/ports/espressif/boards/cytron_maker_feather_aiot_s3/pins.c @@ -3,35 +3,46 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LED_BUILTIN), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO3) }, { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_T4), MP_ROM_PTR(&pin_GPIO4) }, { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_T5), MP_ROM_PTR(&pin_GPIO5) }, { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_T6), MP_ROM_PTR(&pin_GPIO6) }, { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SS), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_T7), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_T8), MP_ROM_PTR(&pin_GPIO8) }, { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_T9), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_T10), MP_ROM_PTR(&pin_GPIO10) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, { MP_ROM_QSTR(MP_QSTR_VP_EN), MP_ROM_PTR(&pin_GPIO11) }, @@ -43,20 +54,27 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_VIN), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_VBATT), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_A12), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_A11), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_T14), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_GPIO15) }, { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO16) }, { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, @@ -71,6 +89,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_D42), MP_ROM_PTR(&pin_GPIO42) }, { MP_ROM_QSTR(MP_QSTR_RGB), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_RGB_BUILTIN), MP_ROM_PTR(&pin_GPIO46) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO46) }, { MP_ROM_QSTR(MP_QSTR_D46), MP_ROM_PTR(&pin_GPIO46) }, diff --git a/ports/espressif/common-hal/dualbank/__init__.c b/ports/espressif/common-hal/dualbank/__init__.c index 91c7981dd9..9e3fb38627 100644 --- a/ports/espressif/common-hal/dualbank/__init__.c +++ b/ports/espressif/common-hal/dualbank/__init__.c @@ -57,14 +57,13 @@ void common_hal_dualbank_flash(const void *buf, const size_t len, const size_t o if (update_partition == NULL) { update_partition = esp_ota_get_next_update_partition(NULL); + assert(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) { @@ -86,14 +85,14 @@ void common_hal_dualbank_flash(const void *buf, const size_t len, const size_t o // 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(); + mp_raise_RuntimeError(translate("Firmware is duplicate")); } // 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(); + mp_raise_RuntimeError(translate("Firmware is invalid")); } } @@ -104,7 +103,7 @@ void common_hal_dualbank_flash(const void *buf, const size_t len, const size_t o } } else { ESP_LOGE(TAG, "received package is not fit len"); - task_fatal_error(); + mp_raise_RuntimeError(translate("Firmware is too big")); } } @@ -128,7 +127,7 @@ void common_hal_dualbank_switch(void) { 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")); + mp_raise_RuntimeError(translate("Firmware is invalid")); } ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)); task_fatal_error(); diff --git a/ports/espressif/esp-idf-config/sdkconfig-debug.defaults b/ports/espressif/esp-idf-config/sdkconfig-debug.defaults index 9d02c62445..e93b3d2825 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-debug.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-debug.defaults @@ -5,6 +5,12 @@ CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set +CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG=y +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set # end of Bootloader config # CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set @@ -60,6 +66,17 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 # end of Hardware Abstraction Layer (HAL) and Low Level (LL) +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set +CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +# end of Log output + CONFIG_LWIP_ESP_LWIP_ASSERT=y # # Deprecated options for backward compatibility diff --git a/ports/espressif/esp-idf-config/sdkconfig-opt.defaults b/ports/espressif/esp-idf-config/sdkconfig-opt.defaults index e9b91113d5..1ccd6478fe 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-opt.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-opt.defaults @@ -5,6 +5,12 @@ CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set # end of Bootloader config # @@ -73,6 +79,17 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=1 # end of Hardware Abstraction Layer (HAL) and Low Level (LL) +# +# Log output +# +CONFIG_LOG_DEFAULT_LEVEL_NONE=y +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +# end of Log output + # # LWIP # diff --git a/ports/espressif/supervisor/internal_flash.c b/ports/espressif/supervisor/internal_flash.c index 2f17b48f0c..d6e96732ba 100644 --- a/ports/espressif/supervisor/internal_flash.c +++ b/ports/espressif/supervisor/internal_flash.c @@ -24,6 +24,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include "supervisor/internal_flash.h" #include @@ -32,27 +33,52 @@ #include "extmod/vfs.h" #include "extmod/vfs_fat.h" + #include "py/mphal.h" #include "py/obj.h" #include "py/runtime.h" -#include "lib/oofatfs/ff.h" -#include "components/spi_flash/include/esp_partition.h" +#include "esp_ota_ops.h" +#include "esp_partition.h" +#include "supervisor/filesystem.h" #include "supervisor/flash.h" #include "supervisor/usb.h" -STATIC const esp_partition_t *_partition; +#define OP_READ 0 +#define OP_WRITE 1 // TODO: Split the caching out of supervisor/shared/external_flash so we can use it. #define SECTOR_SIZE 4096 STATIC uint8_t _cache[SECTOR_SIZE]; STATIC uint32_t _cache_lba = 0xffffffff; +#if CIRCUITPY_STORAGE_EXTEND +#if FF_MAX_SS == FF_MIN_SS +#define SECSIZE(fs) (FF_MIN_SS) +#else +#define SECSIZE(fs) ((fs)->ssize) +#endif // FF_MAX_SS == FF_MIN_SS +STATIC DWORD fatfs_bytes(void) { + FATFS *fatfs = filesystem_circuitpy(); + return (fatfs->csize * SECSIZE(fatfs)) * (fatfs->n_fatent - 2); +} +STATIC bool storage_extended = true; +STATIC const esp_partition_t *_partition[2]; +#else +STATIC const esp_partition_t *_partition[1]; +#endif // CIRCUITPY_STORAGE_EXTEND + void supervisor_flash_init(void) { - _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + if (_partition[0] != NULL) { + return; + } + _partition[0] = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + #if CIRCUITPY_STORAGE_EXTEND + _partition[1] = esp_ota_get_next_update_partition(NULL); + #endif } uint32_t supervisor_flash_get_block_size(void) { @@ -60,19 +86,61 @@ uint32_t supervisor_flash_get_block_size(void) { } uint32_t supervisor_flash_get_block_count(void) { - return _partition->size / FILESYSTEM_BLOCK_SIZE; + #if CIRCUITPY_STORAGE_EXTEND + return ((storage_extended) ? (_partition[0]->size + _partition[1]->size) : _partition[0]->size) / FILESYSTEM_BLOCK_SIZE; + #else + return _partition[0]->size / FILESYSTEM_BLOCK_SIZE; + #endif } void port_internal_flash_flush(void) { - } +STATIC void single_partition_rw(const esp_partition_t *partition, uint8_t *data, + const uint32_t offset, const uint32_t size_total, const bool op) { + if (op == OP_READ) { + esp_partition_read(partition, offset, data, size_total); + } else { + esp_partition_erase_range(partition, offset, size_total); + esp_partition_write(partition, offset, _cache, size_total); + } +} + +#if CIRCUITPY_STORAGE_EXTEND +STATIC void multi_partition_rw(uint8_t *data, + const uint32_t offset, const uint32_t size_total, const bool op) { + if (offset > _partition[0]->size) { + // only r/w partition 1 + single_partition_rw(_partition[1], data, (offset - _partition[0]->size), size_total, op); + } else if ((offset + size_total) > _partition[0]->size) { + // first r/w partition 0, then partition 1 + uint32_t size_0 = _partition[0]->size - offset; + uint32_t size_1 = size_total - size_0; + if (op == OP_READ) { + esp_partition_read(_partition[0], offset, data, size_0); + esp_partition_read(_partition[1], 0, (data + size_0), size_1); + } else { + esp_partition_erase_range(_partition[0], offset, size_0); + esp_partition_write(_partition[0], offset, _cache, size_0); + esp_partition_erase_range(_partition[1], 0, size_1); + esp_partition_write(_partition[1], 0, (_cache + size_0), size_1); + } + } else { + // only r/w partition 0 + single_partition_rw(_partition[0], data, offset, size_total, op); + } +} +#endif + mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { - esp_partition_read(_partition, - block * FILESYSTEM_BLOCK_SIZE, - dest, - num_blocks * FILESYSTEM_BLOCK_SIZE); - return 0; + const uint32_t offset = block * FILESYSTEM_BLOCK_SIZE; + const uint32_t read_total = num_blocks * FILESYSTEM_BLOCK_SIZE; + #if CIRCUITPY_STORAGE_EXTEND + multi_partition_rw(dest, offset, read_total, OP_READ); + #else + single_partition_rw(_partition[0], dest, offset, read_total, OP_READ); + #endif + return 0; // success } mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) { @@ -82,12 +150,8 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32 uint32_t block_address = lba + block; uint32_t sector_offset = block_address / blocks_per_sector * SECTOR_SIZE; uint8_t block_offset = block_address % blocks_per_sector; - if (_cache_lba != block_address) { - esp_partition_read(_partition, - sector_offset, - _cache, - SECTOR_SIZE); + supervisor_flash_read_blocks(_cache, sector_offset / FILESYSTEM_BLOCK_SIZE, blocks_per_sector); _cache_lba = sector_offset; } for (uint8_t b = block_offset; b < blocks_per_sector; b++) { @@ -100,15 +164,34 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32 FILESYSTEM_BLOCK_SIZE); block++; } - esp_partition_erase_range(_partition, sector_offset, SECTOR_SIZE); - esp_partition_write(_partition, - sector_offset, - _cache, - SECTOR_SIZE); + #if CIRCUITPY_STORAGE_EXTEND + multi_partition_rw(_cache, sector_offset, SECTOR_SIZE, OP_WRITE); + #else + single_partition_rw(_partition[0], _cache, sector_offset, SECTOR_SIZE, OP_READ); + #endif } - return 0; // success } void supervisor_flash_release_cache(void) { } + +void supervisor_flash_set_extended(bool extended) { + #if CIRCUITPY_STORAGE_EXTEND + storage_extended = extended; + #endif +} + +bool supervisor_flash_get_extended(void) { + #if CIRCUITPY_STORAGE_EXTEND + return storage_extended; + #else + return false; + #endif +} + +void supervisor_flash_update_extended(void) { + #if CIRCUITPY_STORAGE_EXTEND + storage_extended = (_partition[0]->size < fatfs_bytes()); + #endif +} diff --git a/ports/raspberrypi/bindings/cyw43/__init__.c b/ports/raspberrypi/bindings/cyw43/__init__.c index 66cc5fa1c4..bf0cbc2e67 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.c +++ b/ports/raspberrypi/bindings/cyw43/__init__.c @@ -35,6 +35,12 @@ static int power_management_value = PM_DISABLED; +void cyw43_enter_deep_sleep(void) { +#define WL_REG_ON 23 + gpio_set_dir(WL_REG_ON, GPIO_OUT); + gpio_put(WL_REG_ON, false); +} + void bindings_cyw43_wifi_enforce_pm() { cyw43_wifi_pm(&cyw43_state, power_management_value); } diff --git a/ports/raspberrypi/bindings/cyw43/__init__.h b/ports/raspberrypi/bindings/cyw43/__init__.h index c543f7b9e1..2520c6c2d1 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.h +++ b/ports/raspberrypi/bindings/cyw43/__init__.h @@ -51,3 +51,4 @@ const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj); #define PM_DISABLED CONSTANT_CYW43_PM_VALUE(CYW43_NO_POWERSAVE_MODE, 200, 1, 1, 10) extern void bindings_cyw43_wifi_enforce_pm(void); +void cyw43_enter_deep_sleep(void); diff --git a/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk b/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk index f075b03693..9773755649 100644 --- a/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk @@ -13,7 +13,7 @@ CIRCUITPY__EVE = 1 CIRCUITPY_CYW43 = 1 CIRCUITPY_SSL = 1 CIRCUITPY_SSL_MBEDTLS = 1 -CIRCUITPY_HASHLIB = 0 +CIRCUITPY_HASHLIB = 1 CIRCUITPY_WEB_WORKFLOW = 0 CIRCUITPY_MDNS = 0 CIRCUITPY_SOCKETPOOL = 1 diff --git a/ports/raspberrypi/common-hal/alarm/__init__.c b/ports/raspberrypi/common-hal/alarm/__init__.c index 31fa58aab3..9cfa390116 100644 --- a/ports/raspberrypi/common-hal/alarm/__init__.c +++ b/ports/raspberrypi/common-hal/alarm/__init__.c @@ -38,6 +38,10 @@ #include "shared-bindings/microcontroller/__init__.h" +#if CIRCUITPY_CYW43 +#include "bindings/cyw43/__init__.h" +#endif + #include "supervisor/port.h" #include "supervisor/shared/workflow.h" @@ -204,6 +208,10 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala void NORETURN common_hal_alarm_enter_deep_sleep(void) { bool timealarm_set = alarm_time_timealarm_is_set(); + #if CIRCUITPY_CYW43 + cyw43_enter_deep_sleep(); + #endif + // If there's a timealarm, just enter a very deep light sleep if (timealarm_set) { // Prune the clock for sleep diff --git a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c index bbb521ffc5..1490771661 100644 --- a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c +++ b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c @@ -50,6 +50,12 @@ digitalinout_result_t common_hal_digitalio_digitalinout_construct( self->output = false; self->open_drain = false; + #if CIRCUITPY_CYW43 + if (IS_CYW(self)) { + return DIGITALINOUT_OK; + } + #endif + // Set to input. No output value. gpio_init(pin->number); return DIGITALINOUT_OK; diff --git a/ports/raspberrypi/common-hal/hashlib/Hash.c b/ports/raspberrypi/common-hal/hashlib/Hash.c new file mode 100644 index 0000000000..046bd3f096 --- /dev/null +++ b/ports/raspberrypi/common-hal/hashlib/Hash.c @@ -0,0 +1,57 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/hashlib/Hash.h" + +#include "mbedtls/ssl.h" + +void common_hal_hashlib_hash_update(hashlib_hash_obj_t *self, const uint8_t *data, size_t datalen) { + if (self->hash_type == MBEDTLS_SSL_HASH_SHA1) { + mbedtls_sha1_update_ret(&self->sha1, data, datalen); + return; + } +} + +void common_hal_hashlib_hash_digest(hashlib_hash_obj_t *self, uint8_t *data, size_t datalen) { + if (datalen < common_hal_hashlib_hash_get_digest_size(self)) { + return; + } + if (self->hash_type == MBEDTLS_SSL_HASH_SHA1) { + // We copy the sha1 state so we can continue to update if needed or get + // the digest a second time. + mbedtls_sha1_context copy; + mbedtls_sha1_clone(©, &self->sha1); + mbedtls_sha1_finish_ret(&self->sha1, data); + mbedtls_sha1_clone(&self->sha1, ©); + } +} + +size_t common_hal_hashlib_hash_get_digest_size(hashlib_hash_obj_t *self) { + if (self->hash_type == MBEDTLS_SSL_HASH_SHA1) { + return 20; + } + return 0; +} diff --git a/py/ioctl.h b/ports/raspberrypi/common-hal/hashlib/Hash.h similarity index 68% rename from py/ioctl.h rename to ports/raspberrypi/common-hal/hashlib/Hash.h index 8c84835cc1..9792538e0a 100644 --- a/py/ioctl.h +++ b/ports/raspberrypi/common-hal/hashlib/Hash.h @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2013-2015 Damien P. George + * Copyright (c) 2022 Jeff Epler 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 @@ -23,16 +23,16 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_PY_IOCTL_H -#define MICROPY_INCLUDED_PY_IOCTL_H -#define MP_IOCTL_POLL (0x100 | 1) +#pragma once -// These values are compatible with Linux, which are in turn -// compatible with iBCS2 spec. -#define MP_IOCTL_POLL_RD (0x0001) -#define MP_IOCTL_POLL_WR (0x0004) -#define MP_IOCTL_POLL_ERR (0x0008) -#define MP_IOCTL_POLL_HUP (0x0010) +#include "mbedtls/sha1.h" -#endif // MICROPY_INCLUDED_PY_IOCTL_H +typedef struct { + mp_obj_base_t base; + union { + mbedtls_sha1_context sha1; + }; + // Of MBEDTLS_SSL_HASH_* + uint8_t hash_type; +} hashlib_hash_obj_t; diff --git a/ports/raspberrypi/common-hal/hashlib/__init__.c b/ports/raspberrypi/common-hal/hashlib/__init__.c new file mode 100644 index 0000000000..1ad116ea6c --- /dev/null +++ b/ports/raspberrypi/common-hal/hashlib/__init__.c @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/hashlib/__init__.h" + +#include "mbedtls/ssl.h" + + +bool common_hal_hashlib_new(hashlib_hash_obj_t *self, const char *algorithm) { + if (strcmp(algorithm, "sha1") == 0) { + self->hash_type = MBEDTLS_SSL_HASH_SHA1; + mbedtls_sha1_init(&self->sha1); + mbedtls_sha1_starts_ret(&self->sha1); + return true; + } + return false; +} diff --git a/ports/raspberrypi/common-hal/hashlib/__init__.h b/ports/raspberrypi/common-hal/hashlib/__init__.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.c b/ports/raspberrypi/common-hal/socketpool/Socket.c index 952f4ea7d8..37c37445de 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.c +++ b/ports/raspberrypi/common-hal/socketpool/Socket.c @@ -1080,7 +1080,7 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *socket, ret = lwip_raw_udp_receive(socket, (byte *)buf, len, NULL, NULL, &_errno); break; } - if (ret < 0) { + if (ret == (unsigned)-1) { return -_errno; } return ret; @@ -1089,7 +1089,7 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *socket, mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) { int received = socketpool_socket_recv_into(self, buf, len); if (received < 0) { - mp_raise_OSError(received); + mp_raise_OSError(-received); } return received; } diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 2e7ac2e1d8..09818956ea 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -401,6 +401,9 @@ CFLAGS += -DCIRCUITPY_STATUS_BAR=$(CIRCUITPY_STATUS_BAR) CIRCUITPY_STORAGE ?= 1 CFLAGS += -DCIRCUITPY_STORAGE=$(CIRCUITPY_STORAGE) +CIRCUITPY_STORAGE_EXTEND ?= $(CIRCUITPY_DUALBANK) +CFLAGS += -DCIRCUITPY_STORAGE_EXTEND=$(CIRCUITPY_STORAGE_EXTEND) + CIRCUITPY_STRUCT ?= 1 CFLAGS += -DCIRCUITPY_STRUCT=$(CIRCUITPY_STRUCT) diff --git a/py/gc.c b/py/gc.c index 826540d353..fc6bc90b67 100644 --- a/py/gc.c +++ b/py/gc.c @@ -138,7 +138,6 @@ void gc_init(void *start, void *end) { MP_STATE_MEM(gc_alloc_table_start) = (byte *)start; #if MICROPY_ENABLE_FINALISER - size_t gc_finaliser_table_byte_len = (MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; MP_STATE_MEM(gc_finaliser_table_start) = MP_STATE_MEM(gc_alloc_table_start) + MP_STATE_MEM(gc_alloc_table_byte_len) + 1; #endif @@ -147,18 +146,16 @@ void gc_init(void *start, void *end) { MP_STATE_MEM(gc_pool_end) = end; #if MICROPY_ENABLE_FINALISER + size_t gc_finaliser_table_byte_len = (MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; + (void)gc_finaliser_table_byte_len; // avoid unused variable diagnostic if asserts are disabled assert(MP_STATE_MEM(gc_pool_start) >= MP_STATE_MEM(gc_finaliser_table_start) + gc_finaliser_table_byte_len); #endif - // Clear ATBs plus one more byte. The extra byte might be read when we read the final ATB and - // then try to count its tail. Clearing the byte ensures it is 0 and ends the chain. Without an - // FTB, it'll just clear the pool byte early. - memset(MP_STATE_MEM(gc_alloc_table_start), 0, MP_STATE_MEM(gc_alloc_table_byte_len) + 1); - - #if MICROPY_ENABLE_FINALISER - // clear FTBs - memset(MP_STATE_MEM(gc_finaliser_table_start), 0, gc_finaliser_table_byte_len); - #endif + // Clear ATBs & finalisers (if enabled). This also clears the extra byte + // which appears between ATBs and finalisers that ensures every chain in + // the ATB terminates, rather than erroneously using bits from the + // finalisers. + memset(MP_STATE_MEM(gc_alloc_table_start), 0, MP_STATE_MEM(gc_pool_start) - MP_STATE_MEM(gc_alloc_table_start)); // Set first free ATB index to the start of the heap. for (size_t i = 0; i < MICROPY_ATB_INDICES; i++) { diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c index 9b44114a99..12853b3ac3 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.c +++ b/shared-bindings/_bleio/CharacteristicBuffer.c @@ -25,7 +25,7 @@ */ #include "py/mperrno.h" -#include "py/ioctl.h" +#include "py/stream.h" #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" @@ -138,15 +138,15 @@ STATIC mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t r check_for_deinit(self); raise_error_if_not_connected(self); mp_uint_t ret; - if (request == MP_IOCTL_POLL) { + if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; - if ((flags & MP_IOCTL_POLL_RD) && common_hal_bleio_characteristic_buffer_rx_characters_available(self) > 0) { - ret |= MP_IOCTL_POLL_RD; + if ((flags & MP_STREAM_POLL_RD) && common_hal_bleio_characteristic_buffer_rx_characters_available(self) > 0) { + ret |= MP_STREAM_POLL_RD; } // No writing provided. -// if ((flags & MP_IOCTL_POLL_WR) && common_hal_busio_uart_ready_to_tx(self)) { -// ret |= MP_IOCTL_POLL_WR; +// if ((flags & MP_STREAM_POLL_WR) && common_hal_busio_uart_ready_to_tx(self)) { +// ret |= MP_STREAM_POLL_WR; // } } else { *errcode = MP_EINVAL; diff --git a/shared-bindings/_bleio/PacketBuffer.c b/shared-bindings/_bleio/PacketBuffer.c index 8c6b017c9c..0ce74beff4 100644 --- a/shared-bindings/_bleio/PacketBuffer.c +++ b/shared-bindings/_bleio/PacketBuffer.c @@ -25,7 +25,7 @@ */ #include "py/mperrno.h" -#include "py/ioctl.h" +#include "py/stream.h" #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index a65984c3fb..5663254897 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -33,7 +33,7 @@ #include "shared/runtime/context_manager_helpers.h" #include "shared/runtime/interrupt_char.h" -#include "py/ioctl.h" +#include "py/stream.h" #include "py/objproperty.h" #include "py/objtype.h" #include "py/runtime.h" @@ -276,14 +276,14 @@ STATIC mp_uint_t busio_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t busio_uart_obj_t *self = native_uart(self_in); check_for_deinit(self); mp_uint_t ret; - if (request == MP_IOCTL_POLL) { + if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; - if ((flags & MP_IOCTL_POLL_RD) && common_hal_busio_uart_rx_characters_available(self) > 0) { - ret |= MP_IOCTL_POLL_RD; + if ((flags & MP_STREAM_POLL_RD) && common_hal_busio_uart_rx_characters_available(self) > 0) { + ret |= MP_STREAM_POLL_RD; } - if ((flags & MP_IOCTL_POLL_WR) && common_hal_busio_uart_ready_to_tx(self)) { - ret |= MP_IOCTL_POLL_WR; + if ((flags & MP_STREAM_POLL_WR) && common_hal_busio_uart_ready_to_tx(self)) { + ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; diff --git a/shared-bindings/dualbank/__init__.c b/shared-bindings/dualbank/__init__.c index 83933e889d..d3f75a4153 100644 --- a/shared-bindings/dualbank/__init__.c +++ b/shared-bindings/dualbank/__init__.c @@ -26,6 +26,10 @@ #include "shared-bindings/dualbank/__init__.h" +#if CIRCUITPY_STORAGE_EXTEND +#include "supervisor/flash.h" +#endif + //| """DUALBANK Module //| //| The `dualbank` module adds ability to update and switch @@ -55,6 +59,14 @@ //| """ //| ... +#if CIRCUITPY_STORAGE_EXTEND +STATIC void raise_error_if_storage_extended(void) { + if (supervisor_flash_get_extended()) { + mp_raise_msg_varg(&mp_type_RuntimeError, translate("%q is %q"), MP_QSTR_storage, MP_QSTR_extended); + } +} +#endif + //| def flash(buffer: ReadableBuffer, offset: int = 0) -> None: //| """Writes one of two app partitions at the given offset. //| @@ -70,6 +82,10 @@ STATIC mp_obj_t dualbank_flash(size_t n_args, const mp_obj_t *pos_args, mp_map_t { MP_QSTR_offset, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, }; + #if CIRCUITPY_STORAGE_EXTEND + raise_error_if_storage_extended(); + #endif + 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); @@ -94,6 +110,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(dualbank_flash_obj, 0, dualbank_flash); //| ... //| STATIC mp_obj_t dualbank_switch(void) { + #if CIRCUITPY_STORAGE_EXTEND + raise_error_if_storage_extended(); + #endif common_hal_dualbank_switch(); return mp_const_none; } diff --git a/shared-bindings/keypad/EventQueue.c b/shared-bindings/keypad/EventQueue.c index 615c051188..d09d5db129 100644 --- a/shared-bindings/keypad/EventQueue.c +++ b/shared-bindings/keypad/EventQueue.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ -#include "py/ioctl.h" +#include "py/stream.h" #include "py/mperrno.h" #include "py/objproperty.h" #include "py/runtime.h" @@ -147,8 +147,8 @@ STATIC mp_uint_t eventqueue_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t case MP_STREAM_POLL: { mp_uint_t flags = arg; mp_uint_t ret = 0; - if ((flags & MP_IOCTL_POLL_RD) && common_hal_keypad_eventqueue_get_length(self)) { - ret |= MP_IOCTL_POLL_RD; + if ((flags & MP_STREAM_POLL_RD) && common_hal_keypad_eventqueue_get_length(self)) { + ret |= MP_STREAM_POLL_RD; } return ret; } diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index 47c400aee3..5a4a2556e1 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -104,7 +104,11 @@ MP_PROPERTY_GETTER(mcu_processor_reset_reason_obj, //| temperature: Optional[float] //| """The on-chip temperature, in Celsius, as a float. (read-only) //| -//| Is `None` if the temperature is not available.""" +//| Is `None` if the temperature is not available. +//| +//| .. note :: On small SAMD21 builds without external flash, +//| the reported temperature has reduced accuracy and precision, to save code space. +//| """ STATIC mp_obj_t mcu_processor_get_temperature(mp_obj_t self) { float temperature = common_hal_mcu_processor_get_temperature(); return isnan(temperature) ? mp_const_none : mp_obj_new_float(temperature); diff --git a/shared-bindings/os/__init__.c b/shared-bindings/os/__init__.c index 1ccefaf0b2..4049c04722 100644 --- a/shared-bindings/os/__init__.c +++ b/shared-bindings/os/__init__.c @@ -248,6 +248,17 @@ STATIC mp_obj_t os_urandom(mp_obj_t size_in) { } MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); +//| def utime(path: str, times: Tuple[int, int]) -> None: +//| """Change the timestamp of a file.""" +//| ... +//| +STATIC mp_obj_t os_utime(mp_obj_t path_in, mp_obj_t times_in) { + const char *path = mp_obj_str_get_str(path_in); + common_hal_os_utime(path, times_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(os_utime_obj, os_utime); + STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) }, @@ -264,6 +275,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&os_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&os_remove_obj) }, // unlink aliases to remove + { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&os_utime_obj) }, { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&os_sync_obj) }, diff --git a/shared-bindings/os/__init__.h b/shared-bindings/os/__init__.h index 5a27f309b4..00d8c28a50 100644 --- a/shared-bindings/os/__init__.h +++ b/shared-bindings/os/__init__.h @@ -45,6 +45,7 @@ void common_hal_os_rename(const char *old_path, const char *new_path); void common_hal_os_rmdir(const char *path); mp_obj_t common_hal_os_stat(const char *path); mp_obj_t common_hal_os_statvfs(const char *path); +void common_hal_os_utime(const char *path, mp_obj_t times); // Returns true if data was correctly sourced from a true random number generator. bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length); diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 3661b61973..838395efb3 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -34,6 +34,7 @@ #include "py/runtime.h" #include "shared-bindings/storage/__init__.h" #include "supervisor/shared/translate/translate.h" +#include "supervisor/flash.h" //| """Storage management //| @@ -150,7 +151,7 @@ STATIC mp_obj_t storage_getmount(const mp_obj_t mnt_in) { } MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount); -//| def erase_filesystem() -> None: +//| def erase_filesystem(extended: Optional[bool] = None) -> None: //| """Erase and re-create the ``CIRCUITPY`` filesystem. //| //| On boards that present USB-visible ``CIRCUITPY`` drive (e.g., SAMD21 and SAMD51), @@ -160,16 +161,38 @@ MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount); //| This function can be called from the REPL when ``CIRCUITPY`` //| has become corrupted. //| +//| :param bool extended: On boards that support ``dualbank`` module +//| and the ``extended`` parameter, the ``CIRCUITPY`` storage can be +//| extended by setting this to `True`. If this isn't provided or +//| set to `None` (default), the existing configuration will be used. +//| //| .. warning:: All the data on ``CIRCUITPY`` will be lost, and //| CircuitPython will restart on certain boards.""" //| ... //| -STATIC mp_obj_t storage_erase_filesystem(void) { - common_hal_storage_erase_filesystem(); +STATIC mp_obj_t storage_erase_filesystem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_extended }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_extended, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + 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 CIRCUITPY_STORAGE_EXTEND + bool extended = (args[ARG_extended].u_obj == mp_const_none) ? supervisor_flash_get_extended() : mp_obj_is_true(args[ARG_extended].u_obj); + common_hal_storage_erase_filesystem(extended); + #else + if (mp_obj_is_true(args[ARG_extended].u_obj)) { + mp_raise_NotImplementedError_varg(translate("%q=%q"), MP_QSTR_extended, MP_QSTR_True); + } + common_hal_storage_erase_filesystem(false); + #endif + return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_0(storage_erase_filesystem_obj, storage_erase_filesystem); +MP_DEFINE_CONST_FUN_OBJ_KW(storage_erase_filesystem_obj, 0, storage_erase_filesystem); //| def disable_usb_drive() -> None: //| """Disable presenting ``CIRCUITPY`` as a USB mass storage device. diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index fbf492efab..ffe68c17c8 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -37,7 +37,7 @@ void common_hal_storage_umount_path(const char *path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); void common_hal_storage_remount(const char *path, bool readonly, bool disable_concurrent_write_protection); mp_obj_t common_hal_storage_getmount(const char *path); -void common_hal_storage_erase_filesystem(void); +void common_hal_storage_erase_filesystem(bool extended); bool common_hal_storage_disable_usb_drive(void); bool common_hal_storage_enable_usb_drive(void); diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c index a666a79461..2dfe29035e 100644 --- a/shared-bindings/terminalio/Terminal.c +++ b/shared-bindings/terminalio/Terminal.c @@ -29,7 +29,7 @@ #include "shared-bindings/terminalio/Terminal.h" #include "shared-bindings/util.h" -#include "py/ioctl.h" +#include "py/stream.h" #include "py/objproperty.h" #include "py/objstr.h" #include "py/runtime.h" @@ -111,11 +111,11 @@ STATIC mp_uint_t terminalio_terminal_write(mp_obj_t self_in, const void *buf_in, STATIC mp_uint_t terminalio_terminal_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; - if (request == MP_IOCTL_POLL) { + if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; - if ((flags & MP_IOCTL_POLL_WR) && common_hal_terminalio_terminal_ready_to_tx(self)) { - ret |= MP_IOCTL_POLL_WR; + if ((flags & MP_STREAM_POLL_WR) && common_hal_terminalio_terminal_ready_to_tx(self)) { + ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; diff --git a/shared-bindings/traceback/__init__.c b/shared-bindings/traceback/__init__.c index 566ac57218..eeb7bc458d 100644 --- a/shared-bindings/traceback/__init__.c +++ b/shared-bindings/traceback/__init__.c @@ -38,7 +38,45 @@ //| """ //| ... -STATIC void traceback_exception_common(mp_print_t *print, mp_obj_t value, mp_obj_t tb_obj, mp_obj_t limit_obj) { +STATIC void traceback_exception_common(bool is_print_exception, mp_print_t *print, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_exc, ARG_value, ARG_tb, ARG_limit, ARG_file, ARG_chain }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_value, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_tb, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_limit, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_file, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_chain, MP_ARG_BOOL, {.u_bool = true} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t value = args[ARG_value].u_obj; + if (value == MP_OBJ_NULL) { + value = args[ARG_exc].u_obj; + } + mp_obj_t tb_obj = args[ARG_tb].u_obj; + mp_obj_t limit_obj = args[ARG_limit].u_obj; + + if (args[ARG_file].u_obj != mp_const_none) { + if (!is_print_exception) { + #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE + mp_arg_error_terse_mismatch(); + #else + mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("unexpected keyword argument '%q'"), MP_QSTR_file); + #endif + + } + #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES + mp_get_stream_raise(args[ARG_file].u_obj, MP_STREAM_OP_WRITE); + print->data = MP_OBJ_TO_PTR(args[ARG_file].u_obj); + print->print_strn = mp_stream_write_adaptor; + #else + mp_raise_NotImplementedError(translate("file write is not available")); + #endif + } + if (!mp_obj_is_exception_instance(value)) { mp_raise_TypeError(translate("invalid exception")); } @@ -53,7 +91,9 @@ STATIC void traceback_exception_common(mp_print_t *print, mp_obj_t value, mp_obj mp_obj_exception_t *exc = mp_obj_exception_get_native(value); mp_obj_traceback_t *trace_backup = exc->traceback; - if (tb_obj != mp_const_none && print_tb) { + if (tb_obj == MP_OBJ_NULL) { + /* Print the traceback's exception as is */ + } else if (tb_obj != mp_const_none && print_tb) { exc->traceback = mp_arg_validate_type(tb_obj, &mp_type_traceback, MP_QSTR_tb); } else { exc->traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; @@ -64,14 +104,24 @@ STATIC void traceback_exception_common(mp_print_t *print, mp_obj_t value, mp_obj } //| def format_exception( -//| etype: Type[BaseException], -//| value: BaseException, -//| tb: TracebackType, +//| exc: BaseException | Type[BaseException], +//| /, +//| value: Optional[BaseException] = None, +//| tb: Optional[TracebackType] = None, //| limit: Optional[int] = None, //| chain: Optional[bool] = True, -//| ) -> None: +//| ) -> List[str]: //| """Format a stack trace and the exception information. //| +//| If the exception value is passed in ``exc``, then this exception value and its +//| associated traceback are used. This is compatible with CPython 3.10 and newer. +//| +//| If the exception value is passed in ``value``, then any value passed in for +//| ``exc`` is ignored. ``value`` is used as the exception value and the +//| traceback in the ``tb`` argument is used. In this case, if ``tb`` is None, +//| no traceback will be shown. This is compatible with CPython 3.5 and +//| newer. +//| //| The arguments have the same meaning as the corresponding arguments //| to print_exception(). The return value is a list of strings, each //| ending in a newline and some containing internal newlines. When @@ -80,54 +130,50 @@ STATIC void traceback_exception_common(mp_print_t *print, mp_obj_t value, mp_obj //| //| .. note:: Setting ``chain`` will have no effect as chained exceptions are not yet implemented. //| -//| :param Type[BaseException] etype: This is ignored and inferred from the type of ``value``. -//| :param BaseException value: The exception. Must be an instance of `BaseException`. -//| :param TracebackType tb: The traceback object. If `None`, the traceback will not be printed. +//| :param exc: The exception. Must be an instance of `BaseException`. Unused if value is specified. +//| :param value: If specified, is used in place of ``exc``. +//| :param TracebackType tb: When value is alsp specified, ``tb`` is used in place of the exception's own traceback. If `None`, the traceback will not be printed. //| :param int limit: Print up to limit stack trace entries (starting from the caller’s frame) if limit is positive. //| Otherwise, print the last ``abs(limit)`` entries. If limit is omitted or None, all entries are printed. //| :param bool chain: If `True` then chained exceptions will be printed (note: not yet implemented). -//| //| """ -//| ... //| STATIC mp_obj_t traceback_format_exception(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_etype, ARG_value, ARG_tb, ARG_limit, ARG_chain }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_etype, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_value, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_tb, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_limit, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_chain, MP_ARG_BOOL, {.u_bool = true} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - mp_print_t print; vstr_t vstr; vstr_init_print(&vstr, 0, &print); - traceback_exception_common(&print, args[ARG_value].u_obj, args[ARG_tb].u_obj, args[ARG_limit].u_obj); - return mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + traceback_exception_common(false, &print, n_args, pos_args, kw_args); + mp_obj_t output = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + return mp_obj_new_list(1, &output); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(traceback_format_exception_obj, 0, traceback_format_exception); //| def print_exception( -//| etype: Type[BaseException], -//| value: BaseException, -//| tb: TracebackType, +//| exc: BaseException | Type[BaseException], +//| /, +//| value: Optional[BaseException] = None, +//| tb: Optional[TracebackType] = None, //| limit: Optional[int] = None, //| file: Optional[io.FileIO] = None, //| chain: Optional[bool] = True, //| ) -> None: -//| //| """Prints exception information and stack trace entries. //| +//| If the exception value is passed in ``exc``, then this exception value and its +//| associated traceback are used. This is compatible with CPython 3.10 and newer. +//| +//| If the exception value is passed in ``value``, then any value passed in for +//| ``exc`` is ignored. ``value`` is used as the exception value and the +//| traceback in the ``tb`` argument is used. In this case, if ``tb`` is None, +//| no traceback will be shown. This is compatible with CPython 3.5 and +//| newer. +//| //| .. note:: Setting ``chain`` will have no effect as chained exceptions are not yet implemented. //| -//| :param Type[BaseException] etype: This is ignored and inferred from the type of ``value``. -//| :param BaseException value: The exception. Must be an instance of `BaseException`. -//| :param TracebackType tb: The traceback object. If `None`, the traceback will not be printed. +//| :param exc: The exception. Must be an instance of `BaseException`. Unused if value is specified. +//| :param value: If specified, is used in place of ``exc``. +//| :param tb: When value is alsp specified, ``tb`` is used in place of the exception's own traceback. If `None`, the traceback will not be printed. //| :param int limit: Print up to limit stack trace entries (starting from the caller’s frame) if limit is positive. //| Otherwise, print the last ``abs(limit)`` entries. If limit is omitted or None, all entries are printed. //| :param io.FileIO file: If file is omitted or `None`, the output goes to `sys.stderr`; otherwise it should be an open @@ -139,31 +185,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(traceback_format_exception_obj, 0, traceback_f //| STATIC mp_obj_t traceback_print_exception(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_etype, ARG_value, ARG_tb, ARG_limit, ARG_file, ARG_chain }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_etype, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_value, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_tb, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_limit, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_file, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_chain, MP_ARG_BOOL, {.u_bool = true} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - mp_print_t print = mp_plat_print; - if (args[ARG_file].u_obj != mp_const_none) { - #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES - mp_get_stream_raise(args[ARG_file].u_obj, MP_STREAM_OP_WRITE); - print.data = MP_OBJ_TO_PTR(args[ARG_file].u_obj); - print.print_strn = mp_stream_write_adaptor; - #else - mp_raise_NotImplementedError(translate("file write is not available")); - #endif - } - - traceback_exception_common(&print, args[ARG_value].u_obj, args[ARG_tb].u_obj, args[ARG_limit].u_obj); + traceback_exception_common(true, &print, n_args, pos_args, kw_args); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(traceback_print_exception_obj, 0, traceback_print_exception); diff --git a/shared-bindings/usb_cdc/Serial.c b/shared-bindings/usb_cdc/Serial.c index df96debe7f..9fe6cafd5f 100644 --- a/shared-bindings/usb_cdc/Serial.c +++ b/shared-bindings/usb_cdc/Serial.c @@ -29,7 +29,7 @@ #include "shared-bindings/usb_cdc/Serial.h" #include "shared-bindings/util.h" -#include "py/ioctl.h" +#include "py/stream.h" #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" @@ -114,14 +114,14 @@ STATIC mp_uint_t usb_cdc_serial_ioctl_stream(mp_obj_t self_in, mp_uint_t request usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret = 0; switch (request) { - case MP_IOCTL_POLL: { + case MP_STREAM_POLL: { mp_uint_t flags = arg; ret = 0; - if ((flags & MP_IOCTL_POLL_RD) && common_hal_usb_cdc_serial_get_in_waiting(self) > 0) { - ret |= MP_IOCTL_POLL_RD; + if ((flags & MP_STREAM_POLL_RD) && common_hal_usb_cdc_serial_get_in_waiting(self) > 0) { + ret |= MP_STREAM_POLL_RD; } - if ((flags & MP_IOCTL_POLL_WR) && common_hal_usb_cdc_serial_get_out_waiting(self) == 0) { - ret |= MP_IOCTL_POLL_WR; + if ((flags & MP_STREAM_POLL_WR) && common_hal_usb_cdc_serial_get_out_waiting(self) == 0) { + ret |= MP_STREAM_POLL_WR; } break; } diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c index b63843e8dd..ca07c8695a 100644 --- a/shared-bindings/usb_midi/PortIn.c +++ b/shared-bindings/usb_midi/PortIn.c @@ -29,7 +29,7 @@ #include "shared-bindings/usb_midi/PortIn.h" #include "shared-bindings/util.h" -#include "py/ioctl.h" +#include "py/stream.h" #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" @@ -81,11 +81,11 @@ STATIC mp_uint_t usb_midi_portin_read(mp_obj_t self_in, void *buf_in, mp_uint_t STATIC mp_uint_t usb_midi_portin_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { usb_midi_portin_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; - if (request == MP_IOCTL_POLL) { + if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; - if ((flags & MP_IOCTL_POLL_RD) && common_hal_usb_midi_portin_bytes_available(self) > 0) { - ret |= MP_IOCTL_POLL_RD; + if ((flags & MP_STREAM_POLL_RD) && common_hal_usb_midi_portin_bytes_available(self) > 0) { + ret |= MP_STREAM_POLL_RD; } } else { *errcode = MP_EINVAL; diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c index 5888045b79..f1f61f948a 100644 --- a/shared-bindings/usb_midi/PortOut.c +++ b/shared-bindings/usb_midi/PortOut.c @@ -29,7 +29,7 @@ #include "shared-bindings/usb_midi/PortOut.h" #include "shared-bindings/util.h" -#include "py/ioctl.h" +#include "py/stream.h" #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" @@ -64,11 +64,11 @@ STATIC mp_uint_t usb_midi_portout_write(mp_obj_t self_in, const void *buf_in, mp STATIC mp_uint_t usb_midi_portout_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { usb_midi_portout_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; - if (request == MP_IOCTL_POLL) { + if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; ret = 0; - if ((flags & MP_IOCTL_POLL_WR) && common_hal_usb_midi_portout_ready_to_tx(self)) { - ret |= MP_IOCTL_POLL_WR; + if ((flags & MP_STREAM_POLL_WR) && common_hal_usb_midi_portout_ready_to_tx(self)) { + ret |= MP_STREAM_POLL_WR; } } else { *errcode = MP_EINVAL; diff --git a/shared-module/dotenv/__init__.c b/shared-module/dotenv/__init__.c index be8f2353de..ead7c6561b 100644 --- a/shared-module/dotenv/__init__.c +++ b/shared-module/dotenv/__init__.c @@ -29,6 +29,7 @@ #include "shared-bindings/dotenv/__init__.h" +#include "py/misc.h" #include "py/mpstate.h" #include "py/objstr.h" #include "supervisor/filesystem.h" @@ -272,10 +273,17 @@ mp_obj_t common_hal_dotenv_get_key(const char *path, const char *key) { return mp_const_none; } if ((size_t)actual_len >= sizeof(value)) { - mp_obj_str_t *str = MP_OBJ_TO_PTR(mp_obj_new_str_copy(&mp_type_str, NULL, actual_len + 1)); - dotenv_get_key(path, key, (char *)str->data, actual_len + 1); - str->hash = qstr_compute_hash(str->data, actual_len); - return MP_OBJ_FROM_PTR(str); + byte *buf = m_new(byte, actual_len + 1); + dotenv_get_key(path, key, (char *)buf, actual_len); + buf[actual_len] = 0; + + mp_obj_str_t *o = m_new_obj(mp_obj_str_t); + o->base.type = &mp_type_str; + o->len = actual_len; + o->data = buf; + o->hash = qstr_compute_hash(buf, actual_len); + + return MP_OBJ_FROM_PTR(o); } return mp_obj_new_str(value, actual_len); } diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index 35933ebaf6..200fcb2f61 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -226,3 +226,10 @@ mp_obj_t common_hal_os_statvfs(const char *path) { } return mp_vfs_proxy_call(vfs, MP_QSTR_statvfs, 1, &path_out); } + +void common_hal_os_utime(const char *path, mp_obj_t times) { + mp_obj_t args[2]; + mp_vfs_mount_t *vfs = lookup_path(path, &args[0]); + args[1] = times; + mp_vfs_proxy_call(vfs, MP_QSTR_utime, 2, args); +} diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 8806b7c8c6..7b6eec7e1b 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -267,11 +267,14 @@ void common_hal_storage_remount(const char *mount_path, bool readonly, bool disa filesystem_set_internal_concurrent_write_protection(!disable_concurrent_write_protection); } -void common_hal_storage_erase_filesystem(void) { +void common_hal_storage_erase_filesystem(bool extended) { #if CIRCUITPY_USB usb_disconnect(); #endif mp_hal_delay_ms(1000); + #if CIRCUITPY_STORAGE_EXTEND + supervisor_flash_set_extended(extended); + #endif (void)filesystem_init(false, true); // Force a re-format. Ignore failure. common_hal_mcu_reset(); // We won't actually get here, since we're resetting. diff --git a/shared/libc/string0.c b/shared/libc/string0.c index 86e7cc5960..92b063c552 100644 --- a/shared/libc/string0.c +++ b/shared/libc/string0.c @@ -28,6 +28,8 @@ #include #include +#include "py/mpconfig.h" + #ifndef likely #define likely(x) __builtin_expect((x), 1) #endif @@ -35,6 +37,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" void *memcpy(void *dst, const void *src, size_t n) { +#if CIRCUITPY_FULL_BUILD if (likely(!(((uintptr_t)dst) & 3) && !(((uintptr_t)src) & 3))) { // pointers aligned uint32_t *d = dst; @@ -56,7 +59,9 @@ void *memcpy(void *dst, const void *src, size_t n) { // copy byte *((uint8_t*)d) = *((const uint8_t*)s); } - } else { + } else +#endif + { // unaligned access, copy bytes uint8_t *d = dst; const uint8_t *s = src; @@ -93,6 +98,7 @@ void *memmove(void *dest, const void *src, size_t n) { } void *memset(void *s, int c, size_t n) { +#if CIRCUITPY_FULL_BUILD if (c == 0 && ((uintptr_t)s & 3) == 0) { // aligned store of 0 uint32_t *s32 = s; @@ -106,7 +112,9 @@ void *memset(void *s, int c, size_t n) { if (n & 1) { *((uint8_t*)s32) = 0; } - } else { + } else +#endif + { uint8_t *s2 = s; for (; n > 0; n--) { *s2++ = c; diff --git a/supervisor/flash.h b/supervisor/flash.h index 21d76c9984..5154cb8598 100644 --- a/supervisor/flash.h +++ b/supervisor/flash.h @@ -50,4 +50,8 @@ void supervisor_flash_init_vfs(struct _fs_user_mount_t *vfs); void supervisor_flash_flush(void); void supervisor_flash_release_cache(void); +void supervisor_flash_set_extended(bool extended); +bool supervisor_flash_get_extended(void); +void supervisor_flash_update_extended(void); + #endif // MICROPY_INCLUDED_SUPERVISOR_FLASH_H diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index 283849adc3..01aba0a9ac 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -143,16 +143,22 @@ bool filesystem_init(bool create_allowed, bool force_create) { } else if (res != FR_OK) { return false; } + vfs->str = "/"; vfs->len = 1; vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); vfs->next = NULL; + MP_STATE_VM(vfs_mount_table) = vfs; // The current directory is used as the boot up directory. // It is set to the internal flash filesystem by default. MP_STATE_PORT(vfs_cur) = vfs; + #if CIRCUITPY_STORAGE_EXTEND + supervisor_flash_update_extended(); + #endif + return true; } diff --git a/tests/circuitpython/dotenv_test.env b/tests/circuitpython/dotenv_test.env index e3bc23d6ce..63753b0ea4 100644 --- a/tests/circuitpython/dotenv_test.env +++ b/tests/circuitpython/dotenv_test.env @@ -23,3 +23,15 @@ quoted_then_comment='value'#comment hash_with_spaces=#value value aa🐍bb=key with emoji value_with_emoji=aa🐍bb +sz0=x +sz1=xx +sz2=xxxx +sz3=xxxxxxxx +sz4=xxxxxxxxxxxxxxxx +sz5=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +sz6=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +sz7=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +sz8=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +sz9=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +sz10=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +sz11=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/tests/circuitpython/dotenv_test.py b/tests/circuitpython/dotenv_test.py index f217b72dbe..109a3bf221 100644 --- a/tests/circuitpython/dotenv_test.py +++ b/tests/circuitpython/dotenv_test.py @@ -25,3 +25,7 @@ print(f"quoted_then_comment={dotenv.get_key(FILE, 'quoted_then_comment')}") print(f"hash_with_spaces={dotenv.get_key(FILE, 'hash_with_spaces')}") print(f"aa🐍bb={dotenv.get_key(FILE, 'aa🐍bb')}") print(f"value_with_emoji={dotenv.get_key(FILE, 'value_with_emoji')}") + +for i in range(12): + key = f"sz{i}" + print(f"len({key})={len(dotenv.get_key(FILE, key))}") diff --git a/tests/circuitpython/dotenv_test.py.exp b/tests/circuitpython/dotenv_test.py.exp index d67d570999..e0ed5f1505 100644 --- a/tests/circuitpython/dotenv_test.py.exp +++ b/tests/circuitpython/dotenv_test.py.exp @@ -21,3 +21,15 @@ quoted_then_comment=value hash_with_spaces=#value value aa🐍bb=key with emoji value_with_emoji=aa🐍bb +len(sz0)=1 +len(sz1)=2 +len(sz2)=4 +len(sz3)=8 +len(sz4)=16 +len(sz5)=32 +len(sz6)=64 +len(sz7)=128 +len(sz8)=256 +len(sz9)=512 +len(sz10)=1024 +len(sz11)=2048 diff --git a/tests/circuitpython/traceback_test.py b/tests/circuitpython/traceback_test.py index 6ae73db6ae..17c54c857a 100644 --- a/tests/circuitpython/traceback_test.py +++ b/tests/circuitpython/traceback_test.py @@ -15,13 +15,13 @@ except Exception as exc: print("\nNo Trace:") traceback.print_exception(None, exc, None) print("\nDefault Trace:") - traceback.print_exception(None, exc, exc.__traceback__) + traceback.print_exception(exc) print("\nLimit=1 Trace:") traceback.print_exception(None, exc, exc.__traceback__, limit=1) print("\nLimit=0 Trace:") traceback.print_exception(None, exc, exc.__traceback__, limit=0) print("\nLimit=-1 Trace:") - traceback.print_exception(None, exc, exc.__traceback__, limit=-1) + print("".join(traceback.format_exception(None, exc, exc.__traceback__, limit=-1)), end="") class NonNativeException(Exception): diff --git a/tools/ci_set_matrix.py b/tools/ci_set_matrix.py old mode 100644 new mode 100755 index 0ae6010ac9..f22840fad7 --- a/tools/ci_set_matrix.py +++ b/tools/ci_set_matrix.py @@ -12,6 +12,13 @@ on the event that triggered run. Pull request runs will compare to the base branch while pushes will compare to the current ref. We override this for the adafruit/circuitpython repo so we build all docs/boards for pushes. +When making changes to the script it is useful to manually test it. +You can for instance run +```shell +tools/ci_set_matrix ports/raspberrypi/common-hal/socket/SSLSocket.c +``` +and (at the time this comment was written) get a series of messages indicating +that only the single board raspberry_pi_pico_w would be built. """ import re @@ -19,9 +26,21 @@ import os import sys import json import yaml +import pathlib +from concurrent.futures import ThreadPoolExecutor + +tools_dir = pathlib.Path(__file__).resolve().parent +top_dir = tools_dir.parent + +sys.path.insert(0, str(tools_dir / "adabot")) +sys.path.insert(0, str(top_dir / "docs")) import build_board_info -from shared_bindings_matrix import get_settings_from_makefile +from shared_bindings_matrix import ( + get_settings_from_makefile, + SUPPORTED_PORTS, + all_ports_all_boards, +) PORT_TO_ARCH = { "atmel-samd": "arm", @@ -40,12 +59,17 @@ IGNORE = [ "tools/ci_check_duplicate_usb_vid_pid.py", ] -changed_files = {} -try: - changed_files = json.loads(os.environ["CHANGED_FILES"]) -except json.decoder.JSONDecodeError as exc: - if exc.msg != "Expecting value": - raise +if len(sys.argv) > 1: + print("Using files list on commandline") + changed_files = sys.argv[1:] +else: + c = os.environ["CHANGED_FILES"] + if c == "": + print("CHANGED_FILES is in environment, but value is empty") + changed_files = [] + else: + print("Using files list in CHANGED_FILES") + changed_files = json.loads(os.environ["CHANGED_FILES"]) def set_output(name, value): @@ -53,7 +77,7 @@ def set_output(name, value): with open(os.environ["GITHUB_OUTPUT"], "at") as f: print(f"{name}={value}", file=f) else: - print("Would set GitHub actions output {name} to '{value}'") + print(f"Would set GitHub actions output {name} to '{value}'") def set_boards_to_build(build_all): @@ -74,6 +98,20 @@ def set_boards_to_build(build_all): port_to_boards[port].add(board_id) board_to_port[board_id] = port + def compute_board_settings(boards): + need = set(boards) - set(board_settings.keys()) + if not need: + return + + def get_settings(board): + return ( + board, + get_settings_from_makefile(str(top_dir / "ports" / board_to_port[board]), board), + ) + + with ThreadPoolExecutor(max_workers=os.cpu_count()) as ex: + board_settings.update(ex.map(get_settings, need)) + boards_to_build = all_board_ids if not build_all: @@ -81,7 +119,7 @@ def set_boards_to_build(build_all): board_pattern = re.compile(r"^ports/[^/]+/boards/([^/]+)/") port_pattern = re.compile(r"^ports/([^/]+)/") module_pattern = re.compile( - r"^(ports/[^/]+/common-hal|shared-bindings|shared-module)/([^/]+)/" + r"^(ports/[^/]+/(?:common-hal|bindings)|shared-bindings|shared-module)/([^/]+)/" ) for p in changed_files: # See if it is board specific @@ -93,9 +131,9 @@ def set_boards_to_build(build_all): # See if it is port specific port_matches = port_pattern.search(p) + port = port_matches.group(1) if port_matches else None module_matches = module_pattern.search(p) - if port_matches and not module_matches: - port = port_matches.group(1) + if port and not module_matches: if port != "unix": boards_to_build.update(port_to_boards[port]) continue @@ -111,11 +149,12 @@ def set_boards_to_build(build_all): # As a (nearly) last resort, for some certain files, we compute the settings from the # makefile for each board and determine whether to build them that way. if p.startswith("frozen") or p.startswith("supervisor") or module_matches: - for board in all_board_ids: - if board not in board_settings: - board_settings[board] = get_settings_from_makefile( - "../ports/" + board_to_port[board], board - ) + if port: + board_ids = port_to_boards[port] + else: + board_ids = all_board_ids + compute_board_settings(board_ids) + for board in board_ids: settings = board_settings[board] # Check frozen files to see if they are in each board.