diff --git a/.gitmodules b/.gitmodules index c1ab2f5d40130..b1c06ebcc9b4c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -312,7 +312,7 @@ [submodule "ports/raspberrypi/lib/lwip"] path = ports/raspberrypi/lib/lwip url = https://github.com/adafruit/lwip.git - branch = circuitpython8 + branch = circuitpython9 [submodule "lib/mbedtls"] path = lib/mbedtls url = https://github.com/ARMmbed/mbedtls.git diff --git a/ports/raspberrypi/lib/lwip b/ports/raspberrypi/lib/lwip index d26459c32c83a..bd522fde94093 160000 --- a/ports/raspberrypi/lib/lwip +++ b/ports/raspberrypi/lib/lwip @@ -1 +1 @@ -Subproject commit d26459c32c83aa14a6d4e30237d91cee36e0adbd +Subproject commit bd522fde9409398297b4e3244c92576b86ef16ec diff --git a/ports/raspberrypi/lwip_inc/lwip_mem.h b/ports/raspberrypi/lwip_inc/lwip_mem.h new file mode 100644 index 0000000000000..3e5c91a8bb048 --- /dev/null +++ b/ports/raspberrypi/lwip_inc/lwip_mem.h @@ -0,0 +1,13 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +void *lwip_heap_malloc(size_t size); +void lwip_heap_free(void *ptr); +void *lwip_heap_calloc(size_t num, size_t size); diff --git a/ports/raspberrypi/lwip_inc/lwipopts.h b/ports/raspberrypi/lwip_inc/lwipopts.h index 06df7f13181d1..e3ed4ad63dc11 100644 --- a/ports/raspberrypi/lwip_inc/lwipopts.h +++ b/ports/raspberrypi/lwip_inc/lwipopts.h @@ -5,6 +5,8 @@ // Common settings used in most of the pico_w examples // (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) +#include "lwip_mem.h" + // allow override in some examples #ifndef NO_SYS #define NO_SYS 1 @@ -20,14 +22,62 @@ #define MEM_LIBC_MALLOC 0 #endif #define MEM_ALIGNMENT 4 -#define MEM_SIZE 4000 -#define MEMP_NUM_TCP_SEG 32 -#define MEMP_NUM_ARP_QUEUE 10 -#define PBUF_POOL_SIZE 24 +// MEM_USE_POOLS: mem_malloc uses pools of fixed size memory blocks. Default is 0. +#define MEM_USE_POOLS 0 +// MEM_USE_POOLS_TRY_BIGGER_POOL: if one pool is empty, try the next bigger pool. Default is 0. +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +// MEMP_USE_CUSTOM_POOLS: Use custom pools defined in lwippools.h. Default is 0. +#define MEMP_USE_CUSTOM_POOLS 0 +// MEMP_MEM_MALLOC: Use mem_malloc() for pool memory. Default is 0. +#define MEMP_MEM_MALLOC 1 +#define MEM_CUSTOM_ALLOCATOR 1 +#define MEM_CUSTOM_FREE lwip_heap_free +#define MEM_CUSTOM_MALLOC lwip_heap_malloc +#define MEM_CUSTOM_CALLOC lwip_heap_calloc + +// MEM_SIZE: The LWIP heap size. Memory for mem_malloc and mem_calloc are allocated from +// this heap. If MEMP_MEM_MALLOC is set to 1, memory for memp_malloc is also allocated from +// this heap; if it is 0, memory is statically pre-allocated for each pool. +// Default is 1600. +#define MEM_SIZE 1600 +// MEMP_NUM_PBUF: memp pbufs used when sending from static memory. Default is 16. +#define MEMP_NUM_PBUF 16 +// MEMP_NUM_RAW_PCB: Number of raw connection PCBs. Default is 4. +#define MEMP_NUM_RAW_PCB 4 +// MEMP_NUM_UDP_PCB: Number of UDP PCBs. Default is 4. +#define MEMP_NUM_UDP_PCB 4 +// MEMP_NUM_TCP_PCB: Number of simultaneously active TCP connections. Default is 5. +#define MEMP_NUM_TCP_PCB 5 +// MEMP_NUM_TCP_PCB_LISTEN: Number of listening TCP PCBs. Default is 8. +#define MEMP_NUM_TCP_PCB_LISTEN 8 +// MEMP_NUM_TCP_SEG: Number of simultaneously queued TCP segments. Default is 16. +#define MEMP_NUM_TCP_SEG 16 +// MEMP_NUM_ALTCP_PCB: Number of simultaneously active altcp connections. Default is 5. +#define MEMP_NUM_ALTCP_PCB 5 +// MEMP_NUM_REASSDATA: Number of simultaneously IP packets queued for reassembly. Default is 5. +#define MEMP_NUM_REASSDATA 5 +// MEMP_NUM_FRAG_PBUF: Number of simultaneously IP fragments. Default is 15. +#define MEMP_NUM_FRAG_PBUF 15 +// MEMP_NUM_ARP_QUEUE: Number of simultaneously queued ARP packets. Default is 30. +#define MEMP_NUM_ARP_QUEUE 30 +// MEMP_NUM_IGMP_GROUP: Number of simultaneously active IGMP groups. Default is 8. +#define MEMP_NUM_IGMP_GROUP 8 +// MEMP_NUM_SYS_TIMEOUT: Number of simultaneously active timeouts. +// Use calculated default based on enabled modules. + +// PBUF_POOL_SIZE: Number of pbufs in the pbuf pool. Default is 16. +#define PBUF_POOL_SIZE 16 + +// LWIP's default 250 ms periodic timer interval is too long, resulting in network +// performance issues. We reduce it to 25 ms giving a slow-timer of 50 ms and a +// fast-timer of 25 ms. +#define TCP_TMR_INTERVAL 25 + #define LWIP_ARP 1 #define LWIP_ETHERNET 1 #define LWIP_ICMP 1 #define LWIP_RAW 1 + #define TCP_WND (8 * TCP_MSS) #define TCP_MSS 1460 #define TCP_SND_BUF (8 * TCP_MSS) diff --git a/ports/raspberrypi/lwip_src/lwip_mem.c b/ports/raspberrypi/lwip_src/lwip_mem.c new file mode 100644 index 0000000000000..244f51e289bc9 --- /dev/null +++ b/ports/raspberrypi/lwip_src/lwip_mem.c @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include +#include +#include "lib/tlsf/tlsf.h" +#include "lwip_mem.h" +#include "supervisor/port_heap.h" + +void *lwip_heap_malloc(size_t size) { + return port_malloc(size, true); +} + +void lwip_heap_free(void *ptr) { + port_free(ptr); +} + +void *lwip_heap_calloc(size_t num, size_t size) { + void *ptr = lwip_heap_malloc(num * size); + if (ptr != NULL) { + memset(ptr, 0, num * size); + } + return ptr; +} diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index 3b7b6d6f6d4df..f28553d64d799 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -56,6 +56,7 @@ #include "tusb.h" #include +#include "lib/tlsf/tlsf.h" critical_section_t background_queue_lock; @@ -83,20 +84,18 @@ extern uint32_t _ld_itcm_destination; extern uint32_t _ld_itcm_size; extern uint32_t _ld_itcm_flash_copy; -#ifdef CIRCUITPY_PSRAM_CHIP_SELECT +static tlsf_t _heap = NULL; +static pool_t _ram_pool = NULL; +static pool_t _psram_pool = NULL; +static size_t _psram_size = 0; -#include "lib/tlsf/tlsf.h" +#ifdef CIRCUITPY_PSRAM_CHIP_SELECT #include "src/rp2350/hardware_regs/include/hardware/regs/qmi.h" #include "src/rp2350/hardware_regs/include/hardware/regs/xip.h" #include "src/rp2350/hardware_structs/include/hardware/structs/qmi.h" #include "src/rp2350/hardware_structs/include/hardware/structs/xip_ctrl.h" -static tlsf_t _heap = NULL; -static pool_t _ram_pool = NULL; -static pool_t _psram_pool = NULL; -static size_t _psram_size = 0; - static void __no_inline_not_in_flash_func(setup_psram)(void) { gpio_set_function(CIRCUITPY_PSRAM_CHIP_SELECT->number, GPIO_FUNC_XIP_CS1); _psram_size = 0; @@ -236,8 +235,9 @@ static void __no_inline_not_in_flash_func(setup_psram)(void) { return; } } +#endif -void port_heap_init(void) { +static void _port_heap_init(void) { uint32_t *heap_bottom = port_heap_get_bottom(); uint32_t *heap_top = port_heap_get_top(); size_t size = (heap_top - heap_bottom) * sizeof(uint32_t); @@ -248,6 +248,10 @@ void port_heap_init(void) { } } +void port_heap_init(void) { + // We call _port_heap_init from port_init to initialize the heap early. +} + void *port_malloc(size_t size, bool dma_capable) { void *block = tlsf_malloc(_heap, size); return block; @@ -278,7 +282,6 @@ size_t port_heap_get_largest_free_size(void) { // IDF does this. Not sure why. return tlsf_fit_size(_heap, max_size); } -#endif safe_mode_t port_init(void) { _binary_info(); @@ -344,6 +347,9 @@ safe_mode_t port_init(void) { setup_psram(); #endif + // Initialize heap early to allow for early allocation. + _port_heap_init(); + // Check brownout. #if CIRCUITPY_CYW43 @@ -352,6 +358,7 @@ safe_mode_t port_init(void) { // are intended to meet the power on timing requirements, but apparently // are inadequate. We'll back off this long delay based on future testing. mp_hal_delay_ms(1000); + // Change this as a placeholder as to how to init with country code. // Default country code is CYW43_COUNTRY_WORLDWIDE) if (cyw43_arch_init_with_country(PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE)) {