build and performance issue with iperf client example with FreeRTOS
Hello,
I wanted to check the iperf client performance with FreeRTOS on Pico_w. I modified the example file picow_freertos_iperf.c from github , with
#define CLIENT_TEST 1
#define IPERF_SERVER_IP "10.10.10.231"
However, I get the following compile errors:
uC/src/main.c:82:47: warning: implicit declaration of function 'xstr' [-Wimplicit-function-declaration]
82 | ip4_addr_set_u32(&clientaddr, ipaddr_addr(xstr(IPERF_SERVER_IP)));
| ^~~~
/datadisk/elec_price_monitor/uC/src/main.c:82:47: warning: passing argument 1 of 'ipaddr_addr' makes pointer from integer without a cast [-Wint-conversion]
82 | ip4_addr_set_u32(&clientaddr, ipaddr_addr(xstr(IPERF_SERVER_IP)));
| ^~~~~~~~~~~~~~~~~~~~~
| |
| int
/datadisk/pico/pico-sdk/lib/lwip/src/include/lwip/ip4_addr.h:213:31: note: expected 'const char *' but argument is of type 'int'
213 | u32_t ipaddr_addr(const char *cp);
| ~~~~~~~~~~~~^~
[ 5%] Linking CXX executable ../elec-price-mon.elf
/usr/lib/gcc/arm-none-eabi/13.2.1/../../../arm-none-eabi/bin/ld: CMakeFiles/elec-price-mon.dir/main.c.o: in function `main_task':
/datadisk/elec_price_monitor/uC/src/main.c:82:(.text.main_task+0x4e): undefined reference to `xstr'
Memory region Used Size Region Size %age Used
FLASH: 347404 B 2 MB 16.57%
RAM: 183212 B 256 KB 69.89%
SCRATCH_X: 2 KB 4 KB 50.00%
SCRATCH_Y: 0 B 4 KB 0.00%
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/elec-price-mon.dir/build.make:2888: elec-price-mon.elf] Error 1
make[1]: *** [CMakeFiles/Makefile2:1920: src/CMakeFiles/elec-price-mon.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Removing xstr ofcourse builds the code and i am able to run it on pico_w. A quick grep in the pico_sdk directory didn't return anything.
I have the following directories and libraries linked via the CMakeLists.txt
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/../include
)
target_link_libraries(${PROJECT_NAME}
pico_cyw43_arch_lwip_sys_freertos
pico_stdlib
pico_lwip_iperf
FreeRTOS-Kernel-Heap4 # FreeRTOS kernel and dynamic heap
)
Regarding the performance, it seems low. I noticed that someone reported around 12mbps for their server, however I am barely seeing 1Mbits/s. Following are the logs from serial.
Starting FreeRTOS SMP on both cores:
Version: 7.95.49 (2271bb6 CY) CRC: b7a28ef3 Date: Mon 2021-11-29 22:50:27 0
cyw43 loaded ok, mac 28:cd:c1:0f:6b:f2
API: 12.2
Data: RaspberryPi.PicoW
Compiler: 1.29.4
ClmImport: 1.47.1
Customization: v5 22/06/24
Creation: 2022-06-24 06:55:08
Connecting to Wi-Fi...
connect status: joining
connect status: no ip
connect status: link up
Connected.
blink_task starts
Ready, running iperf client
Completed iperf transfer of 1 MBytes @ 1.5 Mbits/sec
Total iperf megabytes since start 1 Mbytes
I have these additional options in the lwipopts.h
#define NO_SYS 0
#define LWIP_SOCKET 1
#define TCPIP_THREAD_STACKSIZE 1024
#define DEFAULT_THREAD_STACKSIZE 1024
#define DEFAULT_RAW_RECVMBOX_SIZE 8
#define TCPIP_MBOX_SIZE 8
#define LWIP_TIMEVAL_PRIVATE 0
// not necessary, can be done either way
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
Yes, looks like some bitrot. Try adding the following...
#define xstr(s) str(s)
#define str(s) #s
Maybe we should use pico_configure_ip4_address. What performance do you get with the non-freertos examples? I would expect you'd get the same as Freertos. If you want more good iperf performance you're at least going to have to double MEM_SIZE a couple of times.
Thanks. However in the current context ipaddr_addr(xstr(IPERF_SERVER_IP)), what is even the point of this macro if IPERF_SERVER_IP is already defined as a string like "1.2.3.4" ?
Haven't checked the performance with non-freertos example as in my use case i need both freertos and lwip. But do agree, probably more memory and buffers will be needed.
All it's doing is adding quotes. So you can set IPERF_SERVER_IP=1.2.3.4 rather than IPERF_SERVER_IP=\"1.2.3.4\"
Yes, looks like some bitrot. Try adding the following...
#define xstr(s) str(s) #define str(s) #s
Hmmm, I wonder why this wasn't failing in CI?
$ git grep xstr
pico_w/wifi/freertos/iperf/picow_freertos_iperf.c: ip4_addr_set_u32(&clientaddr, ipaddr_addr(xstr(IPERF_SERVER_IP)));
pico_w/wifi/iperf/picow_iperf.c: ip4_addr_set_u32(&clientaddr, ipaddr_addr(xstr(IPERF_SERVER_IP)));
If I search in https://github.com/raspberrypi/pico-examples/actions/runs/15453395505/job/43500581539 (the pico2_w CI-build for the most recent commit on the develop branch) I can find:
[ 20%] Building C object pico_w/wifi/iperf/CMakeFiles/picow_iperf_server_background.dir/picow_iperf.c.o
with no build errors reported? 🤔 Is it possible that some compilers / toolchains include this macro-definition, but others don't?
Oh, I've managed to answer my own question... 😆 The xstr usage is inside a #if CLIENT_TEST, and so we obviously never set CLIENT_TEST during the CI build! 🤦
Perhaps we ought to have a separate CI job (or just an extra build-step inside the existing pico2_w CI job?) that does a build with CLIENT_TEST and IPERF_SERVER_IP defined, so that the iperf client code at least gets compile-checked?