add doc for building examples with cmake build system

change ci matrix build:
- github build make/cmake one per family on push only
- circicle do full cmake build for all toolchain (missing rx-gcc)
This commit is contained in:
hathach
2025-07-02 14:41:16 +07:00
parent a42184b6fe
commit 4579b4f825
6 changed files with 107 additions and 125 deletions

View File

@@ -19,13 +19,12 @@ jobs:
echo "MATRIX_JSON=$MATRIX_JSON"
BUILDSYSTEM_TOOLCHAIN=(
"cmake aarch64-gcc"
"cmake arm-clang"
"cmake arm-gcc"
"cmake esp-idf"
"make aarch64-gcc"
"make arm-gcc"
"make msp430-gcc"
"make riscv-gcc"
"make rx-gcc"
"cmake msp430-gcc"
"cmake riscv-gcc"
)
# only build IAR if not forked PR, since IAR token is not shared

View File

@@ -36,11 +36,6 @@ env:
HIL_JSON: test/hil/tinyusb.json
jobs:
# ---------------------------------------
#
# Build
#
# ---------------------------------------
set-matrix:
runs-on: ubuntu-latest
outputs:
@@ -63,28 +58,31 @@ jobs:
echo "hil_matrix=$HIL_MATRIX_JSON" >> $GITHUB_OUTPUT
# ---------------------------------------
# Build CMake
# Build CMake: only build on push with one-per-family.
# Full built is done by CircleCI in PR
# ---------------------------------------
cmake:
if: github.event_name == 'push'
needs: set-matrix
uses: ./.github/workflows/build_util.yml
strategy:
fail-fast: false
matrix:
toolchain:
# - 'arm-clang' is built by circle-ci in PR
- 'aarch64-gcc'
- 'arm-clang'
- 'arm-gcc'
- 'esp-idf'
- 'msp430-gcc'
- 'riscv-gcc'
with:
build-system: 'cmake'
toolchain: ${{ matrix.toolchain }}
build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }}
one-per-family: ${{ github.event_name == 'push' }}
one-per-family: true
# ---------------------------------------
# Build Make (built by circle-ci in PR, only build on push here)
# Build Make: only build on push with one-per-family
# ---------------------------------------
make:
if: github.event_name == 'push'
@@ -94,19 +92,39 @@ jobs:
fail-fast: false
matrix:
toolchain:
# 'arm-clang'
- 'arm-gcc'
- 'aarch64-gcc'
- 'arm-clang'
- 'arm-gcc'
- 'msp430-gcc'
- 'riscv-gcc'
- 'rx-gcc'
- 'esp-idf'
with:
build-system: 'make'
toolchain: ${{ matrix.toolchain }}
build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }}
one-per-family: true
# ---------------------------------------
# Build IAR
# Since IAR Token secret is not passed to forked PR, only build non-forked PR with make.
# cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family
# ---------------------------------------
arm-iar:
if: github.event_name == 'push' && github.repository_owner == 'hathach'
needs: set-matrix
uses: ./.github/workflows/build_util.yml
secrets: inherit
strategy:
fail-fast: false
matrix:
build-system:
- 'make'
with:
build-system: ${{ matrix.build-system }}
toolchain: 'arm-iar'
build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }}
one-per-family: true
# ---------------------------------------
# Build Make on Windows/MacOS
# ---------------------------------------
@@ -124,28 +142,6 @@ jobs:
build-args: '["stm32h7"]'
one-per-family: true
# ---------------------------------------
# Build IAR
# Since IAR Token secret is not passed to forked PR, only build non-forked PR with make.
# cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family
# ---------------------------------------
arm-iar:
if: false # disable for now since we got reach capacity limit too often
#if: github.event_name == 'push' && github.repository_owner == 'hathach'
needs: set-matrix
uses: ./.github/workflows/build_util.yml
secrets: inherit
strategy:
fail-fast: false
matrix:
build-system:
- 'make'
with:
build-system: ${{ matrix.build-system }}
toolchain: 'arm-iar'
build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }}
one-per-family: true
# ---------------------------------------
# Zephyr
# ---------------------------------------
@@ -168,14 +164,9 @@ jobs:
west build -b pca10056 -d examples/device/msc_dual_lun/build examples/device/msc_dual_lun -- -DRTOS=zephyr
# ---------------------------------------
#
# Hardware in the loop (HIL)
# Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR
# ---------------------------------------
# ---------------------------------------
# Build arm-gcc
# ---------------------------------------
hil-build:
if: |
github.repository_owner == 'hathach' &&

View File

@@ -5,12 +5,12 @@ Getting Started
Add TinyUSB to your project
---------------------------
It is relatively simple to incorporate tinyusb to your project
To incorporate tinyusb to your project
* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is ``your_project/tinyusb``
* Add all the ``.c`` in the ``tinyusb/src`` folder to your project
* Add ``your_project/tinyusb/src`` to your include path. Also make sure your current include path also contains the configuration file ``tusb_config.h``.
* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by IDE/compiler to maintain a unique configure for all boards).
* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by make/cmake to maintain a unique configure for all boards).
* If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud descriptor** callbacks for the stack to work.
* Add ``tusb_init(rhport, role)`` call to your reset initialization code.
* Call ``tusb_int_handler(rhport, in_isr)`` in your USB IRQ Handler
@@ -75,24 +75,36 @@ The hardware code is located in ``hw/bsp`` folder, and is organized by family/bo
.. code-block:: bash
$ cd examples/device/cdc_msc
$ make BOARD=raspberry_pi_pico get-deps
$ make BOARD=feather_nrf52840_express get-deps
You only need to do this once per family. Check out `complete list of dependencies and their designated path here <dependencies.rst>`_
Build
^^^^^
Build Examples
^^^^^^^^^^^^^^
To build example, first change directory to an example folder.
Examples support make and cmake build system, though some MCU family such as espressif/rp2040 only support cmake. First change directory to an example folder.
.. code-block:: bash
$ cd examples/device/cdc_msc
Then compile with ``make BOARD={board_name} all`` , for example
Then compile with make or cmake
.. code-block:: bash
$ make BOARD=raspberry_pi_pico all
$ # make
$ make BOARD=feather_nrf52840_express all
$ # cmake
$ mkdir build && cd build
$ cmake -DBOARD=raspberry_pi_pico ..
$ make
To list all available targets with cmake
.. code-block:: bash
$ cmake --build . --target help
Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``99-tinyusb.rules`` and reload your udev is good to go
@@ -104,20 +116,24 @@ Note: some examples especially those that uses Vendor class (e.g webUSB) may req
RootHub Port Selection
~~~~~~~~~~~~~~~~~~~~~~
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``RHPORT_DEVICE=x`` or ``RHPORT_HOST=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
.. code-block:: bash
$ make BOARD=stm32f746disco PORT=1 all
$ make BOARD=stm32f746disco RHPORT_DEVICE=1 all
$ cmake -DBOARD=stm32f746disco -DRHPORT_DEVICE=1 ..
Port Speed
~~~~~~~~~~
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``SPEED=full/high`` e.g To force F723 operate at full instead of default high speed
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``RHPORT_DEVICE_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` or ``RHPORT_HOST_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` e.g To force F723 operate at full instead of default high speed
.. code-block:: bash
$ make BOARD=stm32f746disco SPEED=full all
$ make BOARD=stm32f746disco RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED all
$ cmake -DBOARD=stm32f746disco -DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED ..
Size Analysis
~~~~~~~~~~~~~
@@ -137,6 +153,8 @@ To compile for debugging add ``DEBUG=1``\ , for example
$ make BOARD=feather_nrf52840_express DEBUG=1 all
$ cmake -DBOARD=feather_nrf52840_express -DCMAKE_BUILD_TYPE=Debug ..
Log
~~~
@@ -146,6 +164,8 @@ Should you have an issue running example and/or submitting an bug report. You co
$ make BOARD=feather_nrf52840_express LOG=2 all
$ cmake -DBOARD=feather_nrf52840_express -DLOG=2 ..
Logger
~~~~~~
@@ -169,6 +189,9 @@ By default log message is printed via on-board UART which is slow and take lots
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all
$ cmake -DBOARD=feather_nrf52840_express -DLOG=2 -DLOGGER=rtt ..
$ cmake -DBOARD=feather_nrf52840_express -DLOG=2 -DLOGGER=swo ..
Flash
^^^^^
@@ -179,11 +202,15 @@ Flash
$ make BOARD=feather_nrf52840_express flash
$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash
Since jlink can be used with most of the boards, there is also ``flash-jlink`` target for your convenience.
Since jlink/openocd can be used with most of the boards, there is also ``flash-jlink/openocd`` (make) and ``EXAMPLE-jlink/openocd`` target for your convenience. Note for stm32 board with stlink, you can use ``flash-stlink`` target as well.
.. code-block:: bash
$ make BOARD=feather_nrf52840_express flash-jlink
$ make BOARD=feather_nrf52840_express flash-openocd
$ cmake --build . --target cdc_msc-jlink
$ cmake --build . --target cdc_msc-openocd
Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with ``uf2`` target
@@ -191,17 +218,18 @@ Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can
$ make BOARD=feather_nrf52840_express all uf2
$ cmake --build . --target cdc_msc-uf2
IAR Support
-----------
^^^^^^^^^^^
Use project connection
^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~
IAR Project Connection files are provided to import TinyUSB stack into your project.
* A buildable project of your MCU need to be created in advance.
* Take example of STM32F0:
- You need ``stm32l0xx.h``, ``startup_stm32f0xx.s``, ``system_stm32f0xx.c``.
@@ -212,15 +240,13 @@ IAR Project Connection files are provided to import TinyUSB stack into your proj
Click ``New Group ...``, name it to ``TUSB``, Click ``Add Variable ...``, name it to ``TUSB_DIR``, change it's value to the path of your TinyUSB stack,
for example ``C:\\tinyusb``
Import stack only
~~~~~~~~~~~~~~~~~
**Import stack only**
1. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``.
Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``.
Run examples
~~~~~~~~~~~~
**Run examples**
1. (Python3 is needed) Run ``iar_gen.py`` to generate .ipcf files of examples:
1. Run ``iar_gen.py`` to generate .ipcf files of examples:
.. code-block::
@@ -231,7 +257,7 @@ Run examples
For example ``C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf``
Native CMake support (9.50.1+)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With 9.50.1 release, IAR added experimental native CMake support (strangely not mentioned in public release note). Now it's possible to import CMakeLists.txt then build and debug as a normal project.

View File

@@ -1,5 +1,3 @@
cmake_minimum_required(VERSION 3.5)
# Apply board specific content i.e IDF_TARGET must be set before project.cmake is included
include("${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake")
string(TOUPPER ${IDF_TARGET} FAMILY_MCUS)

View File

@@ -1,32 +0,0 @@
UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee
UF2_FAMILY_ID_esp32s3 = 0xc47e5767
BOARD_CMAKE := $(file < $(TOP)/$(BOARD_PATH)/board.cmake)
ifneq ($(findstring esp32s2,$(BOARD_CMAKE)),)
IDF_TARGET = esp32s2
else
ifneq ($(findstring esp32s3,$(BOARD_CMAKE)),)
IDF_TARGET = esp32s3
endif
endif
.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu
all:
idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) build
build: all
fullclean:
if test -f sdkconfig; then $(RM) -f sdkconfig ; fi
if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi
idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@
clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files:
idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@
uf2: $(BUILD)/$(PROJECT).uf2
$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin
@echo CREATE $@
$(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_$(IDF_TARGET)) -b 0x0 -c -o $@ $^

View File

@@ -11,36 +11,37 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/msp430_${T
set(FAMILY_MCUS MSP430x5xx CACHE INTERNAL "")
#------------------------------------
# BOARD_TARGET
#------------------------------------
# only need to be built ONCE for all examples
function(add_board_target BOARD_TARGET)
if (NOT TARGET ${BOARD_TARGET})
add_library(${BOARD_TARGET} INTERFACE)
target_compile_definitions(${BOARD_TARGET} INTERFACE
CFG_TUD_ENDPOINT0_SIZE=8
CFG_EXAMPLE_VIDEO_READONLY
CFG_EXAMPLE_MSC_READONLY
)
target_include_directories(${BOARD_TARGET} INTERFACE
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${SDK_DIR}
)
if (TARGET ${BOARD_TARGET})
return()
endif ()
update_board(${BOARD_TARGET})
add_library(${BOARD_TARGET} INTERFACE)
target_compile_definitions(${BOARD_TARGET} INTERFACE
CFG_TUD_ENDPOINT0_SIZE=8
CFG_EXAMPLE_VIDEO_READONLY
CFG_EXAMPLE_MSC_READONLY
)
target_include_directories(${BOARD_TARGET} INTERFACE
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
${SDK_DIR}
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${BOARD_TARGET} INTERFACE
"LINKER:--script=${LD_FILE_GNU}"
-L${SDK_DIR}
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} INTERFACE
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
update_board(${BOARD_TARGET})
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${BOARD_TARGET} INTERFACE
"LINKER:--script=${LD_FILE_GNU}"
-L${SDK_DIR}
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} INTERFACE
"LINKER:--config=${LD_FILE_IAR}"
)
endif ()
endfunction()
@@ -75,7 +76,6 @@ function(family_configure_example TARGET RTOS)
)
target_link_libraries(${TARGET} PUBLIC board_${BOARD})
# Flashing
family_add_bin_hex(${TARGET})
family_flash_msp430flasher(${TARGET})