diff --git a/main.c b/main.c index 7b805b57b0..6ff6202d6d 100644 --- a/main.c +++ b/main.c @@ -1111,6 +1111,8 @@ void gc_collect(void) { // have lost their references in the VM even though they are mounted. gc_collect_root((void **)&MP_STATE_VM(vfs_mount_table), sizeof(mp_vfs_mount_t) / sizeof(mp_uint_t)); + port_gc_collect(); + background_callback_gc_collect(); #if CIRCUITPY_ALARM @@ -1143,6 +1145,10 @@ void gc_collect(void) { gc_collect_end(); } +// Ports may provide an implementation of this function if it is needed +MP_WEAK void port_gc_collect() { +} + void NORETURN nlr_jump_fail(void *val) { reset_into_safe_mode(SAFE_MODE_NLR_JUMP_FAIL); while (true) { diff --git a/ports/mimxrt10xx/common-hal/microcontroller/Pin.c b/ports/mimxrt10xx/common-hal/microcontroller/Pin.c index 9d55382306..fc455d7a27 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/Pin.c +++ b/ports/mimxrt10xx/common-hal/microcontroller/Pin.c @@ -28,6 +28,8 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" +#include "py/gc.h" + STATIC bool claimed_pins[IOMUXC_SW_PAD_CTL_PAD_COUNT]; STATIC bool never_reset_pins[IOMUXC_SW_PAD_CTL_PAD_COUNT]; @@ -147,6 +149,11 @@ typedef struct { volatile static pin_change_interrupt_data pcid[MP_ARRAY_SIZE(s_gpioBases)][32]; +// The 'data' pointers may be to gc objects, they must be kept alive. +void pin_gc_collect() { + gc_collect_root((void **)&pcid, sizeof(pcid) / sizeof(void *)); +} + void enable_pin_change_interrupt(const mcu_pin_obj_t *pin, gpio_change_interrupt_t func, void *data) { int instance = GPIO_GetInstance(pin->gpio); volatile pin_change_interrupt_data *pci = &pcid[instance][pin->number]; diff --git a/ports/mimxrt10xx/common-hal/microcontroller/Pin.h b/ports/mimxrt10xx/common-hal/microcontroller/Pin.h index cbcce13e2b..f75f4fbbee 100644 --- a/ports/mimxrt10xx/common-hal/microcontroller/Pin.h +++ b/ports/mimxrt10xx/common-hal/microcontroller/Pin.h @@ -48,5 +48,6 @@ extern bool mimxrt10xx_board_reset_pin_number(const mcu_pin_obj_t *pin); typedef void (gpio_change_interrupt_t)(void *data); void disable_pin_change_interrupt(const mcu_pin_obj_t *pin); void enable_pin_change_interrupt(const mcu_pin_obj_t *pin, gpio_change_interrupt_t func, void *data); +void pin_gc_collect(void); #endif // MICROPY_INCLUDED_MIMXRT10XX_COMMON_HAL_MICROCONTROLLER_PIN_H diff --git a/ports/mimxrt10xx/supervisor/port.c b/ports/mimxrt10xx/supervisor/port.c index 55bf72352d..1e46159829 100644 --- a/ports/mimxrt10xx/supervisor/port.c +++ b/ports/mimxrt10xx/supervisor/port.c @@ -555,6 +555,10 @@ void port_idle_until_interrupt(void) { common_hal_mcu_enable_interrupts(); } +void port_gc_collect(void) { + pin_gc_collect(); +} + // Catch faults where the memory access violates MPU settings. void MemManage_Handler(void); __attribute__((used)) void PLACE_IN_ITCM(MemManage_Handler)(void) { diff --git a/supervisor/port.h b/supervisor/port.h index 70bdcb0170..b50179e4de 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -128,4 +128,8 @@ void port_post_boot_py(bool heap_valid); // A default weak implementation is provided that does nothing. void port_boot_info(void); +// Some ports want to mark additional pointers as gc roots. +// A default weak implementation is provided that does nothing. +void port_gc_collect(void); + #endif // MICROPY_INCLUDED_SUPERVISOR_PORT_H