hathach / tinyusb

An open source cross-platform USB stack for embedded system
https://www.tinyusb.org
MIT License
5.05k stars 1.06k forks source link

Building TinyUSB as static library with provided CMakeLists doesn't link in DCD functions #2859

Closed brentmellor closed 1 day ago

brentmellor commented 3 days ago

Operating System

MacOS

Board

Custom

Firmware

Trying to link TinyUSB as static library into pre-existing STM32U575 codebase. The makefile-based builds for the TinyUSB examples are not suitable for us as we'd need to basically rewrite our existing software.

What happened ?

TinyUSB when built from the provided tinyusb/src/CMakeLists.txt file as a static library compiles and builds library file. However when attempting to use it, the project fails to link with missing references to the DCD driver functions that should have been included in TinyUSB.

Example build output:

...
[ 36%] Built target tinyusb
[ 37%] Linking C executable project_name.elf
/Applications/ArmGNUToolchain/13.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: libtinyusb.a(usbd.c.obj): in function `tud_rhport_init':
/.../tinyusb/src/device/usbd.c:493:(.text.tud_rhport_init+0x11e): undefined reference to `dcd_init'
/Applications/ArmGNUToolchain/13.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: /.../tinyusb/src/device/usbd.c:494:(.text.tud_rhport_init+0x148): undefined reference to `dcd_int_enable'
/Applications/ArmGNUToolchain/13.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: libtinyusb.a(usbd.c.obj): in function `tud_task_ext':
/.../tinyusb/src/device/usbd.c:624:(.text.tud_task_ext+0x15a): undefined reference to `dcd_edpt_stall'
/Applications/ArmGNUToolchain/13.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: /.../tinyusb/src/device/usbd.c:625:(.text.tud_task_ext+0x164): undefined reference to `dcd_edpt_stall'
/Applications/ArmGNUToolchain/13.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld: libtinyusb.a(usbd.c.obj): in function `process_control_request':
/.../tinyusb/src/device/usbd.c:754:(.text.process_control_request+0x180): undefined reference to `dcd_set_address'
...

How to reproduce ?

Our main project CMakeLists invokes and links everything with something like this (real file has a lot of libraries):

include(${CMAKE_SOURCE_DIR}/cmake/tinyusb.cmake)
...
add_dependencies(${PROJECT_NAME} tinyusb)
target_link_libraries(${PROJECT_NAME}
    PRIVATE tinyusb
)

The tinyusb.cmake file defines the CMake target "tinyusb_config" to expose tusb_config.h and launch the actual TinyUSB CMake file you provide in your repo.

add_library(tinyusb_config INTERFACE)
target_include_directories(tinyusb_config INTERFACE ${CMAKE_SOURCE_DIR}/src/)
include(${CMAKE_SOURCE_DIR}/external/tinyusb/src/CMakeLists.txt)

Here's the meat of our tusb_config.h, based off the dual-CDC example.

// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_TUD_RHPORT
#define BOARD_TUD_RHPORT      0
#endif

// RHPort max operational speed can defined by board.mk
#ifndef BOARD_TUD_MAX_SPEED
#define BOARD_TUD_MAX_SPEED   OPT_MODE_DEFAULT_SPEED
#endif

// Select family and processor part number
#define CFG_TUSB_MCU          OPT_MCU_STM32U5
#define STM32U575xx

// Select bare-metal system
#define CFG_TUSB_OS           OPT_OS_NONE

// Select TinyUSB internal debug output
//(needs UART or RTT setup and read/write syscalls implemented if configured)
#define CFG_TUSB_DEBUG        0

// Enable USB-Device stack
#define CFG_TUD_ENABLED       1

// Default is max speed that hardware controller could support with on-chip PHY
#define CFG_TUD_MAX_SPEED     BOARD_TUD_MAX_SPEED

#define CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_ALIGN          __attribute__ ((aligned(4)))

#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE    64
#endif

// Class
#define CFG_TUD_CDC               2
#define CFG_TUD_MSC               0
#define CFG_TUD_HID               0
#define CFG_TUD_MIDI              0
#define CFG_TUD_VENDOR            0

// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)

// CDC Endpoint transfer buffer size, more is faster
#define CFG_TUD_CDC_EP_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64)

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

N/A - Cannot link static library

Screenshots

No response

I have checked existing issues, dicussion and documentation

brentmellor commented 3 days ago

We were able to get the system to link by manually adding the DCD driver to our project's CMakeLists.txt and building it externally. (reverse engineered the example makefiles to find what file was needed)

I had expected TinyUSB to handle including the DCD driver automatically since all the defines needed to select the correct one are in tusb_config.h and the DCD drivers are located in the tinyusb/src folder. Since the logic to select the correct DCD is built into the makefiles for the examples, perhaps it could be added to the CMake build for the static library? At least there should be a note mentioning that externally compiling the DCD is required.

I'll wait to close this issue for a day to see if there's any comments or suggestions.

hathach commented 1 day ago

yeah, it is intended that user have to manually pick the dcd/hcd driver since some mcus can has different usbip on the same mcu, also some mcus can have different driver variant e.g esp32s2 has one with specific dcd_esp32sx and a more generic dwc2 driver.

brentmellor commented 1 day ago

Thanks for the confirmation, could we get a mention of needing to manually include the DCD file in the CMakeLists or getting started guide? It looks like the information is already available at