diff --git a/ports/zephyr-cp/supervisor/port.c b/ports/zephyr-cp/supervisor/port.c index 1ecde0b0141..a46ce7c68f6 100644 --- a/ports/zephyr-cp/supervisor/port.c +++ b/ports/zephyr-cp/supervisor/port.c @@ -43,6 +43,18 @@ static tlsf_t heap; static size_t tlsf_heap_used = 0; +// TLSF writes its control structure into the first pool it is given, but +// dimensions that structure from the maximum heap size rather than from the +// region itself: tlsf_create_with_pool() forwards max_bytes to tlsf_create(), +// so both of its size checks test the maximum, not the space available. A +// region too small for the structure is therefore overrun rather than +// rejected. On a SiWx917-DK2605A with an 8 MB maximum the structure is 2412 +// bytes and landed in a 1 KB region, overrunning it by 1388 bytes. +// +// Only the region hosting the control structure has to satisfy this; smaller +// regions are still fine as additional pools. +#define MIN_FIRST_POOL_SIZE (8 * 1024) + // Auto generated in pins.c extern const struct device *const rams[]; extern const uint32_t *const ram_bounds[]; @@ -290,10 +302,23 @@ void port_heap_init(void) { } #endif + if (valid_pool_count == 0 && size < MIN_FIRST_POOL_SIZE) { + // Too small to hold the control structure. Leave it for a later + // pass rather than letting TLSF overrun it. + printk("Skipping region at %p: too small to host the heap control structure\n", heap_bottom); + pools[i] = NULL; + continue; + } + printk("Init heap at %p - %p with size %d\n", heap_bottom, heap_top, size); // If this crashes, then make sure you've enabled all of the Kconfig needed for the drivers. if (valid_pool_count == 0) { heap = tlsf_create_with_pool(heap_bottom, size, circuitpy_max_ram_size); + if (heap == NULL) { + printk("Heap creation failed at %p; trying the next region\n", heap_bottom); + pools[i] = NULL; + continue; + } pools[i] = tlsf_get_pool(heap); } else { pools[i] = tlsf_add_pool(heap, heap_bottom + 1, size - sizeof(uint32_t));