diff options
Diffstat (limited to 'ports')
50 files changed, 828 insertions, 346 deletions
diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk index a5722c9ad..697ec02c3 100644 --- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk +++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk @@ -11,3 +11,4 @@ LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 SUPEROPT_GC = 0 +SUPEROPT_VM = 0 diff --git a/ports/atmel-samd/boards/dynalora_usb/board.c b/ports/atmel-samd/boards/dynalora_usb/board.c new file mode 100644 index 000000000..84960e73c --- /dev/null +++ b/ports/atmel-samd/boards/dynalora_usb/board.c @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 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 "supervisor/board.h" + +void board_init(void) { +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.h b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.h new file mode 100644 index 000000000..12359ce8f --- /dev/null +++ b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.h @@ -0,0 +1,36 @@ +#define MICROPY_HW_BOARD_NAME "DynaLoRa_USB" +#define MICROPY_HW_MCU_NAME "samd21e18" + +#define MICROPY_HW_LED_STATUS (&pin_PA27) +#define MICROPY_HW_NEOPIXEL (&pin_PA19) + +#define SPI_FLASH_MOSI_PIN &pin_PA04 +#define SPI_FLASH_MISO_PIN &pin_PA05 +#define SPI_FLASH_SCK_PIN &pin_PA07 +#define SPI_FLASH_CS_PIN &pin_PA06 + +// These are pins not to reset. +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) +#define MICROPY_PORT_C (0) + +#define DEFAULT_I2C_BUS_SCL (&pin_PA01) +#define DEFAULT_I2C_BUS_SDA (&pin_PA00) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA17) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA16) +#define DEFAULT_SPI_BUS_MISO (&pin_PA18) + +#define DEFAULT_UART_BUS_RX (&pin_PA00) +#define DEFAULT_UART_BUS_TX (&pin_PA01) + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA23 1 +#define IGNORE_PIN_PA24 1 + +// Not connected +#define IGNORE_PIN_PA08 1 +#define IGNORE_PIN_PA14 1 +#define IGNORE_PIN_PA21 1 +#define IGNORE_PIN_PA22 1 +#define IGNORE_PIN_PA28 1 diff --git a/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk new file mode 100644 index 000000000..ac14e7395 --- /dev/null +++ b/ports/atmel-samd/boards/dynalora_usb/mpconfigboard.mk @@ -0,0 +1,39 @@ +USB_VID = 0x04D8 +USB_PID = 0xEA2A +USB_PRODUCT = "DynaLoRa_USB" +USB_MANUFACTURER = "BHDynamics" + +CHIP_VARIANT = SAMD21E18A +CHIP_FAMILY = samd21 + +SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = GD25Q32C +LONGINT_IMPL = MPZ + +CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_FREQUENCYIO = 0 +CIRCUITPY_GAMEPAD = 0 +CIRCUITPY_DISPLAYIO = 0 +CIRCUITPY_FULL_BUILD = 0 + +SUPEROPT_GC = 0 + +CFLAGS_BOARD = --param max-inline-insns-auto=15 +ifeq ($(TRANSLATION), zh_Latn_pinyin) +RELEASE_NEEDS_CLEAN_BUILD = 1 +CFLAGS_INLINE_LIMIT = 35 +endif +ifeq ($(TRANSLATION), ja) +RELEASE_NEEDS_CLEAN_BUILD = 1 +CFLAGS_INLINE_LIMIT = 35 +endif +ifeq ($(TRANSLATION), de_DE) +RELEASE_NEEDS_CLEAN_BUILD = 1 +CFLAGS_INLINE_LIMIT = 35 +SUPEROPT_VM = 0 +endif + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_RFM9x +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SD diff --git a/ports/atmel-samd/boards/dynalora_usb/pins.c b/ports/atmel-samd/boards/dynalora_usb/pins.c new file mode 100644 index 000000000..25f498543 --- /dev/null +++ b/ports/atmel-samd/boards/dynalora_usb/pins.c @@ -0,0 +1,41 @@ +#include "shared-bindings/board/__init__.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA30) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA31) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA02) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_RADIO_CS), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RADIO_INT), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_RADIO_RESET), MP_ROM_PTR(&pin_PA10) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_PA03) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA00) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA00) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI1), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_MISO1), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_SCK1), MP_ROM_PTR(&pin_PA01) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA27) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_PA15) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/seeeduino_xiao/mpconfigboard.mk b/ports/atmel-samd/boards/seeeduino_xiao/mpconfigboard.mk index bedec87f4..6bbd84235 100644 --- a/ports/atmel-samd/boards/seeeduino_xiao/mpconfigboard.mk +++ b/ports/atmel-samd/boards/seeeduino_xiao/mpconfigboard.mk @@ -11,3 +11,4 @@ LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 SUPEROPT_GC = 0 +SUPEROPT_VM = 0 diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk index 735d42297..1f88fbead 100644 --- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk @@ -11,14 +11,5 @@ LONGINT_IMPL = NONE CIRCUITPY_FULL_BUILD = 0 SUPEROPT_GC = 0 - -CFLAGS_BOARD = --param max-inline-insns-auto=15 -ifeq ($(TRANSLATION), zh_Latn_pinyin) -RELEASE_NEEDS_CLEAN_BUILD = 1 -CFLAGS_INLINE_LIMIT = 35 -endif -ifeq ($(TRANSLATION), de_DE) -RELEASE_NEEDS_CLEAN_BUILD = 1 -CFLAGS_INLINE_LIMIT = 35 SUPEROPT_VM = 0 -endif +CFLAGS_INLINE_LIMIT = 45 diff --git a/ports/atmel-samd/common-hal/_pew/PewPew.c b/ports/atmel-samd/common-hal/_pew/PewPew.c index cfdfe75d8..1e7561ac8 100644 --- a/ports/atmel-samd/common-hal/_pew/PewPew.c +++ b/ports/atmel-samd/common-hal/_pew/PewPew.c @@ -40,6 +40,7 @@ static uint8_t pewpew_tc_index = 0xff; +static volatile uint16_t pewpew_ticks = 0; void pewpew_interrupt_handler(uint8_t index) { @@ -52,6 +53,7 @@ void pewpew_interrupt_handler(uint8_t index) { } pew_tick(); + ++pewpew_ticks; // Clear the interrupt bit. tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; @@ -123,3 +125,7 @@ void pew_reset(void) { } MP_STATE_VM(pew_singleton) = NULL; } + +uint16_t pew_get_ticks() { + return pewpew_ticks; +} diff --git a/ports/atmel-samd/common-hal/_pew/PewPew.h b/ports/atmel-samd/common-hal/_pew/PewPew.h index da1cae0a2..a9c3b6626 100644 --- a/ports/atmel-samd/common-hal/_pew/PewPew.h +++ b/ports/atmel-samd/common-hal/_pew/PewPew.h @@ -44,5 +44,6 @@ typedef struct { void pew_init(void); void pewpew_interrupt_handler(uint8_t index); void pew_reset(void); +uint16_t pew_get_ticks(void); #endif // MICROPY_INCLUDED_PEW_PEWPEW_H diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index ffe74a274..2551f7bf1 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -97,7 +97,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (!gpio_get_pin_level(sda->number) || !gpio_get_pin_level(scl->number)) { reset_pin_number(sda->number); reset_pin_number(scl->number); - mp_raise_RuntimeError(translate("SDA or SCL needs a pull up")); + mp_raise_RuntimeError(translate("No pull up found on SDA or SCL; check your wiring")); } #endif diff --git a/ports/atmel-samd/common-hal/supervisor/Runtime.c b/ports/atmel-samd/common-hal/supervisor/Runtime.c index 6be38f216..974f26cec 100755 --- a/ports/atmel-samd/common-hal/supervisor/Runtime.c +++ b/ports/atmel-samd/common-hal/supervisor/Runtime.c @@ -28,10 +28,10 @@ #include "shared-bindings/supervisor/Runtime.h" #include "supervisor/serial.h" -bool common_hal_get_serial_connected(void) { +bool common_hal_supervisor_runtime_get_serial_connected(void) { return (bool) serial_connected(); } -bool common_hal_get_serial_bytes_available(void) { +bool common_hal_supervisor_runtime_get_serial_bytes_available(void) { return (bool) serial_bytes_available(); } diff --git a/ports/cxd56/common-hal/supervisor/Runtime.c b/ports/cxd56/common-hal/supervisor/Runtime.c index a0d9e70ab..eeeb1430f 100755 --- a/ports/cxd56/common-hal/supervisor/Runtime.c +++ b/ports/cxd56/common-hal/supervisor/Runtime.c @@ -27,10 +27,10 @@ #include "shared-bindings/supervisor/Runtime.h" #include "supervisor/serial.h" -bool common_hal_get_serial_connected(void) { +bool common_hal_supervisor_runtime_get_serial_connected(void) { return (bool) serial_connected(); } -bool common_hal_get_serial_bytes_available(void) { +bool common_hal_supervisor_runtime_get_serial_bytes_available(void) { return (bool) serial_bytes_available(); } diff --git a/ports/esp32s2/Makefile b/ports/esp32s2/Makefile index aac934782..b4ff0612b 100644 --- a/ports/esp32s2/Makefile +++ b/ports/esp32s2/Makefile @@ -164,7 +164,9 @@ LIBS += -lm endif # TinyUSB defines -CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S2 -DCFG_TUSB_OS=OPT_OS_FREERTOS -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128 +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S2 -DCFG_TUSB_OS=OPT_OS_FREERTOS -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 +CFLAGS += -DCFG_TUD_MSC_BUFSIZE=4096 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128 +CFLAGS += -DCFG_TUD_VENDOR_RX_BUFSIZE=128 -DCFG_TUD_VENDOR_TX_BUFSIZE=128 ###################################### diff --git a/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk index 2dce03881..52c63cb9c 100644 --- a/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk +++ b/ports/esp32s2/boards/espressif_kaluga_1/mpconfigboard.mk @@ -14,4 +14,10 @@ CIRCUITPY_ESP_FLASH_MODE=dio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB +# We only have enough endpoints available in hardware to +# enable ONE of these at a time. +CIRCUITPY_USB_MIDI = 1 +CIRCUITPY_USB_HID = 0 +CIRCUITPY_USB_VENDOR = 0 + CIRCUITPY_MODULE=wrover diff --git a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c index aaef97c7d..4aa7b3b24 100644 --- a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c +++ b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/board.c @@ -27,6 +27,109 @@ #include "supervisor/board.h" #include "mpconfigboard.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +#define DELAY 0x80 + +// display init sequence according to LilyGO example app +uint8_t display_init_sequence[] = { + // sw reset + 0x01, 0 | DELAY, 150, + // sleep out + 0x11, 0 | DELAY, 255, + // normal display mode on + 0x13, 0, + // display and color format settings + 0x36, 1, 0x08, + 0xB6, 2, 0x0A, 0x82, + 0x3A, 1 | DELAY, 0x55, 10, + // ST7789V frame rate setting + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + // voltages: VGH / VGL + 0xB7, 1, 0x35, + // ST7789V power setting + 0xBB, 1, 0x28, + 0xC0, 1, 0x0C, + 0xC2, 2, 0x01, 0xFF, + 0xC3, 1, 0x10, + 0xC4, 1, 0x20, + 0xC6, 1, 0x0F, + 0xD0, 2, 0xA4, 0xA1, + // ST7789V gamma setting + 0xE0, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17, + 0xE1, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E, + 0x21, 0, + // display on + 0x29, 0 | DELAY, 255, + }; + +static void display_init(void) { + busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus; + + common_hal_busio_spi_construct( + spi, + &pin_GPIO36, // CLK + &pin_GPIO35, // MOSI + NULL // MISO not connected + ); + + common_hal_busio_spi_never_reset(spi); + + displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus; + bus->base.type = &displayio_fourwire_type; + + common_hal_displayio_fourwire_construct( + bus, + spi, + &pin_GPIO37, // DC + &pin_GPIO34, // CS + &pin_GPIO38, // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + + displayio_display_obj_t* display = &displays[0].display; + display->base.type = &displayio_display_type; + + // workaround as board_init() is called before reset_port() in main.c + pwmout_reset(); + + common_hal_displayio_display_construct( + display, + bus, + 240, // width (after rotation) + 135, // height (after rotation) + 52, // column start + 40, // row start + 90, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + 0x37, // set vertical scroll command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO33, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness (ignored) + false, // auto_brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false // SH1107_addressing + ); + + common_hal_never_reset_pin(&pin_GPIO33); // backlight pin +} void board_init(void) { // USB @@ -38,6 +141,9 @@ void board_init(void) { common_hal_never_reset_pin(&pin_GPIO43); common_hal_never_reset_pin(&pin_GPIO44); #endif /* DEBUG */ + + // Display + display_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c index bda0fd227..a30c6797a 100644 --- a/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c +++ b/ports/esp32s2/boards/lilygo_ttgo_t8_s2_st7789/pins.c @@ -1,4 +1,5 @@ #include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, @@ -41,13 +42,13 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO10) }, // 1.14 inch LCD ST7789 - { MP_ROM_QSTR(MP_QSTR_LCD_MISO), MP_ROM_PTR(&pin_GPIO4) }, { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO35) }, { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO36) }, { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO34) }, { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO38) }, { MP_ROM_QSTR(MP_QSTR_LCD_BCKL), MP_ROM_PTR(&pin_GPIO33) }, { MP_ROM_QSTR(MP_QSTR_LCD_D_C), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, // Peripheral Power control { MP_ROM_QSTR(MP_QSTR_PE_POWER), MP_ROM_PTR(&pin_GPIO14) }, diff --git a/ports/esp32s2/common-hal/alarm/__init__.c b/ports/esp32s2/common-hal/alarm/__init__.c index 1cec5d4ae..be435e210 100644 --- a/ports/esp32s2/common-hal/alarm/__init__.c +++ b/ports/esp32s2/common-hal/alarm/__init__.c @@ -150,6 +150,14 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala void NORETURN alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_touch_touchalarm_prepare_for_deep_sleep(); + + // Disable brownout detection, which appears to be triggered sometimes when + // waking from deep sleep. + // See https://www.esp32.com/viewtopic.php?f=13&t=19208#p71084 + // and https://github.com/adafruit/circuitpython/issues/4025#issuecomment-771027606 + // TODO: We can remove this workaround when ESP-IDF handles this. + CLEAR_PERI_REG_MASK(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_RST_ENA); + // The ESP-IDF caches the deep sleep settings and applies them before sleep. // We don't need to worry about resetting them in the interim. esp_deep_sleep_start(); diff --git a/ports/esp32s2/common-hal/audiobusio/I2SOut.c b/ports/esp32s2/common-hal/audiobusio/I2SOut.c index 86322be86..eb9b6f8e1 100644 --- a/ports/esp32s2/common-hal/audiobusio/I2SOut.c +++ b/ports/esp32s2/common-hal/audiobusio/I2SOut.c @@ -63,6 +63,9 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t* self, self->bit_clock = bit_clock; self->word_select = word_select; self->data = data; + claim_pin(bit_clock); + claim_pin(word_select); + claim_pin(data); } bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t* self) { diff --git a/ports/esp32s2/common-hal/busio/I2C.c b/ports/esp32s2/common-hal/busio/I2C.c index 772262d0a..8372eb8c3 100644 --- a/ports/esp32s2/common-hal/busio/I2C.c +++ b/ports/esp32s2/common-hal/busio/I2C.c @@ -85,7 +85,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (gpio_get_level(sda->number) == 0 || gpio_get_level(scl->number) == 0) { reset_pin_number(sda->number); reset_pin_number(scl->number); - mp_raise_RuntimeError(translate("SDA or SCL needs a pull up")); + mp_raise_RuntimeError(translate("No pull up found on SDA or SCL; check your wiring")); } #endif diff --git a/ports/esp32s2/common-hal/socketpool/Socket.c b/ports/esp32s2/common-hal/socketpool/Socket.c index fc50ca3ab..5f93807bb 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.c +++ b/ports/esp32s2/common-hal/socketpool/Socket.c @@ -3,7 +3,6 @@ * * The MIT License (MIT) * - * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries * Copyright (c) 2020 Lucian Copeland for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -38,16 +37,15 @@ #include "components/lwip/lwip/src/include/lwip/sys.h" #include "components/lwip/lwip/src/include/lwip/netdb.h" -STATIC socketpool_socket_obj_t * open_socket_handles[CONFIG_LWIP_MAX_SOCKETS]; // 4 on the wrover/wroom +STATIC socketpool_socket_obj_t * open_socket_handles[CONFIG_LWIP_MAX_SOCKETS]; void socket_reset(void) { for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) { if (open_socket_handles[i]) { if (open_socket_handles[i]->num > 0) { + // Close automatically clears socket handle common_hal_socketpool_socket_close(open_socket_handles[i]); - open_socket_handles[i] = NULL; } else { - // accidentally got a TCP socket in here, or something. open_socket_handles[i] = NULL; } } @@ -64,73 +62,14 @@ bool register_open_socket(socketpool_socket_obj_t* self) { return false; } -STATIC void _lazy_init_LWIP(socketpool_socket_obj_t* self) { - if (self->num != -1) { - return; //safe to call on existing socket - } - if (self->tls != NULL) { - mp_raise_RuntimeError(translate("Invalid use of TLS Socket")); - } - int socknum = -1; - socknum = lwip_socket(self->family, self->type, self->ipproto); - if (socknum < 0 || !register_open_socket(self)) { - mp_raise_RuntimeError(translate("Out of sockets")); - } - self->num = socknum; - lwip_fcntl(socknum, F_SETFL, O_NONBLOCK); -} - -STATIC void _lazy_init_TLS(socketpool_socket_obj_t* self) { - if (self->type != SOCK_STREAM || self->num != -1) { - mp_raise_RuntimeError(translate("Invalid socket for TLS")); - } - esp_tls_t* tls_handle = esp_tls_init(); - if (tls_handle == NULL) { - mp_raise_espidf_MemoryError(); - } - self->tls = tls_handle; -} - -void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_uint_t timeout_ms) { - self->timeout_ms = timeout_ms; -} - -bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self, - const char* host, size_t hostlen, uint8_t port) { - _lazy_init_LWIP(self); - - struct sockaddr_in bind_addr; - bind_addr.sin_addr.s_addr = inet_addr(host); - bind_addr.sin_family = AF_INET; - bind_addr.sin_port = htons(port); - - int opt = 1; - int err = lwip_setsockopt(self->num, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - if (err != 0) { - mp_raise_RuntimeError(translate("Issue setting SO_REUSEADDR")); - } - int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) == 0; - return result; -} - -bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int backlog) { - return lwip_listen(self->num, backlog) == 0; -} - socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_obj_t* self, - uint8_t* ip, uint *port) { + uint8_t* ip, uint32_t *port) { struct sockaddr_in accept_addr; socklen_t socklen = sizeof(accept_addr); int newsoc = -1; bool timed_out = false; uint64_t start_ticks = supervisor_ticks_ms64(); - if (self->timeout_ms != (uint)-1) { - mp_printf(&mp_plat_print, "will timeout"); - } else { - mp_printf(&mp_plat_print, "won't timeout"); - } - // Allow timeouts and interrupts while (newsoc == -1 && !timed_out && @@ -140,7 +79,7 @@ socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_o } RUN_BACKGROUND_TASKS; newsoc = lwip_accept(self->num, (struct sockaddr *)&accept_addr, &socklen); - // In non-blocking mode, fail instead of looping + // In non-blocking mode, fail instead of timing out if (newsoc == -1 && self->timeout_ms == 0) { mp_raise_OSError(MP_EAGAIN); } @@ -159,9 +98,8 @@ socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_o socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); sock->base.type = &socketpool_socket_type; sock->num = newsoc; - sock->tls = NULL; - sock->ssl_context = NULL; sock->pool = self->pool; + sock->connected = true; if (!register_open_socket(sock)) { mp_raise_OSError(MP_EBADF); @@ -175,72 +113,136 @@ socketpool_socket_obj_t* common_hal_socketpool_socket_accept(socketpool_socket_o } } -bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, - const char* host, mp_uint_t hostlen, mp_int_t port) { - // For simplicity we use esp_tls for all TCP connections. If it's not SSL, ssl_context will be - // NULL and should still work. This makes regular TCP connections more memory expensive but TLS - // should become more and more common. Therefore, we optimize for the TLS case. +bool common_hal_socketpool_socket_bind(socketpool_socket_obj_t* self, + const char* host, size_t hostlen, uint32_t port) { + struct sockaddr_in bind_addr; + bind_addr.sin_addr.s_addr = inet_addr(host); + bind_addr.sin_family = AF_INET; + bind_addr.sin_port = htons(port); - // Todo: move to SSL Wrapper and add lwip_connect() - _lazy_init_TLS(self); + int opt = 1; + int err = lwip_setsockopt(self->num, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + if (err != 0) { + mp_raise_RuntimeError(translate("Cannot set socket options")); + } + int result = lwip_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) == 0; + return result; +} - esp_tls_cfg_t* tls_config = NULL; - if (self->ssl_context != NULL) { - tls_config = &self->ssl_context->ssl_config; +void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) { + self->connected = false; + if (self->num >= 0) { + lwip_shutdown(self->num, 0); + lwip_close(self->num); + self->num = -1; } - int result = esp_tls_conn_new_sync(host, hostlen, port, tls_config, self->tls); - self->connected = result >= 0; - if (result < 0) { - int esp_tls_code; - int flags; - esp_err_t err = esp_tls_get_and_clear_last_error(self->tls->error_handle, &esp_tls_code, &flags); - - if (err == ESP_ERR_MBEDTLS_SSL_SETUP_FAILED) { - mp_raise_espidf_MemoryError(); - } else if (ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED) { - mp_raise_OSError_msg_varg(translate("Failed SSL handshake")); - } else { - mp_raise_OSError_msg_varg(translate("Unhandled ESP TLS error %d %d %x %d"), esp_tls_code, flags, err, result); + // Remove socket record + for (size_t i = 0; i < MP_ARRAY_SIZE(open_socket_handles); i++) { + if (open_socket_handles[i] == self) { + open_socket_handles[i] = NULL; } + } +} + +bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, + const char* host, size_t hostlen, uint32_t port) { + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }; + struct addrinfo *result_i; + int error = lwip_getaddrinfo(host, NULL, &hints, &result_i); + if (error != 0 || result_i == NULL) { + mp_raise_OSError(EHOSTUNREACH); + } + + // Set parameters + struct sockaddr_in dest_addr; + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr; + #pragma GCC diagnostic pop + freeaddrinfo(result_i); + + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(port); + + // Replace above with function call ----- + + // Switch to blocking mode for this one call + int opts; + opts = lwip_fcntl(self->num,F_GETFL,0); + opts = opts & (~O_NONBLOCK); + lwip_fcntl(self->num, F_SETFL, opts); + + int result = -1; + result = lwip_connect(self->num, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in)); + + // Switch back once complete + opts = opts | O_NONBLOCK; + lwip_fcntl(self->num, F_SETFL, opts); + + if (result >= 0) { + self->connected = true; + return true; } else { - // Connection successful, set the timeout on the underlying socket. We can't rely on the IDF - // to do it because the config structure is only used for TLS connections. Generally, we - // shouldn't hit this timeout because we try to only read available data. However, there is - // always a chance that we try to read something that is used internally. - int fd; - esp_tls_get_conn_sockfd(self->tls, &fd); - struct timeval tv; - tv.tv_sec = 2 * 60; // Two minutes - tv.tv_usec = 0; - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + mp_raise_OSError(errno); } +} - return self->connected; +bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t* self) { + return self->num < 0; } bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self) { return self->connected; } -mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) { - int sent = -1; - if (self->num != -1) { - // LWIP Socket - // TODO: deal with potential failure/add timeout? - sent = lwip_send(self->num, buf, len, 0); - } else if (self->tls != NULL) { - // TLS Socket - sent = esp_tls_conn_write(self->tls, buf, len); +bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t* self, int backlog) { + return lwip_listen(self->num, backlog) == 0; +} + +mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* self, + uint8_t* buf, uint32_t len, uint8_t* ip, uint *port) { + + struct sockaddr_in source_addr; + socklen_t socklen = sizeof(source_addr); + + // LWIP Socket + uint64_t start_ticks = supervisor_ticks_ms64(); + int received = -1; + bool timed_out = false; + while (received == -1 && + !timed_out && + !mp_hal_is_interrupted()) { + if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) { + timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } + RUN_BACKGROUND_TASKS; + received = lwip_recvfrom(self->num, buf, len, 0, (struct sockaddr *)&source_addr, &socklen); + + // In non-blocking mode, fail instead of looping + if (received == -1 && self->timeout_ms == 0) { + mp_raise_OSError(MP_EAGAIN); + } } - if (sent < 0) { - mp_raise_OSError(MP_ENOTCONN); + if (!timed_out) { + memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr)); + *port = source_addr.sin_port; + } else { + mp_raise_OSError(ETIMEDOUT); } - return sent; + + if (received < 0) { + mp_raise_BrokenPipeError(); + return 0; + } + + return received; } -mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) { +mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, const uint8_t* buf, uint32_t len) { int received = 0; bool timed_out = false; @@ -255,54 +257,14 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; } RUN_BACKGROUND_TASKS; - received = lwip_recv(self->num, (void*) buf, len - 1, 0); + received = lwip_recv(self->num, (void*) buf, len, 0); // In non-blocking mode, fail instead of looping if (received == -1 && self->timeout_ms == 0) { mp_raise_OSError(MP_EAGAIN); } } - } else if (self->tls != NULL) { - // TLS Socket - int status = 0; - uint64_t start_ticks = supervisor_ticks_ms64(); - int sockfd; - esp_err_t err = esp_tls_get_conn_sockfd(self->tls, &sockfd); - if (err != ESP_OK) { - mp_raise_OSError(MP_EBADF); - } - while (received == 0 && - status >= 0 && - !timed_out && - !mp_hal_is_interrupted()) { - if (self->timeout_ms != (uint)-1) { - timed_out = self->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; - } - RUN_BACKGROUND_TASKS; - size_t available = esp_tls_get_bytes_avail(self->tls); - if (available == 0) { - // This reads the raw socket buffer and is used for non-TLS connections - // and between encrypted TLS blocks. - status = lwip_ioctl(sockfd, FIONREAD, &available); - } - size_t remaining = len - received; - if (available > remaining) { - available = remaining; - } - if (available > 0) { - status = esp_tls_conn_read(self->tls, (void*) buf + received, available); - if (status == 0) { - // Reading zero when something is available indicates a closed - // connection. (The available bytes could have been TLS internal.) - break; - } - if (status > 0) { - received += status; - } - } - } } else { - // Socket does not have a valid descriptor of either type mp_raise_OSError(MP_EBADF); } @@ -312,29 +274,43 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self, return received; } -mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self, - const char* host, size_t hostlen, uint8_t port, const uint8_t* buf, mp_uint_t len) { +mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, uint32_t len) { + int sent = -1; + if (self->num != -1) { + // LWIP Socket + // TODO: deal with potential failure/add timeout? + sent = lwip_send(self->num, buf, len, 0); + } else { + mp_raise_OSError(MP_EBADF); + } - _lazy_init_LWIP(self); + if (sent < 0) { + mp_raise_OSError(errno); + } + return sent; +} - // Get the IP address string +mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self, + const char* host, size_t hostlen, uint32_t port, const uint8_t* buf, uint32_t len) { + + // Set parameters const struct addrinfo hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, }; - struct addrinfo *result; - int error = lwip_getaddrinfo(host, NULL, &hints, &result); - if (error != 0 || result == NULL) { - return 0; + struct addrinfo *result_i; + int error = lwip_getaddrinfo(host, NULL, &hints, &result_i); + if (error != 0 || result_i == NULL) { + mp_raise_OSError(EHOSTUNREACH); } // Set parameters struct sockaddr_in dest_addr; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" - dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr; + dest_addr.sin_addr.s_addr = ((struct sockaddr_in *)result_i->ai_addr)->sin_addr.s_addr; #pragma GCC diagnostic pop - freeaddrinfo(result); + freeaddrinfo(result_i); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(port); @@ -347,66 +323,6 @@ mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t* self, return bytes_sent; } -mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* self, - uint8_t* buf, mp_uint_t len, uint8_t* ip, uint *port) { - - _lazy_init_LWIP(self); - - struct sockaddr_in source_addr; - socklen_t socklen = sizeof(source_addr); - - // LWIP Socket - uint64_t start_ticks = supervisor_ticks_ms64(); - int received = -1; - bool timed_out = false; - while (received == -1 && - !timed_out && - !mp_hal_is_interrupted()) { - if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) { - timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; - } - RUN_BACKGROUND_TASKS; - received = lwip_recvfrom(self->num, buf, len, 0, (struct sockaddr *)&source_addr, &socklen); - - // In non-blocking mode, fail instead of looping - if (received == -1 && self->timeout_ms == 0) { - mp_raise_OSError(MP_EAGAIN); - } - } - - if (!timed_out) { - memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof(source_addr.sin_addr.s_addr)); - *port = source_addr.sin_port; - } else { - mp_raise_OSError(ETIMEDOUT); - } - - if (received < 0) { - mp_raise_BrokenPipeError(); - return 0; - } - - return received; -} - -void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) { - self->connected = false; - if (self->tls != NULL) { - esp_tls_conn_destroy(self->tls); - self->tls = NULL; - } - if (self->num >= 0) { - lwip_shutdown(self->num, 0); - lwip_close(self->num); - self->num = -1; - } -} - -bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t* self) { - return self->tls == NULL && self->num < 0; -} - - -mp_uint_t common_hal_socketpool_socket_get_hash(socketpool_socket_obj_t* self) { - return self->num; +void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, uint32_t timeout_ms) { + self->timeout_ms = timeout_ms; } diff --git a/ports/esp32s2/common-hal/socketpool/Socket.h b/ports/esp32s2/common-hal/socketpool/Socket.h index 4e6cfa5ef..b86f5597c 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.h +++ b/ports/esp32s2/common-hal/socketpool/Socket.h @@ -41,8 +41,6 @@ typedef struct { int family; int ipproto; bool connected; - esp_tls_t* tls; - ssl_sslcontext_obj_t* ssl_context; socketpool_socketpool_obj_t* pool; mp_uint_t timeout_ms; } socketpool_socket_obj_t; diff --git a/ports/esp32s2/common-hal/socketpool/SocketPool.c b/ports/esp32s2/common-hal/socketpool/SocketPool.c index 70a8b4eca..fbd6dca7a 100644 --- a/ports/esp32s2/common-hal/socketpool/SocketPool.c +++ b/ports/esp32s2/common-hal/socketpool/SocketPool.c @@ -25,6 +25,7 @@ */ #include "shared-bindings/socketpool/SocketPool.h" +#include "common-hal/socketpool/Socket.h" #include "py/runtime.h" #include "shared-bindings/wifi/__init__.h" @@ -65,23 +66,23 @@ socketpool_socket_obj_t* common_hal_socketpool_socket(socketpool_socketpool_obj_ mp_raise_NotImplementedError(translate("Only IPv4 sockets supported")); } - // Consider LWIP and MbedTLS "variant" sockets to be incompatible (for now) - // The variant of the socket is determined by whether the socket is wrapped - // by SSL. If no TLS handle is set in sslcontext_wrap_socket, the first call - // of bind() or connect() will create a LWIP socket with a corresponding - // socketnum. - // TODO: move MbedTLS to its own duplicate Socket or Server API, maybe? socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); sock->base.type = &socketpool_socket_type; - sock->num = -1; sock->type = socket_type; sock->family = addr_family; sock->ipproto = ipproto; + sock->pool = self; sock->timeout_ms = (uint)-1; - sock->tls = NULL; - sock->ssl_context = NULL; - sock->pool = self; + // Create LWIP socket + int socknum = -1; + socknum = lwip_socket(sock->family, sock->type, sock->ipproto); + if (socknum < 0 || !register_open_socket(sock)) { + mp_raise_RuntimeError(translate("Out of sockets")); + } + sock->num = socknum; + // Sockets should be nonblocking in most cases + lwip_fcntl(socknum, F_SETFL, O_NONBLOCK); return sock; } diff --git a/ports/esp32s2/common-hal/ssl/SSLContext.c b/ports/esp32s2/common-hal/ssl/SSLContext.c index e24fd338b..afc3ecce2 100644 --- a/ports/esp32s2/common-hal/ssl/SSLContext.c +++ b/ports/esp32s2/common-hal/ssl/SSLContext.c @@ -25,6 +25,9 @@ */ #include "shared-bindings/ssl/SSLContext.h" +#include "shared-bindings/ssl/SSLSocket.h" + +#include "bindings/espidf/__init__.h" #include "py/runtime.h" @@ -32,10 +35,26 @@ void common_hal_ssl_sslcontext_construct(ssl_sslcontext_obj_t* self) { } -socketpool_socket_obj_t* common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t* self, +ssl_sslsocket_obj_t* common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t* self, socketpool_socket_obj_t* socket, bool server_side, const char* server_hostname) { - socket->ssl_context = self; + if (socket->type != SOCK_STREAM) { + mp_raise_RuntimeError(translate("Invalid socket for TLS")); + } + + ssl_sslsocket_obj_t *sock = m_new_obj_with_finaliser(ssl_sslsocket_obj_t); + sock->base.type = &ssl_sslsocket_type; + sock->ssl_context = self; + sock->sock = socket; + + esp_tls_t* tls_handle = esp_tls_init(); + if (tls_handle == NULL) { + mp_raise_espidf_MemoryError(); + } + sock->tls = tls_handle; + + // TODO: do something with the original socket? Don't call a close on the internal LWIP. + // Should we store server hostname on the socket in case connect is called with an ip? - return socket; + return sock; } diff --git a/ports/esp32s2/common-hal/ssl/SSLSocket.c b/ports/esp32s2/common-hal/ssl/SSLSocket.c new file mode 100644 index 000000000..10c29108c --- /dev/null +++ b/ports/esp32s2/common-hal/ssl/SSLSocket.c @@ -0,0 +1,176 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2021 Lucian Copeland 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/ssl/SSLSocket.h" +#include "shared-bindings/socketpool/Socket.h" +#include "shared-bindings/ssl/SSLContext.h" + +#include "bindings/espidf/__init__.h" +#include "lib/utils/interrupt_char.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "supervisor/shared/tick.h" + +ssl_sslsocket_obj_t* common_hal_ssl_sslsocket_accept(ssl_sslsocket_obj_t* self, + uint8_t* ip, uint32_t *port) { + socketpool_socket_obj_t * sock = common_hal_socketpool_socket_accept(self->sock, ip, port); + ssl_sslsocket_obj_t * sslsock = common_hal_ssl_sslcontext_wrap_socket(self->ssl_context, sock, false, NULL); + return sslsock; +} + +bool common_hal_ssl_sslsocket_bind(ssl_sslsocket_obj_t* self, + const char* host, size_t hostlen, uint32_t port) { + return common_hal_socketpool_socket_bind(self->sock, host, hostlen, port); +} + +void common_hal_ssl_sslsocket_close(ssl_sslsocket_obj_t* self) { + common_hal_socketpool_socket_close(self->sock); + esp_tls_conn_destroy(self->tls); + self->tls = NULL; +} + +bool common_hal_ssl_sslsocket_connect(ssl_sslsocket_obj_t* self, + const char* host, size_t hostlen, uint32_t port) { + esp_tls_cfg_t* tls_config = NULL; + tls_config = &self->ssl_context->ssl_config; + int result = esp_tls_conn_new_sync(host, hostlen, port, tls_config, self->tls); + self->sock->connected = result >= 0; + if (result < 0) { + int esp_tls_code; + int flags; + esp_err_t err = esp_tls_get_and_clear_last_error(self->tls->error_handle, &esp_tls_code, &flags); + + if (err == ESP_ERR_MBEDTLS_SSL_SETUP_FAILED) { + mp_raise_espidf_MemoryError(); + } else if (ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED) { + mp_raise_OSError_msg_varg(translate("Failed SSL handshake")); + } else { + mp_raise_OSError_msg_varg(translate("Unhandled ESP TLS error %d %d %x %d"), esp_tls_code, flags, err, result); + } + } else { + // Connection successful, set the timeout on the underlying socket. We can't rely on the IDF + // to do it because the config structure is only used for TLS connections. Generally, we + // shouldn't hit this timeout because we try to only read available data. However, there is + // always a chance that we try to read something that is used internally. + int fd; + esp_tls_get_conn_sockfd(self->tls, &fd); + struct timeval tv; + tv.tv_sec = 2 * 60; // Two minutes + tv.tv_usec = 0; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + } + + return self->sock->connected; +} + +bool common_hal_ssl_sslsocket_get_closed(ssl_sslsocket_obj_t* self) { + return self->tls == NULL && self->sock->num < 0; +} + +bool common_hal_ssl_sslsocket_get_connected(ssl_sslsocket_obj_t* self) { + return self->sock->connected; +} + +bool common_hal_ssl_sslsocket_listen(ssl_sslsocket_obj_t* self, int backlog) { + return common_hal_socketpool_socket_listen(self->sock, backlog); +} + +mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t* self, const uint8_t* buf, uint32_t len) { + int received = 0; + bool timed_out = false; + int status = 0; + uint64_t start_ticks = supervisor_ticks_ms64(); + int sockfd; + esp_err_t err = esp_tls_get_conn_sockfd(self->tls, &sockfd); + if (err != ESP_OK) { + mp_raise_OSError(MP_EBADF); + } + while (received == 0 && + status >= 0 && + !timed_out && + !mp_hal_is_interrupted()) { + if (self->sock->timeout_ms != (uint)-1 && self->sock->timeout_ms != 0) { + timed_out = self->sock->timeout_ms == 0 || supervisor_ticks_ms64() - start_ticks >= self->sock->timeout_ms; + } + RUN_BACKGROUND_TASKS; + size_t available = esp_tls_get_bytes_avail(self->tls); + if (available == 0) { + // This reads the raw socket buffer and is used for non-TLS connections + // and between encrypted TLS blocks. + status = lwip_ioctl(sockfd, FIONREAD, &available); + } + size_t remaining = len - received; + if (available > remaining) { + available = remaining; + } + if (available > 0) { + status = esp_tls_conn_read(self->tls, (void*) buf + received, available); + if (status == 0) { + // Reading zero when something is available indicates a closed + // connection. (The available bytes could have been TLS internal.) + break; + } + if (status > 0) { + received += status; + } + } + // In non-blocking mode, fail instead of timing out + if (received==0 && self->sock->timeout_ms == 0) { + mp_raise_OSError(MP_EAGAIN); + } + } + + if (timed_out) { + mp_raise_OSError(ETIMEDOUT); + } + return received; +} + +mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t* self, const uint8_t* buf, uint32_t len) { + int sent = -1; + sent = esp_tls_conn_write(self->tls, buf, len); + + if (sent < 0) { + int esp_tls_code; + int flags; + esp_err_t err = esp_tls_get_and_clear_last_error(self->tls->error_handle, &esp_tls_code, &flags); + + if (err == ESP_ERR_MBEDTLS_SSL_SETUP_FAILED) { + mp_raise_espidf_MemoryError(); + } else if (ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED) { + mp_raise_OSError_msg_varg(translate("Failed SSL handshake")); + } else { + mp_raise_OSError_msg_varg(translate("Unhandled ESP TLS error %d %d %x %d"), esp_tls_code, flags, err, sent); + } + } + return sent; +} + +void common_hal_ssl_sslsocket_settimeout(ssl_sslsocket_obj_t* self, uint32_t timeout_ms) { + self->sock->timeout_ms = timeout_ms; +} diff --git a/ports/esp32s2/common-hal/ssl/SSLSocket.h b/ports/esp32s2/common-hal/ssl/SSLSocket.h new file mode 100644 index 000000000..e9e5bff06 --- /dev/null +++ b/ports/esp32s2/common-hal/ssl/SSLSocket.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Lucian Copeland for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SSL_SSLSOCKET_H +#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SSL_SSLSOCKET_H + +#include "py/obj.h" + +#include "common-hal/ssl/SSLContext.h" +#include "common-hal/socketpool/Socket.h" + +#include "components/esp-tls/esp_tls.h" + +typedef struct { + mp_obj_base_t base; + socketpool_socket_obj_t * sock; + esp_tls_t* tls; + ssl_sslcontext_obj_t* ssl_context; +} ssl_sslsocket_obj_t; + +#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_SSL_SSLSOCKET_H diff --git a/ports/esp32s2/common-hal/supervisor/Runtime.c b/ports/esp32s2/common-hal/supervisor/Runtime.c index ea663f897..974f26cec 100644 --- a/ports/esp32s2/common-hal/supervisor/Runtime.c +++ b/ports/esp32s2/common-hal/supervisor/Runtime.c @@ -28,10 +28,10 @@ #include "shared-bindings/supervisor/Runtime.h" #include "supervisor/serial.h" -bool common_hal_get_serial_connected(void) { +bool common_hal_supervisor_runtime_get_serial_connected(void) { return (bool) serial_connected(); } -bool common_hal_get_serial_bytes_available(void) { - return (bool) serial_bytes_available(); +bool common_hal_supervisor_runtime_get_serial_bytes_available(void) { + return (bool) serial_bytes_available(); } diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index 562c60998..5073d8812 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -28,18 +28,18 @@ CIRCUITPY_FREQUENCYIO = 1 CIRCUITPY_I2CPERIPHERAL = 0 CIRCUITPY_ROTARYIO = 1 CIRCUITPY_NVM = 1 +CIRCUITPY_PS2IO ?= 1 +CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 # We don't have enough endpoints to include MIDI. -CIRCUITPY_USB_MIDI = 0 +CIRCUITPY_USB_MIDI ?= 0 +CIRCUITPY_USB_HID ?= 1 +# We have borrowed the VENDOR nomenclature from tinyusb. VENDOR AKA WEBUSB +CIRCUITPY_USB_VENDOR ?= 0 CIRCUITPY_WIFI = 1 CIRCUITPY_WATCHDOG ?= 1 -CIRCUITPY_ESPIDF = 1 - -ifndef CIRCUITPY_PS2IO -CIRCUITPY_PS2IO = 1 -endif -ifndef CIRCUITPY_TOUCHIO_USE_NATIVE -CIRCUITPY_TOUCHIO_USE_NATIVE = 1 -endif +CIRCUITPY_ESPIDF = 1 CIRCUITPY_MODULE ?= none + +USB_NUM_EP = 5 diff --git a/ports/litex/common-hal/supervisor/Runtime.c b/ports/litex/common-hal/supervisor/Runtime.c index ea663f897..974f26cec 100644 --- a/ports/litex/common-hal/supervisor/Runtime.c +++ b/ports/litex/common-hal/supervisor/Runtime.c @@ -28,10 +28,10 @@ #include "shared-bindings/supervisor/Runtime.h" #include "supervisor/serial.h" -bool common_hal_get_serial_connected(void) { +bool common_hal_supervisor_runtime_get_serial_connected(void) { return (bool) serial_connected(); } -bool common_hal_get_serial_bytes_available(void) { - return (bool) serial_bytes_available(); +bool common_hal_supervisor_runtime_get_serial_bytes_available(void) { + return (bool) serial_bytes_available(); } diff --git a/ports/mimxrt10xx/common-hal/busio/I2C.c b/ports/mimxrt10xx/common-hal/busio/I2C.c index aaa2549a8..c8daddc4b 100644 --- a/ports/mimxrt10xx/common-hal/busio/I2C.c +++ b/ports/mimxrt10xx/common-hal/busio/I2C.c @@ -110,7 +110,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if( !GPIO_PinRead(sda->gpio, sda->number) || !GPIO_PinRead(scl->gpio, scl->number)) { common_hal_reset_pin(sda); common_hal_reset_pin(scl); - mp_raise_RuntimeError(translate("SDA or SCL needs a pull up")); + mp_raise_RuntimeError(translate("No pull up found on SDA or SCL; check your wiring")); } #endif diff --git a/ports/mimxrt10xx/common-hal/busio/SPI.c b/ports/mimxrt10xx/common-hal/busio/SPI.c index ce7cbea7e..00d8d9867 100644 --- a/ports/mimxrt10xx/common-hal/busio/SPI.c +++ b/ports/mimxrt10xx/common-hal/busio/SPI.c @@ -38,6 +38,8 @@ #define LPSPI_MASTER_CLK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (CLOCK_GetDiv(kCLOCK_LpspiDiv) + 1)) +#define MAX_SPI_BUSY_RETRIES 100 + //arrays use 0 based numbering: SPI1 is stored at index 0 #define MAX_SPI 4 STATIC bool reserved_spi[MAX_SPI]; @@ -289,7 +291,12 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, xfer.dataSize = len; xfer.configFlags = kLPSPI_MasterPcs0; - const status_t status = LPSPI_MasterTransferBlocking(self->spi, &xfer); + status_t status; + int retries = MAX_SPI_BUSY_RETRIES; + do { + status = LPSPI_MasterTransferBlocking(self->spi, &xfer); + } while (status == kStatus_LPSPI_Busy && --retries > 0); + if (status != kStatus_Success) printf("%s: status %ld\r\n", __func__, status); @@ -311,7 +318,12 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, xfer.rxData = data; xfer.dataSize = len; - const status_t status = LPSPI_MasterTransferBlocking(self->spi, &xfer); + status_t status; + int retries = MAX_SPI_BUSY_RETRIES; + do { + status = LPSPI_MasterTransferBlocking(self->spi, &xfer); + } while (status == kStatus_LPSPI_Busy && --retries > 0); + if (status != kStatus_Success) printf("%s: status %ld\r\n", __func__, status); @@ -333,7 +345,12 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_ou xfer.rxData = data_in; xfer.dataSize = len; - const status_t status = LPSPI_MasterTransferBlocking(self->spi, &xfer); + status_t status; + int retries = MAX_SPI_BUSY_RETRIES; + do { + status = LPSPI_MasterTransferBlocking(self->spi, &xfer); + } while (status == kStatus_LPSPI_Busy && --retries > 0); + if (status != kStatus_Success) printf("%s: status %ld\r\n", __func__, status); diff --git a/ports/mimxrt10xx/common-hal/supervisor/Runtime.c b/ports/mimxrt10xx/common-hal/supervisor/Runtime.c index 6be38f216..974f26cec 100755 --- a/ports/mimxrt10xx/common-hal/supervisor/Runtime.c +++ b/ports/mimxrt10xx/common-hal/supervisor/Runtime.c @@ -28,10 +28,10 @@ #include "shared-bindings/supervisor/Runtime.h" #include "supervisor/serial.h" -bool common_hal_get_serial_connected(void) { +bool common_hal_supervisor_runtime_get_serial_connected(void) { return (bool) serial_connected(); } -bool common_hal_get_serial_bytes_available(void) { +bool common_hal_supervisor_runtime_get_serial_bytes_available(void) { return (bool) serial_bytes_available(); } diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c index 37cb192df..654fa857f 100644 --- a/ports/nrf/common-hal/busio/I2C.c +++ b/ports/nrf/common-hal/busio/I2C.c @@ -131,7 +131,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t * if (!nrf_gpio_pin_read(sda->number) || !nrf_gpio_pin_read(scl->number)) { reset_pin_number(sda->number); reset_pin_number(scl->number); - mp_raise_RuntimeError(translate("SDA or SCL needs a pull up")); + mp_raise_RuntimeError(translate("No pull up found on SDA or SCL; check your wiring")); } #endif diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index eab7deee6..e1169ce7d 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -99,6 +99,7 @@ INC += -I. \ -isystem sdk/src/rp2_common/pico_platform/include/ \ -isystem sdk/src/rp2_common/pico_runtime/printf/include/ \ -isystem sdk/src/rp2_common/pico_bootrom/include/ \ + -isystem sdk/src/rp2_common/pico_unique_id/include/ \ -Isdk_config \ -I../../lib/tinyusb/src \ -I../../supervisor/shared/usb \ @@ -184,6 +185,7 @@ SRC_SDK := \ src/rp2_common/pico_printf/printf.c \ src/rp2_common/pico_runtime/runtime.c \ src/rp2_common/pico_stdio/stdio.c \ + src/rp2_common/pico_unique_id/unique_id.c \ SRC_SDK := $(addprefix sdk/, $(SRC_SDK)) diff --git a/ports/raspberrypi/background.c b/ports/raspberrypi/background.c index c85b83b41..52f2e4fb4 100644 --- a/ports/raspberrypi/background.c +++ b/ports/raspberrypi/background.c @@ -25,20 +25,11 @@ */ #include "background.h" -#include "supervisor/filesystem.h" -#include "supervisor/shared/tick.h" -#include "supervisor/usb.h" - #include "py/runtime.h" -#include "shared-module/network/__init__.h" -#include "supervisor/shared/stack.h" #include "supervisor/port.h" -#if CIRCUITPY_DISPLAYIO -#include "shared-module/displayio/__init__.h" -#endif - void port_start_background_task(void) {} void port_finish_background_task(void) {} -void port_background_task(void) {} +void port_background_task(void) { +} diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.c b/ports/raspberrypi/bindings/rp2pio/StateMachine.c index 0f6f84a56..34633949e 100644 --- a/ports/raspberrypi/bindings/rp2pio/StateMachine.c +++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.c @@ -189,7 +189,7 @@ STATIC mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n if (bufinfo.len % 2 != 0) { mp_raise_ValueError(translate("Program size invalid")); } - if (bufinfo.len > 32) { + if (bufinfo.len > 64) { mp_raise_ValueError(translate("Program too large")); } diff --git a/ports/raspberrypi/boards/raspberry_pi_pico/pins.c b/ports/raspberrypi/boards/raspberry_pi_pico/pins.c index 913676ad2..e1927bc80 100644 --- a/ports/raspberrypi/boards/raspberry_pi_pico/pins.c +++ b/ports/raspberrypi/boards/raspberry_pi_pico/pins.c @@ -24,6 +24,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_GPIO23) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, @@ -35,5 +36,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/raspberrypi/bs2_default_padded_checksummed.S b/ports/raspberrypi/bs2_default_padded_checksummed.S index d77f4867c..6b7074e3b 100644 --- a/ports/raspberrypi/bs2_default_padded_checksummed.S +++ b/ports/raspberrypi/bs2_default_padded_checksummed.S @@ -1,20 +1,23 @@ -// Padded and checksummed version of: /Users/graham/dev/mu/pico_sdk/cmake-build-debug-mu/src/rp2_common/boot_stage2/bs2_default.bin +// Padded and checksummed version of: /home/pi/pico/pico-examples/build/pico-sdk/src/rp2_common/boot_stage2/bs2_default.bin -.section .boot2, "a" +.cpu cortex-m0plus +.thumb -.byte 0x00, 0xb5, 0x2f, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60 -.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2b, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61 -.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x28, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20 -.byte 0x00, 0xf0, 0x3e, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0 -.byte 0x2e, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0 -.byte 0x26, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x29, 0xf8, 0x01, 0x21 -.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x18, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60 -.byte 0x17, 0x49, 0x18, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21 -.byte 0x19, 0x66, 0x00, 0xf0, 0x0c, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x13, 0x49, 0x11, 0x48, 0x01, 0x60 -.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd1, 0x10, 0x48, 0x00, 0x47, 0x03, 0xb5 -.byte 0x99, 0x6a, 0x04, 0x20, 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd -.byte 0x02, 0xb5, 0x18, 0x66, 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd -.byte 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00 -.byte 0x21, 0x22, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x01, 0x01, 0x00, 0x10 -.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x27, 0x2a, 0x60 +.section .boot2, "ax" + +.byte 0x00, 0xb5, 0x32, 0x4b, 0x21, 0x20, 0x58, 0x60, 0x98, 0x68, 0x02, 0x21, 0x88, 0x43, 0x98, 0x60 +.byte 0xd8, 0x60, 0x18, 0x61, 0x58, 0x61, 0x2e, 0x4b, 0x00, 0x21, 0x99, 0x60, 0x02, 0x21, 0x59, 0x61 +.byte 0x01, 0x21, 0xf0, 0x22, 0x99, 0x50, 0x2b, 0x49, 0x19, 0x60, 0x01, 0x21, 0x99, 0x60, 0x35, 0x20 +.byte 0x00, 0xf0, 0x44, 0xf8, 0x02, 0x22, 0x90, 0x42, 0x14, 0xd0, 0x06, 0x21, 0x19, 0x66, 0x00, 0xf0 +.byte 0x34, 0xf8, 0x19, 0x6e, 0x01, 0x21, 0x19, 0x66, 0x00, 0x20, 0x18, 0x66, 0x1a, 0x66, 0x00, 0xf0 +.byte 0x2c, 0xf8, 0x19, 0x6e, 0x19, 0x6e, 0x19, 0x6e, 0x05, 0x20, 0x00, 0xf0, 0x2f, 0xf8, 0x01, 0x21 +.byte 0x08, 0x42, 0xf9, 0xd1, 0x00, 0x21, 0x99, 0x60, 0x1b, 0x49, 0x19, 0x60, 0x00, 0x21, 0x59, 0x60 +.byte 0x1a, 0x49, 0x1b, 0x48, 0x01, 0x60, 0x01, 0x21, 0x99, 0x60, 0xeb, 0x21, 0x19, 0x66, 0xa0, 0x21 +.byte 0x19, 0x66, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x21, 0x99, 0x60, 0x16, 0x49, 0x14, 0x48, 0x01, 0x60 +.byte 0x01, 0x21, 0x99, 0x60, 0x01, 0xbc, 0x00, 0x28, 0x00, 0xd0, 0x00, 0x47, 0x12, 0x48, 0x13, 0x49 +.byte 0x08, 0x60, 0x03, 0xc8, 0x80, 0xf3, 0x08, 0x88, 0x08, 0x47, 0x03, 0xb5, 0x99, 0x6a, 0x04, 0x20 +.byte 0x01, 0x42, 0xfb, 0xd0, 0x01, 0x20, 0x01, 0x42, 0xf8, 0xd1, 0x03, 0xbd, 0x02, 0xb5, 0x18, 0x66 +.byte 0x18, 0x66, 0xff, 0xf7, 0xf2, 0xff, 0x18, 0x6e, 0x18, 0x6e, 0x02, 0xbd, 0x00, 0x00, 0x02, 0x40 +.byte 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x21, 0x22, 0x00, 0x00 +.byte 0xf4, 0x00, 0x00, 0x18, 0x22, 0x20, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x10, 0x08, 0xed, 0x00, 0xe0 +.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xb2, 0x4e, 0x7a diff --git a/ports/raspberrypi/common-hal/busio/I2C.c b/ports/raspberrypi/common-hal/busio/I2C.c index fa49e375e..26a7f3807 100644 --- a/ports/raspberrypi/common-hal/busio/I2C.c +++ b/ports/raspberrypi/common-hal/busio/I2C.c @@ -90,7 +90,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, if (!gpio_get(sda->number) || !gpio_get(scl->number)) { reset_pin_number(sda->number); reset_pin_number(scl->number); - mp_raise_RuntimeError(translate("SDA or SCL needs a pull up")); + mp_raise_RuntimeError(translate("No pull up found on SDA or SCL; check your wiring")); } #endif diff --git a/ports/raspberrypi/common-hal/microcontroller/Processor.c b/ports/raspberrypi/common-hal/microcontroller/Processor.c index 0ad3a51e2..e22286ca3 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Processor.c +++ b/ports/raspberrypi/common-hal/microcontroller/Processor.c @@ -25,6 +25,7 @@ */ #include <math.h> +#include <string.h> #include "py/mphal.h" #include "common-hal/microcontroller/Processor.h" @@ -53,12 +54,9 @@ uint32_t common_hal_mcu_processor_get_frequency(void) { } void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { - // TODO: get the unique id from the flash. The chip itself doesn't have one. - // for (int i=0; i<4; i++) { - // for (int k=0; k<4; k++) { - // raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; - // } - // } + pico_unique_board_id_t retrieved_id; + pico_get_unique_board_id(&retrieved_id); + memcpy(raw_id, retrieved_id.id, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH); } mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { diff --git a/ports/raspberrypi/common-hal/microcontroller/Processor.h b/ports/raspberrypi/common-hal/microcontroller/Processor.h index b7c86e850..afb43f9bd 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Processor.h +++ b/ports/raspberrypi/common-hal/microcontroller/Processor.h @@ -27,7 +27,9 @@ #ifndef MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H #define MICROPY_INCLUDED_RASPBERRYPI_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H -#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 16 +#include "src/rp2_common/pico_unique_id/include/pico/unique_id.h" + +#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH PICO_UNIQUE_BOARD_ID_SIZE_BYTES #include "py/obj.h" diff --git a/ports/raspberrypi/common-hal/microcontroller/__init__.c b/ports/raspberrypi/common-hal/microcontroller/__init__.c index 85bfc329d..bfea8b2d9 100644 --- a/ports/raspberrypi/common-hal/microcontroller/__init__.c +++ b/ports/raspberrypi/common-hal/microcontroller/__init__.c @@ -35,12 +35,16 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" +#include "supervisor/filesystem.h" +#include "supervisor/port.h" #include "supervisor/shared/safe_mode.h" #include "supervisor/shared/translate.h" #include "src/rp2040/hardware_structs/include/hardware/structs/sio.h" #include "src/rp2_common/hardware_sync/include/hardware/sync.h" +#include "hardware/watchdog.h" + void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); } @@ -66,8 +70,11 @@ void common_hal_mcu_enable_interrupts(void) { asm volatile ("cpsie i" : : : "memory"); } +static bool next_reset_to_bootloader = false; + void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { if (runmode == RUNMODE_BOOTLOADER) { + next_reset_to_bootloader = true; } else { } if (runmode == RUNMODE_SAFE_MODE) { @@ -76,6 +83,12 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { } void common_hal_mcu_reset(void) { + filesystem_flush(); + if (next_reset_to_bootloader) { + reset_to_bootloader(); + } else { + reset_cpu(); + } } // The singleton microcontroller.Processor object, bound to microcontroller.cpu diff --git a/ports/raspberrypi/common-hal/neopixel_write/__init__.c b/ports/raspberrypi/common-hal/neopixel_write/__init__.c index 10462b5a3..561d438e2 100644 --- a/ports/raspberrypi/common-hal/neopixel_write/__init__.c +++ b/ports/raspberrypi/common-hal/neopixel_write/__init__.c @@ -29,6 +29,7 @@ #include "bindings/rp2pio/StateMachine.h" #include "common-hal/rp2pio/StateMachine.h" #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/digitalio/DigitalInOut.h" #include "supervisor/port.h" @@ -89,7 +90,11 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, // Use a private deinit of the state machine that doesn't reset the pin. rp2pio_statemachine_deinit(&state_machine, true); + + // Reset the pin and release it from the PIO gpio_init(digitalinout->pin->number); + common_hal_digitalio_digitalinout_switch_to_output((digitalio_digitalinout_obj_t*)digitalinout, false, DRIVE_MODE_PUSH_PULL); + // Update the next start. next_start_raw_ticks = port_get_raw_ticks(NULL) + 1; } diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c index 567ec5ef5..3d8979a03 100644 --- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c +++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c @@ -107,7 +107,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self, if (variable_frequency) { return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; } - // If the other user wants to change frequency then we can't share either. + // If the other user wants a variable frequency then we can't share either. if ((slice_fixed_frequency & (1 << slice)) != 0) { return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE; } @@ -119,7 +119,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self, self->slice = slice; self->channel = channel; channel_use |= channel_use_mask; - if (!variable_frequency) { + if (variable_frequency) { slice_fixed_frequency |= 1 << slice; } diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c index 6510410b0..90c48130e 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -546,15 +546,23 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, size_t tx_remaining = out_len; while (rx_remaining || tx_remaining) { - if (tx_remaining && !pio_sm_is_tx_fifo_full(self->pio, self->state_machine)) { - *tx_destination = *data_out; - data_out++; - --tx_remaining; - } - if (rx_remaining && !pio_sm_is_rx_fifo_empty(self->pio, self->state_machine)) { - *data_in = (uint8_t) *rx_source; - data_in++; - --rx_remaining; + for (int i=0; i<32; i++) { + bool did_transfer = false; + if (tx_remaining && !pio_sm_is_tx_fifo_full(self->pio, self->state_machine)) { + *tx_destination = *data_out; + data_out++; + --tx_remaining; + did_transfer = true; + } + if (rx_remaining && !pio_sm_is_rx_fifo_empty(self->pio, self->state_machine)) { + *data_in = (uint8_t) *rx_source; + data_in++; + --rx_remaining; + did_transfer = true; + } + if (!did_transfer) { + break; + } } RUN_BACKGROUND_TASKS; if (mp_hal_is_interrupted()) { diff --git a/ports/raspberrypi/common-hal/supervisor/Runtime.c b/ports/raspberrypi/common-hal/supervisor/Runtime.c index 6be38f216..974f26cec 100755 --- a/ports/raspberrypi/common-hal/supervisor/Runtime.c +++ b/ports/raspberrypi/common-hal/supervisor/Runtime.c @@ -28,10 +28,10 @@ #include "shared-bindings/supervisor/Runtime.h" #include "supervisor/serial.h" -bool common_hal_get_serial_connected(void) { +bool common_hal_supervisor_runtime_get_serial_connected(void) { return (bool) serial_connected(); } -bool common_hal_get_serial_bytes_available(void) { +bool common_hal_supervisor_runtime_get_serial_bytes_available(void) { return (bool) serial_bytes_available(); } diff --git a/ports/raspberrypi/link.ld b/ports/raspberrypi/link.ld index d642fd680..b83299dee 100644 --- a/ports/raspberrypi/link.ld +++ b/ports/raspberrypi/link.ld @@ -59,12 +59,11 @@ SECTIONS */ .text : { - __reset_start = .; - KEEP (*(.reset)) - . = ALIGN(256); - __reset_end = .; - ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes"); + __logical_binary_start = .; KEEP (*(.vectors)) + KEEP (*(.binary_info_header)) + __binary_info_header_end = .; + KEEP (*(.reset)) /* TODO revisit this now memset/memcpy/float in ROM */ /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from * FLASH ... we will include any thing excluded here in .data below by default */ @@ -246,5 +245,7 @@ SECTIONS /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + + ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") /* todo assert on extra code */ } diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index 6fb4ffaae..292e509cd 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -42,7 +42,7 @@ CIRCUITPY_AUDIOIO = 0 INTERNAL_LIBM = 1 -USB_SERIAL_NUMBER_LENGTH = 32 +USB_SERIAL_NUMBER_LENGTH = 16 # Number of USB endpoint pairs. USB_NUM_EP = 8 diff --git a/ports/raspberrypi/sdk b/ports/raspberrypi/sdk -Subproject 26653ea81e340cacee55025d110c3e014a252a8 +Subproject 55346c953012ef5b32f392fea3b42814db8df2a diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index b14f5173d..7c503514a 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -52,6 +52,8 @@ #include "tusb.h" +#include "pico/bootrom.h" +#include "hardware/watchdog.h" extern volatile bool mp_msc_enabled; @@ -110,13 +112,17 @@ void reset_port(void) { } void reset_to_bootloader(void) { - // reset(); + reset_usb_boot(0, 0); while (true) {} } void reset_cpu(void) { - // reset(); - while (true) {} + watchdog_reboot(0, SRAM_END, 0); + watchdog_start_tick(12); + + while (true) { + __wfi(); + } } bool port_has_fixed_stack(void) { diff --git a/ports/stm/common-hal/supervisor/Runtime.c b/ports/stm/common-hal/supervisor/Runtime.c index ea663f897..974f26cec 100755 --- a/ports/stm/common-hal/supervisor/Runtime.c +++ b/ports/stm/common-hal/supervisor/Runtime.c @@ -28,10 +28,10 @@ #include "shared-bindings/supervisor/Runtime.h" #include "supervisor/serial.h" -bool common_hal_get_serial_connected(void) { +bool common_hal_supervisor_runtime_get_serial_connected(void) { return (bool) serial_connected(); } -bool common_hal_get_serial_bytes_available(void) { - return (bool) serial_bytes_available(); +bool common_hal_supervisor_runtime_get_serial_bytes_available(void) { + return (bool) serial_bytes_available(); } |
