From 46fd60c70398b51136a2deea84f30e867679ca53 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 14 Feb 2019 12:54:34 -0800 Subject: [PATCH 1/3] Prevent infinite display update recursion and fix VFS mounting Fixes #1529 --- extmod/vfs_fat_file.c | 5 ++++- main.c | 14 ++++++++++++++ py/circuitpy_mpconfig.h | 1 - py/runtime.c | 25 ------------------------- shared-module/displayio/__init__.c | 13 ++++++++++++- supervisor/shared/filesystem.c | 2 +- 6 files changed, 31 insertions(+), 29 deletions(-) diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 1b2bb27f83..690073ce48 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -186,12 +186,15 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar break; } } + assert(vfs != NULL); + if ((vfs->flags & FSUSER_USB_WRITABLE) != 0 && (mode & FA_WRITE) != 0) { + mp_raise_OSError(MP_EROFS); + } pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t); o->base.type = type; const char *fname = mp_obj_str_get_str(args[0].u_obj); - assert(vfs != NULL); FRESULT res = f_open(&vfs->fatfs, &o->fp, fname, mode); if (res != FR_OK) { m_del_obj(pyb_file_obj_t, o); diff --git a/main.c b/main.c index fac9864e38..68ee66d02a 100755 --- a/main.c +++ b/main.c @@ -127,6 +127,20 @@ void stop_mp(void) { #if CIRCUITPY_NETWORK network_module_deinit(); #endif + + #if MICROPY_VFS + mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); + + // Unmount all heap allocated vfs mounts. + while (gc_nbytes(vfs) > 0) { + vfs = vfs->next; + } + MP_STATE_VM(vfs_mount_table) = vfs; + MP_STATE_VM(vfs_cur) = vfs; + #endif + + // Run any finalizers before we stop using the heap. + gc_sweep_all(); } #define STRING_LIST(...) {__VA_ARGS__, ""} diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index c70d52a7bb..d83282123e 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -123,7 +123,6 @@ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MULTI_PARTITION (1) -#define MICROPY_FATFS_NUM_PERSISTENT (1) // Only enable this if you really need it. It allocates a byte cache of this size. // #define MICROPY_FATFS_MAX_SS (4096) diff --git a/py/runtime.c b/py/runtime.c index fb62edf73b..060748f1b8 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -131,31 +131,6 @@ void mp_init(void) { sizeof(MP_STATE_VM(fs_user_mount)) - MICROPY_FATFS_NUM_PERSISTENT); #endif - #if MICROPY_VFS - #if MICROPY_FATFS_NUM_PERSISTENT > 0 - // We preserve the last MICROPY_FATFS_NUM_PERSISTENT mounts because newer - // mounts are put at the front of the list. - mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); - // Count how many mounts we have. - uint8_t count = 0; - while (vfs != NULL) { - vfs = vfs->next; - count++; - } - // Find the vfs MICROPY_FATFS_NUM_PERSISTENT mounts from the end. - vfs = MP_STATE_VM(vfs_mount_table); - for (uint8_t j = 0; j < count - MICROPY_FATFS_NUM_PERSISTENT; j++) { - vfs = vfs->next; - } - MP_STATE_VM(vfs_mount_table) = vfs; - MP_STATE_VM(vfs_cur) = vfs; - #else - // initialise the VFS sub-system - MP_STATE_VM(vfs_cur) = NULL; - MP_STATE_VM(vfs_mount_table) = NULL; - #endif - #endif - #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index c4f9cbeb79..5db571f33f 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -6,6 +6,7 @@ #include "shared-bindings/displayio/Display.h" #include "shared-bindings/displayio/Group.h" #include "shared-bindings/displayio/Palette.h" +#include "supervisor/shared/autoreload.h" #include "supervisor/shared/display.h" #include "supervisor/memory.h" #include "supervisor/usb.h" @@ -18,7 +19,13 @@ static inline void swap(uint16_t* a, uint16_t* b) { *b = temp; } +bool refreshing_displays = false; + void displayio_refresh_displays(void) { + if (refreshing_displays) { + return; + } + refreshing_displays = true; for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { if (displays[i].display.base.type == NULL || displays[i].display.base.type == &mp_type_NoneType) { continue; @@ -27,6 +34,7 @@ void displayio_refresh_displays(void) { displayio_display_update_backlight(display); if (!displayio_display_frame_queued(display)) { + refreshing_displays = false; return; } if (displayio_display_refresh_queued(display)) { @@ -89,8 +97,9 @@ void displayio_refresh_displays(void) { index += 1; // The buffer is full, send it. if (index >= buffer_size) { - if (!displayio_display_send_pixels(display, buffer, buffer_size / 2)) { + if (!displayio_display_send_pixels(display, buffer, buffer_size / 2) || reload_requested) { displayio_display_finish_region_update(display); + refreshing_displays = false; return; } // TODO(tannewt): Make refresh displays faster so we don't starve other @@ -103,12 +112,14 @@ void displayio_refresh_displays(void) { // Send the remaining data. if (index && !displayio_display_send_pixels(display, buffer, index * 2)) { displayio_display_finish_region_update(display); + refreshing_displays = false; return; } displayio_display_finish_region_update(display); } displayio_display_finish_refresh(display); } + refreshing_displays = false; } void common_hal_displayio_release_displays(void) { diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index d968f47986..3382d28be8 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -95,7 +95,7 @@ void filesystem_flush(void) { void filesystem_writable_by_python(bool writable) { fs_user_mount_t *vfs = &_internal_vfs; - if (writable) { + if (!writable) { vfs->flags |= FSUSER_USB_WRITABLE; } else { vfs->flags &= ~FSUSER_USB_WRITABLE; From 53fa65e318efc6ac17ae904e1e60cb91aa2ac954 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 15 Feb 2019 13:51:54 -0800 Subject: [PATCH 2/3] Speed up pyportal by writing memory on the same access as our rotation. --- ports/atmel-samd/boards/pyportal/board.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/atmel-samd/boards/pyportal/board.c b/ports/atmel-samd/boards/pyportal/board.c index d9631e2dc9..d2c328850b 100644 --- a/ports/atmel-samd/boards/pyportal/board.c +++ b/ports/atmel-samd/boards/pyportal/board.c @@ -48,7 +48,7 @@ uint8_t display_init_sequence[] = { 0xc1, 1, 0x10, // Power control SAP[2:0];BT[3:0] 0xc5, 2, 0x3e, 0x28, // VCM control 0xc7, 1, 0x86, // VCM control2 - 0x36, 1, 0x08, // Memory Access Control + 0x36, 1, 0xa8, // Memory Access Control 0x37, 1, 0x00, // Vertical scroll zero 0x3a, 1, 0x55, // COLMOD: Pixel Format Set 0xb1, 2, 0x00, 0x18, // Frame Rate Control (In Normal Mode/Full Colors) @@ -82,7 +82,7 @@ void board_init(void) { 240, // Height 0, // column start 0, // row start - 270, // rotation + 0, // rotation 16, // Color depth MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command From b1e8c4367987944c3faaad613142fec974840044 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 15 Feb 2019 13:52:25 -0800 Subject: [PATCH 3/3] Fix reload while display is updating. --- shared-module/displayio/__init__.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 5db571f33f..0d35abf0f6 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -2,6 +2,7 @@ #include #include "shared-module/displayio/__init__.h" +#include "py/reload.h" #include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/displayio/Display.h" #include "shared-bindings/displayio/Group.h" @@ -22,6 +23,12 @@ static inline void swap(uint16_t* a, uint16_t* b) { bool refreshing_displays = false; void displayio_refresh_displays(void) { + // Somehow reloads from the sdcard are being lost. So, cheat and reraise. + if (reload_requested) { + mp_raise_reload_exception(); + return; + } + if (refreshing_displays) { return; }