summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2021-01-23 23:28:35 +0700
committerGitHub <[email protected]>2021-01-23 23:28:35 +0700
commit469ca2f1559800f4b1eabc860336ff33ed118718 (patch)
treea6b68799030fd5cdc41881ebdbd259a8ee97b1e6
parentedd91d28f5afa175d7f52ec1bf1845ff29aabab9 (diff)
parente6ce18b01990d5e06f12e0aeb57d53ce365ba7b7 (diff)
Merge pull request #600 from hathach/refactor-bsp
Refactor bsp
-rw-r--r--.github/workflows/build.yml94
-rw-r--r--.gitmodules7
-rw-r--r--README.md6
-rw-r--r--docs/boards.md4
-rw-r--r--examples/device/board_test/CMakeLists.txt64
-rw-r--r--examples/device/cdc_msc/CMakeLists.txt72
-rw-r--r--examples/device/cdc_msc/src/tusb_config.h2
-rw-r--r--examples/device/cdc_msc_freertos/CMakeLists.txt15
-rw-r--r--examples/device/hid_composite_freertos/CMakeLists.txt15
-rw-r--r--examples/device/uac2_headset/.skip.MCU_SAMD110
-rw-r--r--examples/device/uac2_headset/.skip.MCU_SAME5X0
-rw-r--r--examples/device/uac2_headset/.skip.MCU_SAMG0
-rw-r--r--examples/make.mk2
-rw-r--r--examples/rules.mk28
-rw-r--r--hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h (renamed from hw/bsp/esp32s2/boards/esp32s2_kaluga_1/board.h)0
-rw-r--r--hw/bsp/esp32s2/boards/espressif_saola_1/board.h (renamed from hw/bsp/esp32s2/boards/esp32s2_saola_1/board.h)0
-rw-r--r--hw/bsp/esp32s2/family.cmake6
-rw-r--r--hw/bsp/esp32s2/family.mk2
-rw-r--r--hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c99
-rw-r--r--hw/bsp/rp2040/boards/raspberry_pi_pico/board.h46
-rw-r--r--hw/bsp/rp2040/family.c137
-rw-r--r--hw/bsp/rp2040/family.cmake3
-rw-r--r--hw/bsp/rp2040/family_extra.cmake1
m---------hw/mcu/raspberrypi/pico-sdk0
-rw-r--r--src/host/usbh.c2
-rw-r--r--tools/build_board.py (renamed from tools/build_all.py)98
-rw-r--r--tools/build_esp32s.py102
-rw-r--r--tools/build_esp32s2.py99
-rw-r--r--tools/build_family.py136
29 files changed, 722 insertions, 318 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e5b8cd6ae..f1732027f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -20,8 +20,50 @@ jobs:
cd test
ceedling test:all
- # Build most of the ports
- build:
+ # build all example for each family
+ build-family:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ family:
+ - 'imxrt'
+ - 'nrf'
+ #- 'rp2040'
+ - 'samd21'
+ - 'samd51'
+ - 'stm32f4'
+ - 'stm32f7'
+ steps:
+ - name: Setup Python
+ uses: actions/setup-python@v2
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v1
+
+ - name: Install Toolchains
+ run: |
+ # ARM GCC from xpack
+ npm install --global xpm
+ xpm install --global @xpack-dev-tools/arm-none-eabi-gcc@latest
+ echo `echo $HOME/opt/xPacks/@xpack-dev-tools/arm-none-eabi-gcc/*/.content/bin` >> $GITHUB_PATH
+
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v2
+ with:
+ submodules: 'true'
+
+ - name: Checkout Sub-Submodules
+ run: |
+ # some submodule has it own submodules that need to be fetched as well
+ git submodule update --init --recursive hw/mcu/microchip
+ git submodule update --init --recursive lib/FreeRTOS
+
+ - name: Build
+ run: python3 tools/build_family.py ${{ matrix.family }}
+
+ # Build all no-family (opharned) boards
+ build-board:
runs-on: ubuntu-latest
strategy:
fail-fast: false
@@ -40,28 +82,36 @@ jobs:
- 'device/midi_test'
- 'device/msc_dual_lun'
- 'device/net_lwip_webserver'
+ - 'device/uac2_headset'
- 'device/usbtmc'
- 'device/webusb_serial'
- 'host/cdc_msc_hid'
steps:
- name: Setup Python
- uses: actions/setup-python@v1
+ uses: actions/setup-python@v2
- name: Setup Node.js
uses: actions/setup-node@v1
- name: Cache MSP430 Toolchain
+ uses: actions/cache@v2
id: cache-msp430
- uses: actions/cache@v1
with:
path: /tmp/dl/
# Increment gcc version number at end when updating downloads
- key: msp430-${{ runner.os }}-9.2.0.50
+ key: ${{ runner.os }}-msp430-9.2.0.50
- - name: Install Toolchains
+ - name: Install MSP430 Toolchain
+ if: steps.cache-msp430.outputs.cache-hit != 'true'
env:
- MSP430GCC_URL: http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2
+ MSP430GCC_URL: http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2
+ run: |
+ mkdir -p /tmp/dl/
+ [ -f "/tmp/dl/msp430-gcc.tar.bz2" ] || wget --progress=dot:mega $MSP430GCC_URL -O /tmp/dl/msp430-gcc.tar.bz2
+ tar -C $HOME -xaf /tmp/dl/msp430-gcc.tar.bz2
+
+ - name: Install Toolchains
run: |
# ARM & RISC-V GCC from xpack
npm install --global xpm
@@ -71,39 +121,35 @@ jobs:
echo `echo $HOME/opt/xPacks/@xpack-dev-tools/riscv-none-embed-gcc/*/.content/bin` >> $GITHUB_PATH
# TI MSP430 GCC
- mkdir -p /tmp/dl/
- [ -f "/tmp/dl/msp430-gcc.tar.bz2" ] || wget --progress=dot:mega $MSP430GCC_URL -O /tmp/dl/msp430-gcc.tar.bz2
- tar -C $HOME -xaf /tmp/dl/msp430-gcc.tar.bz2
echo `echo $HOME/msp430-gcc-*_linux64/bin` >> $GITHUB_PATH
- name: Checkout TinyUSB
uses: actions/checkout@v2
with:
- # Cannot do submodule checkout here since LWIP's git server cannot checkout unadventised commits (it must use tags)
- submodules: 'false'
+ submodules: 'true'
- - name: Checkout Submodules
+ - name: Checkout Sub-Submodules
run: |
- git submodule sync --recursive
- # Special case LWIP since GNU's Savannah can't do shallow checkout of non-tagged commits
- git submodule update --init --recursive lib/lwip
- git submodule update --init --recursive --depth 1
+ # some submodule has it own submodules that need to be fetched as well
+ git submodule update --init --recursive hw/mcu/microchip
+ git submodule update --init --recursive lib/FreeRTOS
- name: Build
- run: |
- python3 tools/build_all.py ${{ matrix.example }}
+ run: python3 tools/build_board.py ${{ matrix.example }}
- # Build ESP32S
- build-esp32s:
+ # Build ESP32S2
+ build-esp32s2:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
- example: ['board_test', 'cdc_msc_freertos', 'hid_composite_freertos']
+ board:
+ - 'espressif_kaluga_1'
+ - 'espressif_saola_1'
steps:
- name: Setup Python
- uses: actions/setup-python@v1
+ uses: actions/setup-python@v2
- name: Pull ESP-IDF docker
run: docker pull espressif/idf:latest
@@ -114,4 +160,4 @@ jobs:
submodules: 'false'
- name: Build
- run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32s.py ${{ matrix.example }}
+ run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32s2.py ${{ matrix.board }}
diff --git a/.gitmodules b/.gitmodules
index 1fefa13f0..46e2d807c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -21,7 +21,7 @@
url = https://github.com/majbthrd/nuc_driver.git
[submodule "lib/lwip"]
path = lib/lwip
- url = https://git.savannah.nongnu.org/git/lwip.git
+ url = https://github.com/lwip-tcpip/lwip.git
[submodule "lib/FreeRTOS"]
path = lib/FreeRTOS
url = https://github.com/FreeRTOS/FreeRTOS.git
@@ -112,3 +112,8 @@
[submodule "lib/sct_neopixel"]
path = lib/sct_neopixel
url = https://github.com/gsteiert/sct_neopixel
+[submodule "hw/mcu/raspberrypi/pico-sdk"]
+ path = hw/mcu/raspberrypi/pico-sdk
+ url = https://github.com/raspberrypi/pico-sdk.git
+ fetchRecurseSubmodules = false
+
diff --git a/README.md b/README.md
index 0ed84e9e8..74e5a4afb 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ The stack supports the following MCUs:
- iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064
- Kinetis: KL25
- LPC Series: 11Uxx, 13xx, 175x_6x, 177x_8x, 18xx, 40xx, 43xx, 51Uxx, 54xxx, 55xx
+- **Raspberry Pi:** RP2040
- **Sony:** CXD56
- **ST:** STM32 series: L0, F0, F1, F2, F3, F4, F7, H7 both FullSpeed and HighSpeed
- **TI:** MSP430
@@ -98,8 +99,9 @@ TinyUSB is currently used by these other projects:
- [Adafruit nRF52 Bootloader](https://github.com/adafruit/Adafruit_nRF52_Bootloader)
- [Adafruit SAMD Arduino](https://github.com/adafruit/ArduinoCore-samd)
- [CircuitPython](https://github.com/adafruit/circuitpython)
+- [Espressif IDF](https://github.com/espressif/esp-idf)
- [MicroPython](https://github.com/micropython/micropython)
- [mynewt](https://mynewt.apache.org)
+- [Raspberry pico-sdk](https://github.com/raspberrypi/pico-sdk)
+- [TinyUF2 Bootloader](https://github.com/adafruit/tinyuf2)
- [TinyUSB Arduino Library](https://github.com/adafruit/Adafruit_TinyUSB_Arduino)
-
-Let me know if your project also uses TinyUSB and want to share.
diff --git a/docs/boards.md b/docs/boards.md
index e703d2490..ded1cca93 100644
--- a/docs/boards.md
+++ b/docs/boards.md
@@ -88,6 +88,10 @@ This code base already had supported for a handful of following boards (sorted a
- [NGX LPC4330-Xplorer](https://www.nxp.com/design/designs/lpc4330-xplorer-board:OM13027)
- [Double M33 Express](https://www.crowdsupply.com/steiert-solutions/double-m33-express)
+### Raspberry PI RP2040
+
+- [Raspberry PI PICO](https://www.raspberrypi.org/products/raspberry-pi-pico/)
+
### Sony
- [Sony Spresense CXD5602](https://developer.sony.com/develop/spresense)
diff --git a/examples/device/board_test/CMakeLists.txt b/examples/device/board_test/CMakeLists.txt
index c09ffe215..54a4009fe 100644
--- a/examples/device/board_test/CMakeLists.txt
+++ b/examples/device/board_test/CMakeLists.txt
@@ -1,15 +1,65 @@
-# The following five lines of boilerplate have to be in your project's
-# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
+# use directory name for project id
+get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+
# TOP is absolute path to root directory of TinyUSB git repo
set(TOP "../../..")
get_filename_component(TOP "${TOP}" REALPATH)
-# Add example src and bsp directories
-set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components")
+# Check for -DFAMILY=
+if(NOT DEFINED FAMILY)
+ message(FATAL_ERROR "Invalid FAMILY specified")
+endif()
+
+include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
+project(${PROJECT})
+
+if(FAMILY STREQUAL "rp2040")
+
+pico_sdk_init()
+
+add_executable(${PROJECT})
+
+# TinyUSB Stack source
+set(SRC_TINYUSB
+ ${TOP}/src/tusb.c
+ ${TOP}/src/common/tusb_fifo.c
+ ${TOP}/src/device/usbd.c
+ ${TOP}/src/device/usbd_control.c
+ ${TOP}/src/class/audio/audio_device.c
+ ${TOP}/src/class/cdc/cdc_device.c
+ ${TOP}/src/class/dfu/dfu_rt_device.c
+ ${TOP}/src/class/hid/hid_device.c
+ ${TOP}/src/class/midi/midi_device.c
+ ${TOP}/src/class/msc/msc_device.c
+ ${TOP}/src/class/net/net_device.c
+ ${TOP}/src/class/usbtmc/usbtmc_device.c
+ ${TOP}/src/class/vendor/vendor_device.c
+ ${TOP}/src/portable/raspberrypi/${FAMILY}/dcd_rp2040.c
+ ${TOP}/src/portable/raspberrypi/${FAMILY}/rp2040_usb.c
+)
+
+target_sources(${PROJECT} PUBLIC
+ src/main.c
+ ${TOP}/hw/bsp/${FAMILY}/family.c
+ ${SRC_TINYUSB}
+)
+
+target_include_directories(${PROJECT} PUBLIC
+ src/
+ ${TOP}/hw
+ ${TOP}/src
+ ${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}
+)
+
+target_compile_definitions(${PROJECT} PUBLIC
+ CFG_TUSB_MCU=OPT_MCU_RP2040
+ CFG_TUSB_OS=OPT_OS_PICO
+)
+
+target_link_libraries(${PROJECT} pico_stdlib)
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-set(SUPPORTED_TARGETS esp32s2)
+pico_add_extra_outputs(${PROJECT})
-project(board_test)
+endif()
diff --git a/examples/device/cdc_msc/CMakeLists.txt b/examples/device/cdc_msc/CMakeLists.txt
new file mode 100644
index 000000000..ada122b62
--- /dev/null
+++ b/examples/device/cdc_msc/CMakeLists.txt
@@ -0,0 +1,72 @@
+cmake_minimum_required(VERSION 3.5)
+
+# use directory name for project id
+get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+
+# TOP is absolute path to root directory of TinyUSB git repo
+set(TOP "../../..")
+get_filename_component(TOP "${TOP}" REALPATH)
+
+# Check for -DFAMILY=
+if(NOT DEFINED FAMILY)
+ message(FATAL_ERROR "Invalid FAMILY specified")
+endif()
+
+include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
+project(${PROJECT})
+
+if(FAMILY STREQUAL "rp2040")
+
+pico_sdk_init()
+
+add_executable(${PROJECT})
+
+# TinyUSB Stack source
+set(SRC_TINYUSB
+ ${TOP}/src/tusb.c
+ ${TOP}/src/common/tusb_fifo.c
+ ${TOP}/src/device/usbd.c
+ ${TOP}/src/device/usbd_control.c
+ ${TOP}/src/class/audio/audio_device.c
+ ${TOP}/src/class/cdc/cdc_device.c
+ ${TOP}/src/class/dfu/dfu_rt_device.c
+ ${TOP}/src/class/hid/hid_device.c
+ ${TOP}/src/class/midi/midi_device.c
+ ${TOP}/src/class/msc/msc_device.c
+ ${TOP}/src/class/net/net_device.c
+ ${TOP}/src/class/usbtmc/usbtmc_device.c
+ ${TOP}/src/class/vendor/vendor_device.c
+ ${TOP}/src/portable/raspberrypi/${FAMILY}/dcd_rp2040.c
+ ${TOP}/src/portable/raspberrypi/${FAMILY}/rp2040_usb.c
+)
+
+# Example source
+set(SRC_EXAMPLE
+ src/main.c
+ src/msc_disk.c
+ src/usb_descriptors.c
+)
+
+target_sources(${PROJECT} PUBLIC
+ ${SRC_EXAMPLE}
+ ${TOP}/hw/bsp/${FAMILY}/family.c
+ ${SRC_TINYUSB}
+)
+
+target_include_directories(${PROJECT} PUBLIC
+ src/
+ ${TOP}/hw
+ ${TOP}/src
+ ${TOP}/hw/bsp/${FAMILY}/boards/${BOARD}
+)
+
+target_compile_definitions(${PROJECT} PUBLIC
+ CFG_TUSB_MCU=OPT_MCU_RP2040
+ CFG_TUSB_OS=OPT_OS_PICO
+)
+
+target_link_libraries(${PROJECT} pico_stdlib)
+
+pico_add_extra_outputs(${PROJECT})
+
+endif()
diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h
index 1370e61c5..e0099785b 100644
--- a/examples/device/cdc_msc/src/tusb_config.h
+++ b/examples/device/cdc_msc/src/tusb_config.h
@@ -65,7 +65,9 @@
#endif
// This example doesn't use an RTOS
+#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
+#endif
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
// #define CFG_TUSB_DEBUG 0
diff --git a/examples/device/cdc_msc_freertos/CMakeLists.txt b/examples/device/cdc_msc_freertos/CMakeLists.txt
index 146b49cb0..2e55d8c47 100644
--- a/examples/device/cdc_msc_freertos/CMakeLists.txt
+++ b/examples/device/cdc_msc_freertos/CMakeLists.txt
@@ -1,15 +1,18 @@
-# The following five lines of boilerplate have to be in your project's
-# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
+# use directory name for project id
+get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+
# TOP is absolute path to root directory of TinyUSB git repo
set(TOP "../../..")
get_filename_component(TOP "${TOP}" REALPATH)
-# Add example src and bsp directories
-set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components")
+# Check for -DFAMILY=
+if(NOT DEFINED FAMILY)
+ message(FATAL_ERROR "Invalid FAMILY specified")
+endif()
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-set(SUPPORTED_TARGETS esp32s2)
+include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
+project(${PROJECT})
project(cdc_msc_freertos)
diff --git a/examples/device/hid_composite_freertos/CMakeLists.txt b/examples/device/hid_composite_freertos/CMakeLists.txt
index 3c48e4e70..c4777f122 100644
--- a/examples/device/hid_composite_freertos/CMakeLists.txt
+++ b/examples/device/hid_composite_freertos/CMakeLists.txt
@@ -1,15 +1,18 @@
-# The following five lines of boilerplate have to be in your project's
-# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
+# use directory name for project id
+get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+
# TOP is absolute path to root directory of TinyUSB git repo
set(TOP "../../..")
get_filename_component(TOP "${TOP}" REALPATH)
-# Add example src and bsp directories
-set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components")
+# Check for -DFAMILY=
+if(NOT DEFINED FAMILY)
+ message(FATAL_ERROR "Invalid FAMILY specified")
+endif()
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-set(SUPPORTED_TARGETS esp32s2)
+include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
+project(${PROJECT})
project(hid_composite_freertos)
diff --git a/examples/device/uac2_headset/.skip.MCU_SAMD11 b/examples/device/uac2_headset/.skip.MCU_SAMD11
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/examples/device/uac2_headset/.skip.MCU_SAMD11
diff --git a/examples/device/uac2_headset/.skip.MCU_SAME5X b/examples/device/uac2_headset/.skip.MCU_SAME5X
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/examples/device/uac2_headset/.skip.MCU_SAME5X
diff --git a/examples/device/uac2_headset/.skip.MCU_SAMG b/examples/device/uac2_headset/.skip.MCU_SAMG
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/examples/device/uac2_headset/.skip.MCU_SAMG
diff --git a/examples/make.mk b/examples/make.mk
index bf3b36a62..da0f60d2f 100644
--- a/examples/make.mk
+++ b/examples/make.mk
@@ -40,7 +40,7 @@ ifeq ($(FAMILY),)
include $(TOP)/hw/bsp/$(BOARD)/board.mk
else
# Include Family and Board specific defs
- include $(TOP)/$(FAMILY_PATH)/family.mk
+ -include $(TOP)/$(FAMILY_PATH)/family.mk
SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c))
endif
diff --git a/examples/rules.mk b/examples/rules.mk
index fb1fe76c2..ab0373bac 100644
--- a/examples/rules.mk
+++ b/examples/rules.mk
@@ -2,34 +2,46 @@
# Common make rules for all examples
# ---------------------------------------
-ifeq ($(CROSS_COMPILE),xtensa-esp32s2-elf-)
+ifeq ($(FAMILY),esp32s2)
# Espressif IDF use CMake build system, this add wrapper target to call idf.py
.PHONY: all clean flash
.DEFAULT_GOAL := all
all:
- idf.py -B$(BUILD) -DBOARD=$(BOARD) build
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) build
build: all
clean:
- idf.py -B$(BUILD) -DBOARD=$(BOARD) clean
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) clean
+
+fullclean:
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) fullclean
flash:
- idf.py -B$(BUILD) -DBOARD=$(BOARD) flash
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) flash
bootloader-flash:
- idf.py -B$(BUILD) -DBOARD=$(BOARD) bootloader-flash
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) bootloader-flash
app-flash:
- idf.py -B$(BUILD) -DBOARD=$(BOARD) app-flash
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) app-flash
erase:
- idf.py -B$(BUILD) -DBOARD=$(BOARD) erase_flash
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) erase_flash
monitor:
- idf.py -B$(BUILD) -DBOARD=$(BOARD) monitor
+ idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) monitor
+
+else ifeq ($(FAMILY),rp2040)
+
+all:
+ [ -d $(BUILD) ] || cmake -S . -B $(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) -DPICO_BUILD_DOCS=0
+ $(MAKE) -C $(BUILD)
+
+clean:
+ $(RM) -rf $(BUILD)
else
# GNU Make build system
diff --git a/hw/bsp/esp32s2/boards/esp32s2_kaluga_1/board.h b/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h
index 6bb44f76d..6bb44f76d 100644
--- a/hw/bsp/esp32s2/boards/esp32s2_kaluga_1/board.h
+++ b/hw/bsp/esp32s2/boards/espressif_kaluga_1/board.h
diff --git a/hw/bsp/esp32s2/boards/esp32s2_saola_1/board.h b/hw/bsp/esp32s2/boards/espressif_saola_1/board.h
index f450b9a8b..f450b9a8b 100644
--- a/hw/bsp/esp32s2/boards/esp32s2_saola_1/board.h
+++ b/hw/bsp/esp32s2/boards/espressif_saola_1/board.h
diff --git a/hw/bsp/esp32s2/family.cmake b/hw/bsp/esp32s2/family.cmake
new file mode 100644
index 000000000..c19221b14
--- /dev/null
+++ b/hw/bsp/esp32s2/family.cmake
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.5)
+
+# Add example src and bsp directories
+set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components")
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+set(SUPPORTED_TARGETS esp32s2)
diff --git a/hw/bsp/esp32s2/family.mk b/hw/bsp/esp32s2/family.mk
deleted file mode 100644
index 167ef6226..000000000
--- a/hw/bsp/esp32s2/family.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-# Cross Compiler for ESP32
-CROSS_COMPILE = xtensa-esp32s2-elf-
diff --git a/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c b/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c
deleted file mode 100644
index efdb54733..000000000
--- a/hw/bsp/raspberry_pi_pico/board_raspberry_pi_pico.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "pico/stdlib.h"
-#include "../board.h"
-
-#ifndef LED_PIN
-#define LED_PIN PICO_DEFAULT_LED_PIN
-#endif
-
-void board_init(void)
-{
- setup_default_uart();
- gpio_init(LED_PIN);
- gpio_set_dir(LED_PIN, 1);
-
- // Button
-
- // todo probably set up device mode?
-
-#if TUSB_OPT_HOST_ENABLED
- // set portfunc to host !!!
-#endif
-}
-
-////--------------------------------------------------------------------+
-//// USB Interrupt Handler
-////--------------------------------------------------------------------+
-//void USB_IRQHandler(void)
-//{
-//#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
-// tuh_isr(0);
-//#endif
-//
-//#if CFG_TUSB_RHPORT0_MODE & OPT_MODE_DEVICE
-// tud_int_handler(0);
-//#endif
-//}
-
-//--------------------------------------------------------------------+
-// Board porting API
-//--------------------------------------------------------------------+
-
-void board_led_write(bool state)
-{
- gpio_put(LED_PIN, state);
-}
-
-uint32_t board_button_read(void)
-{
- return 0;
-}
-
-int board_uart_read(uint8_t* buf, int len)
-{
- for(int i=0;i<len;i++) {
- buf[i] = uart_getc(uart_default);
- }
- return 0;
-}
-
-int board_uart_write(void const * buf, int len)
-{
-// UART_Send(BOARD_UART_PORT, &c, 1, BLOCKING);
- for(int i=0;i<len;i++) {
- uart_putc(uart_default, ((char *)buf)[i]);
- }
- return 0;
-}
-
-#if CFG_TUSB_OS == OPT_OS_NONE
-uint32_t board_millis(void)
-{
- return to_ms_since_boot(get_absolute_time());
-}
-#endif
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h
new file mode 100644
index 000000000..61532d8cb
--- /dev/null
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h
@@ -0,0 +1,46 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define LED_PIN PICO_DEFAULT_LED_PIN
+#define LED_STATE_ON 1
+
+// Button pin is BOOTSEL which is flash CS pin
+
+#define BUTTON_BOOTSEL
+#define BUTTON_STATE_ACTIVE 0
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */
diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c
new file mode 100644
index 000000000..e616acd19
--- /dev/null
+++ b/hw/bsp/rp2040/family.c
@@ -0,0 +1,137 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ * Copyright (c) 2021, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "pico/stdlib.h"
+#include "hardware/gpio.h"
+#include "hardware/sync.h"
+#include "hardware/structs/ioqspi.h"
+#include "hardware/structs/sio.h"
+
+#include "bsp/board.h"
+#include "board.h"
+
+#ifdef BUTTON_BOOTSEL
+// This example blinks the Picoboard LED when the BOOTSEL button is pressed.
+//
+// Picoboard has a button attached to the flash CS pin, which the bootrom
+// checks, and jumps straight to the USB bootcode if the button is pressed
+// (pulling flash CS low). We can check this pin in by jumping to some code in
+// SRAM (so that the XIP interface is not required), floating the flash CS
+// pin, and observing whether it is pulled low.
+//
+// This doesn't work if others are trying to access flash at the same time,
+// e.g. XIP streamer, or the other core.
+bool __no_inline_not_in_flash_func(get_bootsel_button)() {
+ const uint CS_PIN_INDEX = 1;
+
+ // Must disable interrupts, as interrupt handlers may be in flash, and we
+ // are about to temporarily disable flash access!
+ uint32_t flags = save_and_disable_interrupts();
+
+ // Set chip select to Hi-Z
+ hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
+ GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
+ IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
+
+ // Note we can't call into any sleep functions in flash right now
+ for (volatile int i = 0; i < 1000; ++i);
+
+ // The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
+ // Note the button pulls the pin *low* when pressed.
+ bool button_state = (sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX));
+
+ // Need to restore the state of chip select, else we are going to have a
+ // bad time when we return to code in flash!
+ hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
+ GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
+ IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
+
+ restore_interrupts(flags);
+
+ return button_state;
+}
+#endif
+
+void board_init(void)
+{
+ setup_default_uart();
+ gpio_init(LED_PIN);
+ gpio_set_dir(LED_PIN, GPIO_OUT);
+
+ // Button
+#ifndef BUTTON_BOOTSEL
+#endif
+
+ // todo probably set up device mode?
+#if TUSB_OPT_DEVICE_ENABLED
+
+#endif
+
+#if TUSB_OPT_HOST_ENABLED
+ // set portfunc to host !!!
+#endif
+}
+
+//--------------------------------------------------------------------+
+// Board porting API
+//--------------------------------------------------------------------+
+
+void board_led_write(bool state)
+{
+ gpio_put(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
+}
+
+uint32_t board_button_read(void)
+{
+#ifdef BUTTON_BOOTSEL
+ return BUTTON_STATE_ACTIVE == get_bootsel_button();
+#else
+ return 0;
+#endif
+}
+
+int board_uart_read(uint8_t* buf, int len)
+{
+ for(int i=0;i<len;i++) {
+ buf[i] = uart_getc(uart_default);
+ }
+ return 0;
+}
+
+int board_uart_write(void const * buf, int len)
+{
+ for(int i=0;i<len;i++) {
+ uart_putc(uart_default, ((char *)buf)[i]);
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------+
+// USB Interrupt Handler
+// rp2040 implementation will install approriate handler when initializing
+// tinyusb. There is no need to forward IRQ from application
+//--------------------------------------------------------------------+
diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake
new file mode 100644
index 000000000..8a3882cc0
--- /dev/null
+++ b/hw/bsp/rp2040/family.cmake
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.12)
+set(PICO_SDK_PATH ${TOP}/hw/mcu/raspberrypi/pico-sdk)
+include(${PICO_SDK_PATH}/pico_sdk_init.cmake)
diff --git a/hw/bsp/rp2040/family_extra.cmake b/hw/bsp/rp2040/family_extra.cmake
new file mode 100644
index 000000000..661845844
--- /dev/null
+++ b/hw/bsp/rp2040/family_extra.cmake
@@ -0,0 +1 @@
+pico_sdk_init()
diff --git a/hw/mcu/raspberrypi/pico-sdk b/hw/mcu/raspberrypi/pico-sdk
new file mode 160000
+Subproject ef38b746efaeb0aa1354406198a76da29302aad
diff --git a/src/host/usbh.c b/src/host/usbh.c
index bf265199d..10ae991f4 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -154,7 +154,7 @@ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr)
tusb_speed_t tuh_device_get_speed (uint8_t const dev_addr)
{
TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG);
- return _usbh_devices[dev_addr].speed;
+ return (tusb_speed_t) _usbh_devices[dev_addr].speed;
}
void osal_task_delay(uint32_t msec)
diff --git a/tools/build_all.py b/tools/build_board.py
index 787011e26..cf3a8fb94 100644
--- a/tools/build_all.py
+++ b/tools/build_board.py
@@ -18,48 +18,60 @@ total_time = time.monotonic()
build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |'
build_separator = '-' * 106
+def filter_with_input(mylist):
+ if len(sys.argv) > 1:
+ input_args = list(set(mylist).intersection(sys.argv))
+ if len(input_args) > 0:
+ mylist[:] = input_args
+
# If examples are not specified in arguments, build all
all_examples = []
-
for entry in os.scandir("examples/device"):
if entry.is_dir():
all_examples.append("device/" + entry.name)
-
for entry in os.scandir("examples/host"):
if entry.is_dir():
all_examples.append("host/" + entry.name)
-
-if len(sys.argv) > 1:
- input_examples = list(set(all_examples).intersection(sys.argv))
- if len(input_examples) > 0:
- all_examples = input_examples
-
+filter_with_input(all_examples)
all_examples.sort()
# If boards are not specified in arguments, build all
all_boards = []
-
for entry in os.scandir("hw/bsp"):
- if entry.is_dir() and entry.name != "esp32s2":
- if os.path.isdir(entry.path + "/boards"):
- # family directory
- for subentry in os.scandir(entry.path + "/boards"):
- if subentry.is_dir(): all_boards.append(subentry.name)
- else:
- all_boards.append(entry.name)
+ if entry.is_dir() and os.path.exists(entry.path + "/board.mk"):
+ all_boards.append(entry.name)
+filter_with_input(all_boards)
+all_boards.sort()
-if len(sys.argv) > 1:
- input_boards = list(set(all_boards).intersection(sys.argv))
- if len(input_boards) > 0:
- all_boards = input_boards
+def build_board(example, board):
+ global success_count, fail_count, skip_count
+ start_time = time.monotonic()
+ flash_size = "-"
+ sram_size = "-"
-all_boards.sort()
+ # Check if board is skipped
+ if skip_example(example, board):
+ success = SKIPPED
+ skip_count += 1
+ print(build_format.format(example, board, success, '-', flash_size, sram_size))
+ else:
+ subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+ if build_result.returncode == 0:
+ success = SUCCEEDED
+ success_count += 1
+ (flash_size, sram_size) = build_size(example, board)
+ else:
+ exit_status = build_result.returncode
+ success = FAILED
+ fail_count += 1
-def build_example(example, board):
- subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- return subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ build_duration = time.monotonic() - start_time
+ print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
+
+ if build_result.returncode != 0:
+ print(build_result.stdout.decode("utf-8"))
def build_size(example, board):
#elf_file = 'examples/device/{}/_build/build-{}/{}-firmware.elf'.format(example, board, board)
@@ -72,11 +84,7 @@ def build_size(example, board):
def skip_example(example, board):
ex_dir = 'examples/' + example
-
board_mk = 'hw/bsp/{}/board.mk'.format(board)
- if not os.path.exists(board_mk):
- board_mk = list(glob.iglob('hw/bsp/*/boards/{}/../../family.mk'.format(board)))[0]
-
with open(board_mk) as mk:
mk_contents = mk.read()
@@ -107,35 +115,7 @@ print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', '
for example in all_examples:
print(build_separator)
for board in all_boards:
- start_time = time.monotonic()
-
- flash_size = "-"
- sram_size = "-"
-
- # Check if board is skipped
- if skip_example(example, board):
- success = SKIPPED
- skip_count += 1
- print(build_format.format(example, board, success, '-', flash_size, sram_size))
- else:
- build_result = build_example(example, board)
-
- if build_result.returncode == 0:
- success = SUCCEEDED
- success_count += 1
- (flash_size, sram_size) = build_size(example, board)
- else:
- exit_status = build_result.returncode
- success = FAILED
- fail_count += 1
-
- build_duration = time.monotonic() - start_time
- print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
-
- if build_result.returncode != 0:
- print(build_result.stdout.decode("utf-8"))
-
-
+ build_board(example, board)
total_time = time.monotonic() - total_time
print(build_separator)
diff --git a/tools/build_esp32s.py b/tools/build_esp32s.py
deleted file mode 100644
index c63bbf6d2..000000000
--- a/tools/build_esp32s.py
+++ /dev/null
@@ -1,102 +0,0 @@
-import os
-import glob
-import sys
-import subprocess
-import time
-
-SUCCEEDED = "\033[32msucceeded\033[0m"
-FAILED = "\033[31mfailed\033[0m"
-SKIPPED = "\033[33mskipped\033[0m"
-
-success_count = 0
-fail_count = 0
-skip_count = 0
-exit_status = 0
-
-total_time = time.monotonic()
-
-build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |'
-build_separator = '-' * 100
-
-# 1st Argument is Example, build all examples if not existed
-all_examples = []
-if len(sys.argv) > 1:
- all_examples.append(sys.argv[1])
-else:
- for entry in os.scandir("examples/device"):
- # Only includes example with CMakeLists.txt for esp32s
- if entry.is_dir() and os.path.exists(entry.path + "/CMakeLists.txt"):
- all_examples.append(entry.name)
-all_examples.sort()
-
-# 2nd Argument is Board, build all boards if not existed
-all_boards = []
-if len(sys.argv) > 2:
- all_boards.append(sys.argv[2])
-else:
- for entry in os.scandir("hw/bsp/esp32s2/boards"):
- if entry.is_dir():
- all_boards.append(entry.name)
-
-all_boards.sort()
-
-def build_example(example, board):
- subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- return subprocess.run("make -C examples/device/{} BOARD={} all".format(example, board), shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-
-def build_size(example, board):
- #elf_file = 'examples/device/{}/_build/build-{}/{}-firmware.elf'.format(example, board, board)
- elf_file = 'examples/device/{}/_build/build-{}/*.elf'.format(example, board)
- size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8")
- size_list = size_output.split('\n')[1].split('\t')
- flash_size = int(size_list[0])
- sram_size = int(size_list[1]) + int(size_list[2])
- return (flash_size, sram_size)
-
-def skip_example(example, board):
- return 0
-
-print(build_separator)
-print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM'))
-print(build_separator)
-
-for example in all_examples:
- for board in all_boards:
- start_time = time.monotonic()
-
- flash_size = "-"
- sram_size = "-"
-
- # Check if board is skipped
- if skip_example(example, board):
- success = SKIPPED
- skip_count += 1
- print(build_format.format(example, board, success, '-', flash_size, sram_size))
- else:
- build_result = build_example(example, board)
-
- if build_result.returncode == 0:
- success = SUCCEEDED
- success_count += 1
- (flash_size, sram_size) = build_size(example, board)
- else:
- exit_status = build_result.returncode
- success = FAILED
- fail_count += 1
-
- build_duration = time.monotonic() - start_time
- print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
-
- if build_result.returncode != 0:
- print(build_result.stdout.decode("utf-8"))
-
-
-
-total_time = time.monotonic() - total_time
-print(build_separator)
-print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time))
-print(build_separator)
-
-sys.exit(exit_status)
diff --git a/tools/build_esp32s2.py b/tools/build_esp32s2.py
new file mode 100644
index 000000000..cff0cc33b
--- /dev/null
+++ b/tools/build_esp32s2.py
@@ -0,0 +1,99 @@
+import os
+import glob
+import sys
+import subprocess
+import time
+
+SUCCEEDED = "\033[32msucceeded\033[0m"
+FAILED = "\033[31mfailed\033[0m"
+SKIPPED = "\033[33mskipped\033[0m"
+
+success_count = 0
+fail_count = 0
+skip_count = 0
+exit_status = 0
+
+total_time = time.monotonic()
+
+build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |'
+build_separator = '-' * 100
+
+def filter_with_input(mylist):
+ if len(sys.argv) > 1:
+ input_args = list(set(mylist).intersection(sys.argv))
+ if len(input_args) > 0:
+ mylist[:] = input_args
+
+# Build all examples if not specified
+all_examples = []
+for entry in os.scandir("examples/device"):
+ # Only includes example with CMakeLists.txt for esp32s
+ if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults"):
+ all_examples.append(entry.name)
+filter_with_input(all_examples)
+all_examples.sort()
+
+# Build all boards if not specified
+all_boards = []
+for entry in os.scandir("hw/bsp/esp32s2/boards"):
+ if entry.is_dir():
+ all_boards.append(entry.name)
+filter_with_input(all_boards)
+all_boards.sort()
+
+def build_board(example, board):
+ global success_count, fail_count, skip_count
+ start_time = time.monotonic()
+ flash_size = "-"
+ sram_size = "-"
+
+ # Check if board is skipped
+ if skip_example(example, board):
+ success = SKIPPED
+ skip_count += 1
+ print(build_format.format(example, board, success, '-', flash_size, sram_size))
+ else:
+ subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+ if build_result.returncode == 0:
+ success = SUCCEEDED
+ success_count += 1
+ (flash_size, sram_size) = build_size(example, board)
+ else:
+ exit_status = build_result.returncode
+ success = FAILED
+ fail_count += 1
+
+ build_duration = time.monotonic() - start_time
+ print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
+
+ if build_result.returncode != 0:
+ print(build_result.stdout.decode("utf-8"))
+
+def build_size(example, board):
+ #elf_file = 'examples/device/{}/_build/build-{}/{}-firmware.elf'.format(example, board, board)
+ elf_file = 'examples/device/{}/_build/build-{}/*.elf'.format(example, board)
+ size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8")
+ size_list = size_output.split('\n')[1].split('\t')
+ flash_size = int(size_list[0])
+ sram_size = int(size_list[1]) + int(size_list[2])
+ return (flash_size, sram_size)
+
+def skip_example(example, board):
+ return 0
+
+print(build_separator)
+print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM'))
+print(build_separator)
+
+for example in all_examples:
+ for board in all_boards:
+ build_board(example, board)
+
+total_time = time.monotonic() - total_time
+print(build_separator)
+print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time))
+print(build_separator)
+
+sys.exit(exit_status)
diff --git a/tools/build_family.py b/tools/build_family.py
new file mode 100644
index 000000000..7f2c1a706
--- /dev/null
+++ b/tools/build_family.py
@@ -0,0 +1,136 @@
+import os
+import glob
+import sys
+import subprocess
+import time
+
+SUCCEEDED = "\033[32msucceeded\033[0m"
+FAILED = "\033[31mfailed\033[0m"
+SKIPPED = "\033[33mskipped\033[0m"
+
+success_count = 0
+fail_count = 0
+skip_count = 0
+exit_status = 0
+
+total_time = time.monotonic()
+
+build_format = '| {:29} | {:30} | {:18} | {:7} | {:6} | {:6} |'
+build_separator = '-' * 106
+
+def filter_with_input(mylist):
+ if len(sys.argv) > 1:
+ input_args = list(set(mylist).intersection(sys.argv))
+ if len(input_args) > 0:
+ mylist[:] = input_args
+
+# If examples are not specified in arguments, build all
+all_examples = []
+for entry in os.scandir("examples/device"):
+ if entry.is_dir():
+ all_examples.append("device/" + entry.name)
+for entry in os.scandir("examples/host"):
+ if entry.is_dir():
+ all_examples.append("host/" + entry.name)
+filter_with_input(all_examples)
+all_examples.sort()
+
+# If family are not specified in arguments, build all
+all_families = []
+for entry in os.scandir("hw/bsp"):
+ if entry.is_dir() and os.path.isdir(entry.path + "/boards") and entry.name != "esp32s2":
+ all_families.append(entry.name)
+
+filter_with_input(all_families)
+all_families.sort()
+
+def build_family(example, family):
+ all_boards = []
+ for entry in os.scandir("hw/bsp/{}/boards".format(family)):
+ if entry.is_dir():
+ all_boards.append(entry.name)
+ all_boards.sort()
+
+ for board in all_boards:
+ build_board(example, board)
+
+def build_board(example, board):
+ global success_count, fail_count, skip_count
+ start_time = time.monotonic()
+ flash_size = "-"
+ sram_size = "-"
+
+ # Check if board is skipped
+ if skip_example(example, board):
+ success = SKIPPED
+ skip_count += 1
+ print(build_format.format(example, board, success, '-', flash_size, sram_size))
+ else:
+ subprocess.run("make -C examples/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ build_result = subprocess.run("make -j -C examples/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+ if build_result.returncode == 0:
+ success = SUCCEEDED
+ success_count += 1
+ (flash_size, sram_size) = build_size(example, board)
+ else:
+ exit_status = build_result.returncode
+ success = FAILED
+ fail_count += 1
+
+ build_duration = time.monotonic() - start_time
+ print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size))
+
+ if build_result.returncode != 0:
+ print(build_result.stdout.decode("utf-8"))
+
+def build_size(example, board):
+ #elf_file = 'examples/device/{}/_build/build-{}/{}-firmware.elf'.format(example, board, board)
+ elf_file = 'examples/{}/_build/build-{}/*.elf'.format(example, board)
+ size_output = subprocess.run('size {}'.format(elf_file), shell=True, stdout=subprocess.PIPE).stdout.decode("utf-8")
+ size_list = size_output.split('\n')[1].split('\t')
+ flash_size = int(size_list[0])
+ sram_size = int(size_list[1]) + int(size_list[2])
+ return (flash_size, sram_size)
+
+def skip_example(example, board):
+ ex_dir = 'examples/' + example
+ board_mk = 'hw/bsp/{}/family.mk'.format(family)
+
+ with open(board_mk) as mk:
+ mk_contents = mk.read()
+
+ # Skip all OPT_MCU_NONE these are WIP port
+ if '-DCFG_TUSB_MCU=OPT_MCU_NONE' in mk_contents:
+ return 1
+
+ # Skip if CFG_TUSB_MCU in board.mk to match skip file
+ for skip_file in glob.iglob(ex_dir + '/.skip.MCU_*'):
+ mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(skip_file).split('.')[2]
+ if mcu_cflag in mk_contents:
+ return 1
+
+ # Build only list, if exists only these MCU are built
+ only_list = list(glob.iglob(ex_dir + '/.only.MCU_*'))
+ if len(only_list) > 0:
+ for only_file in only_list:
+ mcu_cflag = '-DCFG_TUSB_MCU=OPT_' + os.path.basename(only_file).split('.')[2]
+ if mcu_cflag in mk_contents:
+ return 0
+ return 1
+ return 0
+
+print(build_separator)
+print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM'))
+
+for example in all_examples:
+ print(build_separator)
+ for family in all_families:
+ build_family(example, family)
+
+total_time = time.monotonic() - total_time
+print(build_separator)
+print("Build Summary: {} {}, {} {}, {} {} and took {:.2f}s".format(success_count, SUCCEEDED, fail_count, FAILED, skip_count, SKIPPED, total_time))
+print(build_separator)
+
+sys.exit(exit_status)