From ed5c0bd465df71d09ae9ec1475a230382f213851 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 4 Dec 2024 12:11:45 -0600 Subject: [PATCH 1/2] rgbmatrix: Avoid leaving an incompletely configured display bus I did not reproduce the exact problem reported; however, I reproduced that a failure to construct an RGBMatrix object would leave CircuitPython in an inconsistent state with a display bus registered but not working: ```py >>> import rgbmatrix, board; rgbmatrix.RGBMatrix(width=64, bit_depth=1, rgb_pins=[], addr_pins=[], clock_pin=board.A0, latch_pin=board.A1, output_enable_pin=board.A2) Traceback (most recent call last): File "", line 1, in ValueError: The length of rgb_pins must be 6, 12, 18, 24, or 30 >>> import rgbmatrix, board; rgbmatrix.RGBMatrix(width=64, bit_depth=1, rgb_pins=[], addr_pins=[], clock_pin=board.A0, latch_pin=board.A1, output_enable_pin=board.A2) Traceback (most recent call last): File "", line 1, in RuntimeError: Too many display busses; forgot displayio.release_displays() ? ``` After the fix the second call also results in a ValueError, not a RuntimeError, which is correct. Closes #9674 --- shared-bindings/rgbmatrix/RGBMatrix.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/shared-bindings/rgbmatrix/RGBMatrix.c b/shared-bindings/rgbmatrix/RGBMatrix.c index bb4b5093330e..f879190e830a 100644 --- a/shared-bindings/rgbmatrix/RGBMatrix.c +++ b/shared-bindings/rgbmatrix/RGBMatrix.c @@ -116,6 +116,16 @@ static void preflight_pins_or_throw(uint8_t clock_pin, uint8_t *rgb_pins, uint8_ #endif } +typedef struct { + nlr_jump_callback_node_t callback; + mp_obj_base_t *base_ptr; +} nlr_jump_callback_node_clear_displaybus_t; + +static void clear_display_bus(void *node_in) { + nlr_jump_callback_node_clear_displaybus_t *node = node_in; + node->base_ptr->type = &mp_type_NoneType; +} + //| def __init__( //| self, //| *, @@ -217,6 +227,13 @@ static mp_obj_t rgbmatrix_rgbmatrix_make_new(const mp_obj_type_t *type, size_t n rgbmatrix_rgbmatrix_obj_t *self = &allocate_display_bus_or_raise()->rgbmatrix; self->base.type = &rgbmatrix_RGBMatrix_type; + // If an exception is thrown, ensure the display bus object's type is set + // back to the uninitialized/deinitialied type. **note that all other resource + // deallocations must be handled by the shared-module code** + nlr_jump_callback_node_clear_displaybus_t node; + node.base_ptr = &self->base; + nlr_push_jump_callback(&node.callback, clear_display_bus); + uint8_t rgb_count, addr_count; uint8_t rgb_pins[MP_ARRAY_SIZE(self->rgb_pins)]; uint8_t addr_pins[MP_ARRAY_SIZE(self->addr_pins)]; @@ -254,7 +271,6 @@ static mp_obj_t rgbmatrix_rgbmatrix_make_new(const mp_obj_type_t *type, size_t n clock_pin, latch_pin, output_enable_pin, args[ARG_doublebuffer].u_bool, args[ARG_framebuffer].u_obj, tile, args[ARG_serpentine].u_bool, NULL); - claim_and_never_reset_pins(args[ARG_rgb_list].u_obj); claim_and_never_reset_pins(args[ARG_addr_list].u_obj); claim_and_never_reset_pin(args[ARG_clock_pin].u_obj); From bc465e51d710a9aacd4a1d20e24a4133f933087a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 4 Dec 2024 20:25:37 -0600 Subject: [PATCH 2/2] Disable terminal on itsybitsy depending on language .. as was already done for metro m4 express. Soon we're likely to need to do this across the board for 512kB flash SAMD51 parts. --- .../boards/itsybitsy_m4_express/mpconfigboard.mk | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk index d952a74b510b..de70d4fe0e55 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk @@ -16,3 +16,13 @@ CIRCUITPY_GIFIO = 0 CIRCUITPY_JPEGIO = 0 CIRCUITPY_BITBANG_APA102 = 1 + +# We don't have room for the fonts for terminalio for certain languages, +# so turn off terminalio, and if it's off and displayio is on, +# force a clean build. +# Note that we cannot test $(CIRCUITPY_DISPLAYIO) directly with an +# ifeq, because it's not set yet. +ifneq (,$(filter $(TRANSLATION),ja ko ru)) +CIRCUITPY_TERMINALIO = 0 +RELEASE_NEEDS_CLEAN_BUILD = $(CIRCUITPY_DISPLAYIO) +endif