From c80e7c14e6305e50e3b39f97172d4d8fe1214d3b Mon Sep 17 00:00:00 2001 From: cpottle9 Date: Tue, 7 Mar 2023 15:24:36 -0800 Subject: [PATCH] rp2: Allocate GC heap from unused RAM. Borrowing an idea from the mimxrt port (also stm32 port): in the loader input file memmap_mp.ld calculate __GcHeapStart and __GcHeapEnd as the unused RAM. Then in main.c use these addresses as arguments to gc_init(). The benefits of this change are: 1) When libraries are added or removed in the future changing BSS usage, main.c's sizing of the GC heap does not need to be changed. 2) Currently these changes make the GC area about 30 KBytes larger, eg on PICO_W the GC heap increases from 166016 to 192448 bytes. Without that change this RAM would never get used. 3) If someone wants to disable one or more SRAM blocks on the RP2040 to reduce power consumption it will be easy: just change the MEMORY section in memmap_mp.ld. For instance to not use SRAM2 and SRAM3 change it to: MEMORY { FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 128k SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k } Then to turn off clocks for SRAM2 and SRAM3 from MicroPython, set the appropriate bits in WAKE_EN0 and SLEEP_EN0. Tested by running the firmware.uf2 file on PICO_W and displaying micropython.mem_info(). Confirmed GC total size approximately matched the size calculated by the loader. Signed-off-by: cpottle9 --- ports/rp2/main.c | 12 ++---------- ports/rp2/memmap_mp.ld | 7 +++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ports/rp2/main.c b/ports/rp2/main.c index 570c4302f..afc22aee7 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -59,16 +59,8 @@ #include "lib/cyw43-driver/src/cyw43.h" #endif -#ifndef MICROPY_GC_HEAP_SIZE -#if MICROPY_PY_LWIP -#define MICROPY_GC_HEAP_SIZE 166 * 1024 -#else -#define MICROPY_GC_HEAP_SIZE 192 * 1024 -#endif -#endif - extern uint8_t __StackTop, __StackBottom; -__attribute__((section(".uninitialized_bss"))) static char gc_heap[MICROPY_GC_HEAP_SIZE]; +extern uint8_t __GcHeapStart, __GcHeapEnd; // Embed version info in the binary in machine readable form bi_decl(bi_program_version_string(MICROPY_GIT_TAG)); @@ -118,7 +110,7 @@ int main(int argc, char **argv) { // Initialise stack extents and GC heap. mp_stack_set_top(&__StackTop); mp_stack_set_limit(&__StackTop - &__StackBottom - 256); - gc_init(&gc_heap[0], &gc_heap[MP_ARRAY_SIZE(gc_heap)]); + gc_init(&__GcHeapStart, &__GcHeapEnd); #if MICROPY_PY_LWIP // lwIP doesn't allow to reinitialise itself by subsequent calls to this function diff --git a/ports/rp2/memmap_mp.ld b/ports/rp2/memmap_mp.ld index 82f9cb01c..6be05b094 100644 --- a/ports/rp2/memmap_mp.ld +++ b/ports/rp2/memmap_mp.ld @@ -248,11 +248,18 @@ SECTIONS __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); __StackBottom = __StackTop - SIZEOF(.stack_dummy); + /* Define start and end of GC heap */ + __GcHeapStart = __bss_end__; + __GcHeapEnd = __StackLimit; PROVIDE(__stack = __StackTop); /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") + /* Check GC heap is at least 128 KB */ + /* On a RP2040 using all SRAM this should always be the case. */ + ASSERT((__GcHeapEnd - __GcHeapStart) > 128*1024, "GcHeap is too small") + 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 */ }