Skip to content

Commit

Permalink
Merge pull request #30 from espressif/feature/idf_component_files
Browse files Browse the repository at this point in the history
feat(tinyusb): Added initial files to make an idf component
  • Loading branch information
roma-jam authored Oct 30, 2024
2 parents 933ac29 + aadb750 commit 4b4c984
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 0 deletions.
64 changes: 64 additions & 0 deletions .github/ci/override_managed_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env python
#
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

import sys
import argparse
from pathlib import Path
from glob import glob
from idf_component_tools.manifest import ManifestManager


def override_with_local_component(component, local_path, app):
app_path = Path(app)

absolute_local_path = Path(local_path).absolute()
if not absolute_local_path.exists():
print('[Error] {} path does not exist'.format(local_path))
raise Exception
if not app_path.exists():
print('[Error] {} path does not exist'.format(app_path))
raise Exception

print('[Info] Processing app {}'.format(app))
manager = ManifestManager(app_path / 'main', 'app')
if '/' not in component:
# Prepend with default namespace
component_with_namespace = 'espressif/' + component

try:
manager.manifest_tree['dependencies'][component_with_namespace] = {
'version': '*',
'override_path': str(absolute_local_path)
}
except KeyError:
print('[Error] {} app does not depend on {}'.format(app, component_with_namespace))
raise KeyError

manager.dump()


def override_with_local_component_all(component, local_path, apps):
# Process wildcard, e.g. "app_prefix_*"
apps_with_glob = list()
for app in apps:
apps_with_glob += glob(app)

# Go through all collected apps
for app in apps_with_glob:
try:
override_with_local_component(component, local_path, app)
except:
print("[Error] Could not process app {}".format(app))
return -1
return 0


if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('component', help='Existing component that the app depends on')
parser.add_argument('local_path', help='Path to component that will be used instead of the managed version')
parser.add_argument('apps', nargs='*', help='List of apps to process')
args = parser.parse_args()
sys.exit(override_with_local_component_all(args.component, args.local_path, args.apps))
28 changes: 28 additions & 0 deletions .github/workflows/build_idf_examples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Build ESP-IDF USB examples

on:
schedule:
- cron: '0 0 * * SAT' # Saturday midnight
pull_request:
types: [opened, reopened, synchronize]

jobs:
build:
strategy:
matrix:
idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "release-v5.4", "latest"]
runs-on: ubuntu-20.04
container: espressif/idf:${{ matrix.idf_ver }}
steps:
- uses: actions/checkout@v4
with:
submodules: 'true'
- name: Build ESP-IDF USB Device examples
shell: bash
run: |
. ${IDF_PATH}/export.sh
pip install idf-component-manager==1.5.2 idf-build-apps --upgrade
python .github/ci/override_managed_component.py tinyusb . ${IDF_PATH}/examples/peripherals/usb/device/tusb_*
cd ${IDF_PATH}
idf-build-apps find --path examples/peripherals/usb/device/ --recursive --target all --manifest-file examples/peripherals/.build-test-rules.yml
idf-build-apps build --path examples/peripherals/usb/device/ --recursive --target all --manifest-file examples/peripherals/.build-test-rules.yml
25 changes: 25 additions & 0 deletions .github/workflows/upload_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Push TinyUSB to Espressif Component Service

# If the commit is tagged, it will be uploaded. Other scenario silently fail.
on:
push:
tags:
- v*

jobs:
upload_components:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Remove unneeded files
shell: bash
run: rm -rf docs tools lib/embedded-cli lib/fatfs lib/SEGGER_RTT

- name: Upload components to component service
uses: espressif/upload-components-ci-action@v1
with:
name: "tinyusb"
version: ${{ github.ref_name }}
namespace: "espressif"
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
65 changes: 65 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
idf_build_get_property(target IDF_TARGET)

if(target STREQUAL "esp32s3")
set(tusb_mcu "OPT_MCU_ESP32S3")
set(tusb_family "esp32sx")
elseif(target STREQUAL "esp32s2")
set(tusb_mcu "OPT_MCU_ESP32S2")
set(tusb_family "esp32sx")
elseif(target STREQUAL "esp32p4")
set(tusb_mcu "OPT_MCU_ESP32P4")
set(tusb_family "esp32px")
endif()

set(compile_options
"-DCFG_TUSB_MCU=${tusb_mcu}"
)

idf_component_get_property(freertos_include freertos ORIG_INCLUDE_PATH)

set(includes_private
"src/"
"src/device"
"lib/networking" # For RNDIS definitions
)

set(includes_public
"src/"
# The FreeRTOS API include convention in tinyusb is different from esp-idf
"${freertos_include}"
)

set(srcs
"src/class/cdc/cdc_device.c"
"src/class/hid/hid_device.c"
"src/class/midi/midi_device.c"
"src/class/msc/msc_device.c"
"src/class/vendor/vendor_device.c"
"src/class/audio/audio_device.c"
"src/class/video/video_device.c"
"src/class/bth/bth_device.c"
# NET class
"src/class/net/ecm_rndis_device.c"
"lib/networking/rndis_reports.c"
"src/class/net/ncm_device.c"
# DFU
"src/class/dfu/dfu_device.c"
"src/class/dfu/dfu_rt_device.c"
# Common, device-mode related
"src/portable/synopsys/dwc2/dcd_dwc2.c"
"src/common/tusb_fifo.c"
"src/device/usbd_control.c"
"src/device/usbd.c"
"src/tusb.c"
)

idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes_public}
PRIV_INCLUDE_DIRS ${includes_private}
PRIV_REQUIRES esp_netif # required by rndis_reports.c: #include "netif/ethernet.h"
)

target_compile_options(${COMPONENT_LIB} PUBLIC ${compile_options})

# when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false
set_source_files_properties("src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits")
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Espressif TinyUSB component

Upstream [TinyUSB](https://github.com/hathach/tinyusb) fork with integration into ESP-IDF build system.

## How to use

There are two options of using TinyUSB component with Espressif's SoCs:

### 1. Use component via [Espressif TinyUSB additions](https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb)

[Espressif TinyUSB additions](https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb) provides several preconfigured features to use benefits of TinyUSB stack faster.

To use [Espressif TinyUSB additions](https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb), add ``idf_component.yml`` to your main component with the following content::

```yaml
## IDF Component Manager Manifest File
dependencies:
esp_tinyusb: "^1.0.0" # Automatically update minor releases
```
Or simply run:
```
idf.py add-dependency "esp_tinyusb^1.0.0"
```

Then, the Espressif TinyUSB component will be added automatically during resolving dependencies by the component manager.

### 2. Use component directly

Use this option for custom TinyUSB applications.
In this case you will have to provide configuration header file ``tusb_config.h``. More information about TinyUSB configuration can be found [in official TinyUSB documentation](https://docs.tinyusb.org/en/latest/reference/getting_started.html).

You will also have to tell TinyUSB where to find the configuration file. This can be achieved by adding following CMake snippet to you main component's ``CMakeLists.txt``:

```cmake
idf_component_get_property(tusb_lib espressif__tinyusb COMPONENT_LIB)
target_include_directories(${tusb_lib} PRIVATE path_to_your_tusb_config)
```

Again, you can add this component to your project by adding ``idf_component.yml`` file:

```yaml
## IDF Component Manager Manifest File
dependencies:
tinyusb: "~0.15.1" # Automatically update bugfix releases. TinyUSB does not guarantee backward compatibility
```
Or simply run:
```
idf.py add-dependency "tinyusb~0.15.1"
```

README from the upstream TinyUSB can be found in [hathach/tinyusb/README](https://github.com/hathach/tinyusb/blob/master/README.rst).
10 changes: 10 additions & 0 deletions idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
description: TinyUSB ported to Espressif's SoCs
url: https://docs.tinyusb.org/en/latest/
documentation: "https://docs.tinyusb.org/en/latest/"
repository: "https://github.com/espressif/tinyusb.git"
dependencies:
idf: '>=5.0' # IDF 4.x contains TinyUSB as submodule
targets:
- esp32s2
- esp32s3
- esp32p4
2 changes: 2 additions & 0 deletions sbom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
originator: 'Person: Ha Thach <[email protected]>'

0 comments on commit 4b4c984

Please sign in to comment.