Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve RP2 Network Performance Issue #10027

Merged
merged 4 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion ports/raspberrypi/lib/lwip
Submodule lwip updated 151 files
13 changes: 13 additions & 0 deletions ports/raspberrypi/lwip_inc/lwip_mem.h
Original file line number Diff line number Diff line change
@@ -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 <stddef.h>

void *lwip_heap_malloc(size_t size);
void lwip_heap_free(void *ptr);
void *lwip_heap_calloc(size_t num, size_t size);
58 changes: 54 additions & 4 deletions ports/raspberrypi/lwip_inc/lwipopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
27 changes: 27 additions & 0 deletions ports/raspberrypi/lwip_src/lwip_mem.c
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>
#include <string.h>
#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;
}
25 changes: 16 additions & 9 deletions ports/raspberrypi/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

#include "tusb.h"
#include <cmsis_compiler.h>
#include "lib/tlsf/tlsf.h"

critical_section_t background_queue_lock;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand All @@ -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)) {
Expand Down
Loading