From cbfb2d0f55a59d025c186cb6bdfea8ce5a8afb6c Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 11 May 2023 12:12:34 -0700 Subject: [PATCH] Add Pimoroni Inky Frame 5.7 Tweak DTCM and ITCM loading and prevent epd refresh while waiting for autoreload. --- main.c | 4 +- .../boards/pimoroni_inky_frame_5_7/board.c | 114 ++++++++++++++++++ .../boards/pimoroni_inky_frame_5_7/link.ld | 1 + .../pimoroni_inky_frame_5_7/mpconfigboard.h | 17 +++ .../pimoroni_inky_frame_5_7/mpconfigboard.mk | 26 ++++ .../pico-sdk-configboard.h | 1 + .../boards/pimoroni_inky_frame_5_7/pins.c | 52 ++++++++ ports/raspberrypi/supervisor/port.c | 17 +-- tools/cortex-m-fault-gdb.py | 6 +- 9 files changed, 224 insertions(+), 14 deletions(-) create mode 100644 ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c create mode 100644 ports/raspberrypi/boards/pimoroni_inky_frame_5_7/link.ld create mode 100644 ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h create mode 100644 ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk create mode 100644 ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pico-sdk-configboard.h create mode 100644 ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pins.c diff --git a/main.c b/main.c index ae8c339172..122f079129 100644 --- a/main.c +++ b/main.c @@ -666,8 +666,10 @@ STATIC bool run_code_py(safe_mode_t safe_mode, bool *simulate_reset) { #endif { // Refresh the ePaper display if we have one. That way it'll show an error message. + // Skip if we're about to autoreload. Otherwise we may delay when user code can update + // the display. #if CIRCUITPY_DISPLAYIO - if (time_to_epaper_refresh > 0) { + if (time_to_epaper_refresh > 0 && !autoreload_pending()) { time_to_epaper_refresh = maybe_refresh_epaperdisplay(); } diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c new file mode 100644 index 0000000000..53fd01b75a --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c @@ -0,0 +1,114 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 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" + +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/displayio/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-bindings/board/__init__.h" +#include "supervisor/shared/board.h" + +#define DELAY 0x80 + +// This is an SPD1656 control chip. The display is a 5.7" ACeP EInk. + +const uint8_t display_start_sequence[] = { + 0x01, 4, 0x37, 0x00, 0x23, 0x23, // power setting + 0x00, 2, 0xef, 0x08, // panel setting (PSR) + 0x03, 1, 0x00, // PFS + 0x06, 3, 0xc7, 0xc7, 0x1d, // booster + 0x30, 1, 0x3c, // PLL setting + 0x41, 1, 0x00, // TSE + 0x50, 1, 0x37, // vcom and data interval setting + 0x60, 1, 0x22, // tcon setting + 0x61, 4, 0x02, 0x58, 0x01, 0xc0, // tres + 0xe3, 1, 0xaa, // PWS + 0x04, DELAY | 0, 0xc8, // VCM DC and delay 200ms +}; + +const uint8_t display_stop_sequence[] = { + 0x02, 1, 0x00, // power off + 0x07, 1, 0xa5 // deep sleep +}; + +const uint8_t refresh_sequence[] = { + 0x12, 0x00 +}; + +void board_init(void) { + displayio_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + + bus->base.type = &displayio_fourwire_type; + common_hal_displayio_fourwire_construct(bus, + spi, + &pin_GPIO28, // EPD_DC Command or data + &pin_GPIO17, // EPD_CS Chip select + &pin_GPIO27, // EPD_RST Reset + 1000000, // Baudrate + 0, // Polarity + 0); // Phase + + displayio_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &displayio_epaperdisplay_type; + common_hal_displayio_epaperdisplay_construct( + display, + bus, + display_start_sequence, sizeof(display_start_sequence), + 1.0, // start up time + display_stop_sequence, sizeof(display_stop_sequence), + 600, // width + 448, // height + 640, // ram_width + 480, // ram_height + 0, // colstart + 0, // rowstart + 180, // rotation + NO_COMMAND, // set_column_window_command + NO_COMMAND, // set_row_window_command + NO_COMMAND, // set_current_column_command + NO_COMMAND, // set_current_row_command + 0x10, // write_black_ram_command + false, // black_bits_inverted + NO_COMMAND, // write_color_ram_command + false, // color_bits_inverted + 0x000000, // highlight_color + refresh_sequence, sizeof(refresh_sequence), + 28.0, // refresh_time + NULL, // busy_pin + false, // busy_state + 30.0, // seconds_per_frame + false, // always_toggle_chip_select + false, // grayscale + true, // acep + false, // two_byte_sequence_length + false); // address_little_endian +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/link.ld b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/link.ld new file mode 100644 index 0000000000..e814bead4c --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h new file mode 100644 index 0000000000..0817a6c594 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h @@ -0,0 +1,17 @@ +#define MICROPY_HW_BOARD_NAME "Pimoroni Inky Frame 5.7" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_GPIO6) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO5) + +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO16) diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk new file mode 100644 index 0000000000..40583e1b96 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk @@ -0,0 +1,26 @@ +USB_VID = 0x2E8A +USB_PID = 0x1018 +USB_PRODUCT = "Inky Frame 5.7" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_SSL_MBEDTLS = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + +CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pico-sdk-configboard.h new file mode 100644 index 0000000000..36da55d457 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pico-sdk-configboard.h @@ -0,0 +1 @@ +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pins.c b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pins.c new file mode 100644 index 0000000000..4496790c6c --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/pins.c @@ -0,0 +1,52 @@ +#include "shared-bindings/board/__init__.h" + +#include "supervisor/board.h" +#include "shared-module/displayio/__init__.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_HOLD_SYS_EN), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_I2C_INT), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_LED_ACT), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_LED_CONN), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_CLK), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_LATCH), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_SWITCH_OUT), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LED_A), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LED_C), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LED_D), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_LED_E), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_INKY_CS), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SCLK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT1), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT2), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_INKY_RES), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_INKY_DC), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_CYW1) }, + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_CYW2) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_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_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index e45fa8837a..08a9d96c2e 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -104,22 +104,23 @@ safe_mode_t port_init(void) { _binary_info(); // Set brown out. + // Load from the XIP memory space that doesn't cache. That way we don't + // evict anything else. The code we're loading is linked to the RAM address + // anyway. + size_t nocache = 0x03000000; + // Copy all of the "tightly coupled memory" code and data to run from RAM. // This lets us use the 16k cache for dynamically used data and code. // We must do this before we try and call any of its code or load the data. + uint32_t *itcm_flash_copy = (uint32_t *)(((size_t)&_ld_itcm_flash_copy) | nocache); for (uint32_t i = 0; i < ((size_t)&_ld_itcm_size) / 4; i++) { - (&_ld_itcm_destination)[i] = (&_ld_itcm_flash_copy)[i]; - // Now zero it out to evict the line from the XIP cache. Without this, - // it'll stay in the XIP cache anyway. - (&_ld_itcm_flash_copy)[i] = 0x0; + (&_ld_itcm_destination)[i] = itcm_flash_copy[i]; } // Copy all of the data to run from DTCM. + uint32_t *dtcm_flash_copy = (uint32_t *)(((size_t)&_ld_dtcm_data_flash_copy) | nocache); for (uint32_t i = 0; i < ((size_t)&_ld_dtcm_data_size) / 4; i++) { - (&_ld_dtcm_data_destination)[i] = (&_ld_dtcm_data_flash_copy)[i]; - // Now zero it out to evict the line from the XIP cache. Without this, - // it'll stay in the XIP cache anyway. - (&_ld_dtcm_data_flash_copy)[i] = 0x0; + (&_ld_dtcm_data_destination)[i] = dtcm_flash_copy[i]; } // Clear DTCM bss. diff --git a/tools/cortex-m-fault-gdb.py b/tools/cortex-m-fault-gdb.py index 54a921e91f..898630ab4e 100644 --- a/tools/cortex-m-fault-gdb.py +++ b/tools/cortex-m-fault-gdb.py @@ -45,12 +45,8 @@ class CortexMFault(gdb.Command): print("vtor", hex(vtor)) icsr = self._read(ICSR) - if (icsr & (1 << 23)) != 0: - print("No preempted exceptions") - else: - print("Another exception was preempted") vectactive = icsr & 0x1FF - print(hex(icsr), vectactive) + print("icsr", hex(icsr), vectactive) if vectactive != 0: if vectactive in EXCEPTIONS: vectactive = EXCEPTIONS[vectactive]