raspberrypi / pico-examples

BSD 3-Clause "New" or "Revised" License
2.79k stars 810 forks source link

How to build net_lwip_webserver tinysb example in pico-examples? #238

Open sdbbs opened 2 years ago

sdbbs commented 2 years ago

The main CMakeLists.txt starts with add_subdirectory, and it does:

add_subdirectory(usb)

usb/CMakeLists.txt then does

add_subdirectory(device)

and finally, usb/device/CMakeLists.txt does:

set(FAMILY rp2040)
set(BOARD pico_sdk)
set(TINYUSB_FAMILY_PROJECT_NAME_PREFIX "tinyusb_dev_")
add_subdirectory(${PICO_TINYUSB_PATH}/examples/device tinyusb_device_examples)

add_subdirectory(dev_hid_composite)
add_subdirectory(dev_lowlevel)

For me, PICO_TINYUSB_PATH resolved to the tinyusb inside pico-sdk (e.g. /path/to/pico-sdk/lib/tinyusb), and ther e is a net_lwip_webserver subdirectory there:

$ ls /path/to/pico-sdk/lib/tinyusb/examples/device
audio_4_channel_mic/  cdc_msc_freertos/       hid_composite/           msc_dual_lun/        webusb_serial/
audio_test/           dfu/                    hid_composite_freertos/  net_lwip_webserver/  99-tinyusb.rules
board_test/           dfu_runtime/            hid_generic_inout/       uac2_headset/        CMakeLists.txt
cdc_dual_ports/       dynamic_configuration/  hid_multiple_interface/  usbtmc/
cdc_msc/              hid_boot_interface/     midi_test/               video_capture/

When I try to build pico-examples once, I can notice that a pico-examples/build/usb/device/tinyusb_device_examples directory does get created, and inside it, I can see a copy of net_lwip_webserver:

$ cd /path/to/pico-examples/build/usb/device/tinyusb_device_examples
$ ls
audio_4_channel_mic/  CMakeFiles/             hid_generic_inout/       pico-sdk/       cmake_install.cmake
audio_test/           dfu/                    hid_multiple_interface/  uac2_headset/   Makefile
board_test/           dfu_runtime/            midi_test/               usbtmc/
cdc_dual_ports/       dynamic_configuration/  msc_dual_lun/            video_capture/
cdc_msc/              hid_composite/          net_lwip_webserver/      webusb_serial/

... however, no .elf are built; if I try to issue make in this directory, a build starts and completes:

$ make
[  0%] No update step for 'ELF2UF2Build'
[  0%] No patch step for 'ELF2UF2Build'
[  0%] Performing configure step for 'ELF2UF2Build'
-- The C compiler identification is GNU 12.1.0
...
[100%] Built target tinyusb_dev_usbtmc
[100%] Built target tinyusb_dev_video_capture
[100%] Built target tinyusb_dev_webusb_serial

... however, net_lwip_webserver is still not built:

$ find . -name '*.elf'
./audio_4_channel_mic/tinyusb_dev_audio_4_channel_mic.elf
./audio_test/tinyusb_dev_audio_test.elf
./board_test/tinyusb_dev_board_test.elf
./cdc_dual_ports/tinyusb_dev_cdc_dual_ports.elf
./cdc_msc/tinyusb_dev_cdc_msc.elf
./dfu/tinyusb_dev_dfu.elf
./dfu_runtime/tinyusb_dev_dfu_runtime.elf
./dynamic_configuration/tinyusb_dev_dynamic_configuration.elf
./hid_composite/tinyusb_dev_hid_composite.elf
./hid_generic_inout/tinyusb_dev_hid_generic_inout.elf
./hid_multiple_interface/tinyusb_dev_hid_multiple_interface.elf
./midi_test/tinyusb_dev_midi_test.elf
./msc_dual_lun/tinyusb_dev_msc_dual_lun.elf
./uac2_headset/tinyusb_dev_uac2_headset.elf
./usbtmc/tinyusb_dev_usbtmc.elf
./video_capture/tinyusb_dev_video_capture.elf
./webusb_serial/tinyusb_dev_webusb_serial.elf

What would I have to do, in order to force the tinyusb net_lwip_webserver to be built as part of pico-examples?

sdbbs commented 2 years ago

Ok, I think I figured it out; first I noticed that the original [tinyusb/blob/master/examples/device/net_lwip_webserver/CMakeLists.txt) - unlike most other tinyusb examples - has this conditional stanza:

...
set(TOP "../../..")
get_filename_component(TOP "${TOP}" REALPATH)

if (EXISTS ${TOP}/lib/lwip/src)
    include(${TOP}/hw/bsp/family_support.cmake)
...

Basically, the project (along with the list of files to be compiled) gets created only if the ${TOP}/lib/lwip/src; in my case, these files get copied into pico-examples tree from pico-sdk; so I checked my pico-sdk path there, and while the parent lwip directory existed, the child lwip/src did not:

$ ls -la /path/to/pico-sdk/lib/tinyusb/lib/lwip/
total 4.0K
drwxr-xr-x 1 sd None 0 Mar 29 13:30 ./
drwxr-xr-x 1 sd None 0 Mar 29 13:30 ../

$ ls /path/to/pico-sdk/lib/tinyusb/lib/lwip/src
ls: cannot access '/path/to/pico-sdk/lib/tinyusb/lib/lwip/src': No such file or directory

And this "smelled" like an unitialized submodule - and indeed, it was: note that tinyusb is a submodule of pico-sdk - but it aslo turns out, lwip is a submodule of tinyusb; so apparently when I set this up, apparently I did not do recursive git submodule update:

$ cd /path/to/pico-sdk
$ git submodule status
 4bfab30c02279a0530e1a56f4a7c539f2d35a293 lib/tinyusb (0.12.0)

$ cd lib/tinyusb/
$ git submodule status
-7eb7bfa9ea4fbeacfafe1d5f77d5a0e6ed3922e7 hw/mcu/gd/nuclei-sdk
...
-159e31b689577dbf69cf0683bbaffbd71fa5ee10 lib/lwip
...

So first we need to checkout the submodules in pico-sdk:

$ cd /path/to/pico-sdk/lib/tinyusb/
$ git submodule update --init --recursive
Submodule 'hw/mcu/gd/nuclei-sdk' (https://github.com/Nuclei-Software/nuclei-sdk.git) registered for path 'hw/mcu/gd/nuclei-sdk'
...

Then, go back to pico-examples, and first repeat the cmake command in its build/ subdirectory (sometime just running make will notice changes in cmake files, and will automatically call cmake at start, but not in this case); and then finally:

$ cd /path/to/pico-examples/build/usb/device/tinyusb_device_examples
$ make
...
[100%] Linking CXX executable tinyusb_dev_net_lwip_webserver.elf
...

Nice - finally, also this example compiles!

Slion commented 4 weeks ago

Thanks for posting this. On Windows 11 using SDK 1.5.1 to build tinyusb_dev_net_lwip_webserver I also had to checkout the lwip submodule from the TinyUSB clone which is itself a submodule from the SDK. You will need to make sure you have admin right when doing that if like me your SDK is installed in Program Files. Tip don't update all submodules from TinyUSB cause there are a lot of them you don't need. Just update the lwip submodule. Once lwip is updated you need to reconfigure your pico-examples cmake and the missing target will show up. After building and flashing just point your host PC browser to http://tiny.usb you should get the lwip default page.

@sdbbs @kilograham This issue can be closed. Though maybe the readme file should be amended to mention the lwip submodule must be updated for that example to be available.

lurch commented 3 weeks ago

Though maybe the readme file should be amended to mention the lwip submodule must be updated for that example to be available.

Note that in later versions of TinyUSB (i.e. as used by Pico-SDK 2.0.0) it no longer uses submodules, but uses a separate script to download dependencies. See https://github.com/raspberrypi/pico-examples/issues/516#issuecomment-2294033687