Picow: failing to link lwip


I’ve created an application that talks to a service via sockets.
This compiles fine, yet linking gives:

/home/folkert/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/12.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/BUILD_FOR_RP2040/src/server.cpp.o: in function `_ZN6serverD2Ev':
server.cpp:(.text._ZN6serverD2Ev+0xa): undefined reference to `lwip_close'

(also for lwip_accept, lwip_socket, lwip_read and so on).

I’m targetting the raspberry pi pico-w.

My platformio.ini looks like this:

default_envs = BUILD_FOR_RP2040
src_dir = .

lib_ldf_mode = deep+
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board_build.core = earlephilhower
board = rpipicow
framework = arduino
lib_deps = greiman/SdFat@^2.2.2
extra_scripts = pre:prepare.py



#define LWIP_SOCKET		 	1
#define NO_SYS                          1
#define MEM_ALIGNMENT                   4
#define LWIP_RAW                        1
#define LWIP_NETCONN                    0
#define LWIP_DHCP                       1
#define LWIP_ICMP                       1
#define LWIP_UDP                        0
#define LWIP_TCP                        1
#define ETH_PAD_SIZE                    0

#define TCP_MSS                         (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/)
#define TCP_SND_BUF                     (2 * TCP_MSS)

#define LWIP_TIMEVAL_PRIVATE            0       /* Use the system-wide timeval definitions */
#define MEM_LIBC_MALLOC             0

#define LWIP_DNS                    1

Any ideas?

f.w.i.w. the complete source code is at GitHub - folkertvanheusden/iESP at RP2040W

1 Like

No, you cannot modify the LWIP parameters like that by just changing lwiptopts, because LWIP is only present as a precompiled library in Arduino-Pico, not compiled from source. Your changes will be throughly ignored and this will only lead to the headers hallucinating that certain functions exist, when really their implementation isn’t present.

Activating LWIP_SOCKET in the context of the lwip support code present in Arduino-Pico is actually very difficult. (It can be done painlessly in pure Arduino-Pico with activated FreeRTOS and NO_SYS = 0). We’ve talked about that in https://github.com/earlephilhower/arduino-pico/discussions/1958.

However… you should still have a function to close a connection, even if the socket API is not present. A tcp_close must exist. Let me double check.

It seems like your server.cpp is very significantly relying on the socket API, although both the ESP32 and the Arduino-Pico would have had the WiFiServer class to offer which would have abstracted away the socket uniformly.

Unfortunately I think that Arduino-Pico is not the right choice here because of the current difficulties of getting LWIP_SOCKET turned on. You should either build the firmware with the native Pico-SDK (CMake) or use WiFiServer class as discussed.


Thanks for the elaborate help!

With cmake (I was trying that parallel to this) I have more luck regarding the lwip build.
Unfortunately there SD card stuff fails.
So I think I’ll rewrite server.cpp a bit to use the WifiServer class. At least I will look into that.

F.w.i.w.: I created a wrapper-class (another layer…) for the socket-api so that I can easily shove in an arduino-version.
It compiles, it links…and it hangs :slight_smile:

        Serial.println(F("Set hostname"));

        Serial.println(F("Start WiFi"));
        Serial.println(F("Disable WiFi low power"));
        Serial.print(F("Connecting to: "));
        WiFi.begin(ssid, wifi_pw);

It crashes somewhere after the WiFi.mode().

Picking the right pico will help… (w versus non-w).

1 Like