diff options
| author | Zixun LI <[email protected]> | 2025-11-25 10:59:43 +0100 |
|---|---|---|
| committer | Zixun LI <[email protected]> | 2025-11-25 10:59:43 +0100 |
| commit | dc083e4d9c87658498a3bd0b527d25bc88dd1ed6 (patch) | |
| tree | 0523e934e5a1b1fe8331b28990ddf2e2f4478077 | |
| parent | e59b2c40fc9e655918629d73cc8c54b86b4a70c1 (diff) | |
| parent | fee2d2a034d65aa625bc1a8b32c3b7a51292a39f (diff) | |
Merge remote-tracking branch 'tinyusb/master' into n6_build
Signed-off-by: Zixun LI <[email protected]>
721 files changed, 26275 insertions, 13206 deletions
diff --git a/.PVS-Studio/.pvsconfig b/.PVS-Studio/.pvsconfig new file mode 100644 index 000000000..c098fc375 --- /dev/null +++ b/.PVS-Studio/.pvsconfig @@ -0,0 +1,19 @@ +//V_EXCLUDE_PATH */iar/cxarm* +//V_EXCLUDE_PATH */pico-sdk/* +//V_EXCLUDE_PATH */esp-idf/* +//V_EXCLUDE_PATH */hw/mcu/* +//V_EXCLUDE_PATH */hw/bsp/espressif/components/* +//V_EXCLUDE_PATH */lib/* + +//-V::2506 MISRA. A function should have a single point of exit at the end. +//-V::2514 MISRA. Unions should not be used. +//-V::2520 [MISRA-C-16.3] Every switch-clause should be terminated by an unconditional 'break' statement +//-V:memcpy:2547 [MISRA-C-17.7] The return value of non-void function 'memcpy' should be used. +//-V:memmove:2547 [MISRA-C-17.7] The return value of non-void function 'memmove' should be used. +//-V:printf:2547 [MISRA-C-17.7] +//-V::2584::{gintsts} dwc2 interrupt handler +//-V::2584::{hcint} dwc2 interrupt handler +//-V::2600 [MISRA-C-21.6] The function with the 'printf' name should not be used. +//+V2614 DISABLE_LENGHT_LIMIT_CHECK:YES +//-V:memcpy:2628 Pointer arguments to the 'memcpy' function should be pointers to qualified or unqualified versions of compatible types. +//-V::2659 [MISRA-C-16.1] Switch statements should be well-formed. Every switch-clause should be terminated by an unconditional 'break' statement diff --git a/.circleci/config.yml b/.circleci/config.yml index 3342cbc65..580f5fe2e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,8 +32,6 @@ jobs: BUILDSYSTEM_TOOLCHAIN+=("cmake arm-iar") fi - RESOURCE_LARGE='["nrf", "imxrt", "stm32f4", "stm32h7 stm32h7rs"]' - gen_build_entry() { local build_system="$1" local toolchain="$2" @@ -61,21 +59,7 @@ jobs: FAMILY=$(echo $MATRIX_JSON | jq -r ".\"$toolchain\"") echo "FAMILY_${toolchain}=$FAMILY" - # FAMILY_LARGE = FAMILY - RESOURCE_LARGE - # Separate large from medium+ resources - FAMILY_LARGE=$(jq -n --argjson family "$FAMILY" --argjson resource "$RESOURCE_LARGE" '$family | map(select(IN($resource[])))') - FAMILY=$(jq -n --argjson family "$FAMILY" --argjson resource "$RESOURCE_LARGE" '$family | map(select(IN($resource[]) | not))') - - if [[ $toolchain == esp-idf || $toolchain == arm-iar ]]; then - gen_build_entry "$build_system" "$toolchain" "$FAMILY" "large" - else - gen_build_entry "$build_system" "$toolchain" "$FAMILY" "medium+" - - # add large resources if available - if [ "$(echo $FAMILY_LARGE | jq 'length')" -gt 0 ]; then - gen_build_entry "$build_system" "$toolchain" "$FAMILY_LARGE" "large" - fi - fi + gen_build_entry "$build_system" "$toolchain" "$FAMILY" "large" done - continuation/continue: diff --git a/.circleci/config2.yml b/.circleci/config2.yml index d86a3f662..ab0fd7ba1 100644 --- a/.circleci/config2.yml +++ b/.circleci/config2.yml @@ -34,6 +34,7 @@ commands: chmod +x toolchain.run ./toolchain.run -p ~/cache/<< parameters.toolchain >>/gnurx -y elif [[ << parameters.toolchain >> == arm-iar ]]; then + wget --progress=dot:giga https://netstorage.iar.com/FileStore/STANDARD/001/003/926/iar-lmsc-tools_1.8_amd64.deb -O ~/cache/<< parameters.toolchain >>/iar-lmsc-tools.deb wget --progress=dot:giga $toolchain_url -O ~/cache/<< parameters.toolchain >>/toolchain.deb else wget --progress=dot:giga $toolchain_url -O toolchain.tar.gz @@ -44,6 +45,7 @@ commands: # Add toolchain to PATH if [[ << parameters.toolchain >> == arm-iar ]]; then # Install IAR since we only cache deb file + sudo dpkg -i ~/cache/<< parameters.toolchain >>/iar-lmsc-tools.deb sudo dpkg --ignore-depends=libusb-1.0-0 -i ~/cache/<< parameters.toolchain >>/toolchain.deb echo "export PATH=$PATH:/opt/iar/cxarm/arm/bin" >> $BASH_ENV else @@ -102,6 +104,7 @@ commands: - run: name: Build + no_output_timeout: 20m command: | if [ << parameters.toolchain >> == esp-idf ]; then docker run --rm -v $PWD:/project -w /project espressif/idf:v5.3.2 python tools/build.py << parameters.family >> @@ -125,7 +128,7 @@ jobs: parameters: resource_class: type: string - default: medium+ + default: large build-system: type: string toolchain: diff --git a/.clang-format b/.clang-format index 0fd168e5a..f15c26c9e 100644 --- a/.clang-format +++ b/.clang-format @@ -1,66 +1,99 @@ -# Generated from CLion C/C++ Code Style settings +--- +Language: Cpp BasedOnStyle: LLVM -AccessModifierOffset: -2 AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: None -AlignOperands: Align +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true + AlignCaseColons: false +AlignEscapedNewlines: LeftWithLastLine +AlignOperands: true +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 AllowAllArgumentsOnNextLine: false AllowAllConstructorInitializersOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Always +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseExpressionOnASingleLine: true AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Always -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterReturnType: None +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true BreakBeforeBraces: Custom BraceWrapping: AfterCaseLabel: false AfterClass: false - AfterControlStatement: Never + AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false + AfterStruct: false AfterUnion: false - BeforeCatch: false + AfterExternBlock: false + BeforeCatch: true BeforeElse: false - IndentBraces: false - SplitEmptyFunction: false + BeforeLambdaBody: false + BeforeWhile: false + SplitEmptyFunction: true SplitEmptyRecord: true + SplitEmptyNamespace: true +BracedInitializerIndentWidth: 2 BreakBeforeBinaryOperators: None -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakInheritanceList: BeforeColon -ColumnLimit: 0 -CompactNamespaces: false -ContinuationIndentWidth: 4 -IndentCaseLabels: true +BreakConstructorInitializers: AfterColon +BreakConstructorInitializersBeforeComma: false +ContinuationIndentWidth: 2 +ColumnLimit: 120 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +Cpp11BracedListStyle: true +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^<.*' + Priority: 1 + - Regex: '^".*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' IndentPPDirectives: BeforeHash -IndentWidth: 2 -KeepEmptyLinesAtTheStartOfBlocks: true +InsertBraces: true +IndentCaseLabels: true +InsertNewlineAtEOF: true +MacroBlockBegin: '' +MacroBlockEnd: '' MaxEmptyLinesToKeep: 2 NamespaceIndentation: All -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PointerAlignment: Right +PenaltyBreakBeforeFirstCallParameter: 1000000 +PenaltyBreakOpenParenthesis: 1000000 +QualifierAlignment: Custom +QualifierOrder: ['static', 'const', 'volatile', 'restrict', 'type'] ReflowComments: false -SpaceAfterCStyleCast: true -SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: false SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 0 SpacesInAngles: false +SpacesInConditionalStatement: false SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: true SpacesInParentheses: false -SpacesInSquareBrackets: false +SortIncludes: false TabWidth: 2 -UseTab: Never +... diff --git a/.github/actions/get_deps/action.yml b/.github/actions/get_deps/action.yml index ae9e7bbef..a84db893b 100644 --- a/.github/actions/get_deps/action.yml +++ b/.github/actions/get_deps/action.yml @@ -19,11 +19,16 @@ runs: - name: Linux dependencies if: runner.os == 'Linux' run: | - sudo apt install -y ninja-build + NINJA_URL=https://github.com/ninja-build/ninja/releases/download/v1.13.1/ninja-linux.zip + wget $NINJA_URL -O ninja-linux.zip + unzip ninja-linux.zip -d ninja-bin + echo >> $GITHUB_PATH "${{ github.workspace }}/ninja-bin" shell: bash - name: Get Dependencies + env: + ARG: ${{ inputs.arg }} run: | - python3 tools/get_deps.py ${{ inputs.arg }} + python3 tools/get_deps.py ${ARG} echo "PICO_SDK_PATH=${{ github.workspace }}/pico-sdk" >> $GITHUB_ENV shell: bash diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index 6fd5c9d4e..d15a29f20 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -30,8 +30,10 @@ runs: inputs.toolchain != 'arm-gcc' && inputs.toolchain != 'esp-idf' id: set-toolchain-url + env: + TOOLCHAIN: ${{ inputs.toolchain }} run: | - TOOLCHAIN_URL=$(jq -r '."${{ inputs.toolchain }}"' .github/actions/setup_toolchain/toolchain.json) + TOOLCHAIN_URL=$(jq -r --arg tc "$TOOLCHAIN" '.[$tc]' .github/actions/setup_toolchain/toolchain.json) echo "toolchain_url=$TOOLCHAIN_URL" echo "toolchain_url=$TOOLCHAIN_URL" >> $GITHUB_OUTPUT shell: bash @@ -47,11 +49,13 @@ runs: - name: Set toolchain option id: set-toolchain-option + env: + TOOLCHAIN: ${{ inputs.toolchain }} run: | BUILD_OPTION="" - if [[ "${{ inputs.toolchain }}" == *"clang"* ]]; then + if [[ "$TOOLCHAIN" == *"clang"* ]]; then BUILD_OPTION="--toolchain clang" - elif [[ "${{ inputs.toolchain }}" == "arm-iar" ]]; then + elif [[ "$TOOLCHAIN" == "arm-iar" ]]; then BUILD_OPTION="--toolchain iar" fi echo "build_option=$BUILD_OPTION" diff --git a/.github/actions/setup_toolchain/download/action.yml b/.github/actions/setup_toolchain/download/action.yml index ce9643010..af7a9ad4e 100644 --- a/.github/actions/setup_toolchain/download/action.yml +++ b/.github/actions/setup_toolchain/download/action.yml @@ -21,27 +21,34 @@ runs: - name: Install Toolchain if: steps.cache-toolchain-download.outputs.cache-hit != 'true' + env: + TOOLCHAIN: ${{ inputs.toolchain }} + TOOLCHAIN_URL: ${{ inputs.toolchain_url }} run: | - mkdir -p ~/cache/${{ inputs.toolchain }} + mkdir -p ~/cache/${TOOLCHAIN} - if [[ ${{ inputs.toolchain }} == rx-gcc ]]; then - wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.run + if [[ ${TOOLCHAIN} == rx-gcc ]]; then + wget --progress=dot:giga ${TOOLCHAIN_URL} -O toolchain.run chmod +x toolchain.run - ./toolchain.run -p ~/cache/${{ inputs.toolchain }}/gnurx -y - elif [[ ${{ inputs.toolchain }} == arm-iar ]]; then - wget --progress=dot:giga ${{ inputs.toolchain_url }} -O ~/cache/${{ inputs.toolchain }}/cxarm.deb + ./toolchain.run -p ~/cache/${TOOLCHAIN}/gnurx -y + elif [[ ${TOOLCHAIN} == arm-iar ]]; then + wget --progress=dot:giga https://netstorage.iar.com/FileStore/STANDARD/001/003/926/iar-lmsc-tools_1.8_amd64.deb -O ~/cache/${TOOLCHAIN}/iar-lmsc-tools.deb + wget --progress=dot:giga ${TOOLCHAIN_URL} -O ~/cache/${TOOLCHAIN}/cxarm.deb else - wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.tar.gz - tar -C ~/cache/${{ inputs.toolchain }} -xaf toolchain.tar.gz + wget --progress=dot:giga ${TOOLCHAIN_URL} -O toolchain.tar.gz + tar -C ~/cache/${TOOLCHAIN} -xaf toolchain.tar.gz fi shell: bash - name: Setup Toolchain + env: + TOOLCHAIN: ${{ inputs.toolchain }} run: | - if [[ ${{ inputs.toolchain }} == arm-iar ]]; then - sudo apt-get install -y ~/cache/${{ inputs.toolchain }}/cxarm.deb + if [[ ${TOOLCHAIN} == arm-iar ]]; then + sudo dpkg -i ~/cache/${TOOLCHAIN}/iar-lmsc-tools.deb + sudo apt install -y ~/cache/${TOOLCHAIN}/cxarm.deb echo >> $GITHUB_PATH "/opt/iar/cxarm/arm/bin" else - echo >> $GITHUB_PATH `echo ~/cache/${{ inputs.toolchain }}/*/bin` + echo >> $GITHUB_PATH `echo ~/cache/${TOOLCHAIN}/*/bin` fi shell: bash diff --git a/.github/actions/setup_toolchain/espressif/action.yml b/.github/actions/setup_toolchain/espressif/action.yml index b50ffd41d..e9d645ac8 100644 --- a/.github/actions/setup_toolchain/espressif/action.yml +++ b/.github/actions/setup_toolchain/espressif/action.yml @@ -13,8 +13,10 @@ runs: using: "composite" steps: - name: Set DOCKER_ESP_IDF + env: + TOOLCHAIN: ${{ inputs.toolchain }} run: | - DOCKER_ESP_IDF=$HOME/cache/${{ inputs.toolchain }}/docker_image.tar + DOCKER_ESP_IDF=$HOME/cache/${TOOLCHAIN}/docker_image.tar echo "DOCKER_ESP_IDF=$DOCKER_ESP_IDF" >> $GITHUB_ENV shell: bash @@ -27,10 +29,12 @@ runs: - name: Pull and Save Docker Image if: steps.cache-toolchain-espressif.outputs.cache-hit != 'true' + env: + TOOLCHAIN_VERSION: ${{ inputs.toolchain_version }} run: | - docker pull espressif/idf:${{ inputs.toolchain_version }} + docker pull espressif/idf:${TOOLCHAIN_VERSION} mkdir -p $(dirname $DOCKER_ESP_IDF) - docker save -o $DOCKER_ESP_IDF espressif/idf:${{ inputs.toolchain_version }} + docker save -o $DOCKER_ESP_IDF espressif/idf:${TOOLCHAIN_VERSION} du -sh $DOCKER_ESP_IDF shell: bash @@ -42,7 +46,9 @@ runs: shell: bash - name: Tag Local Image + env: + TOOLCHAIN_VERSION: ${{ inputs.toolchain_version }} run: | - docker tag espressif/idf:${{ inputs.toolchain_version }} espressif/idf:tinyusb + docker tag espressif/idf:${TOOLCHAIN_VERSION} espressif/idf:tinyusb docker images shell: bash diff --git a/.github/actions/setup_toolchain/toolchain.json b/.github/actions/setup_toolchain/toolchain.json index f7123ef11..8496dcad3 100644 --- a/.github/actions/setup_toolchain/toolchain.json +++ b/.github/actions/setup_toolchain/toolchain.json @@ -5,5 +5,5 @@ "msp430-gcc": "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", "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz", "rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run", - "arm-iar": "https://netstorage.iar.com/FileStore/STANDARD/001/003/583/cxarm-9.60.4.deb" + "arm-iar": "https://netstorage.iar.com/FileStore/STANDARD/001/003/723/cxarm-9.70.1.deb" } diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 572b8d6f5..000000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,133 +0,0 @@ -# TinyUSB -TinyUSB is an open-source cross-platform USB Host/Device stack for embedded systems, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events deferred to non-ISR task functions. - -Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. - -## Working Effectively - -### Bootstrap and Build Setup -- Install ARM GCC toolchain: `sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi` -- Fetch core dependencies: `python3 tools/get_deps.py` -- takes <1 second. NEVER CANCEL. -- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4) -- Dependencies are cached in `lib/` and `hw/mcu/` directories - -### Build Examples -Choose ONE of these approaches: - -**Option 1: Individual Example with CMake (RECOMMENDED)** -```bash -cd examples/device/cdc_msc -mkdir -p build && cd build -cmake -DBOARD=stm32f407disco -DCMAKE_BUILD_TYPE=MinSizeRel .. -cmake --build . -j4 -``` --- takes 1-2 seconds. NEVER CANCEL. Set timeout to 5+ minutes. - -**Option 2: Individual Example with Make** -```bash -cd examples/device/cdc_msc -make BOARD=stm32f407disco all -``` --- takes 2-3 seconds. NEVER CANCEL. Set timeout to 5+ minutes. - -**Option 3: All Examples for a Board** -```bash -python3 tools/build.py -b BOARD_NAME -``` --- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes. - -### Unit Testing -- Install Ceedling: `sudo gem install ceedling` -- Run all unit tests: `cd test/unit-test && ceedling` -- takes 4 seconds. NEVER CANCEL. Set timeout to 10+ minutes. -- Tests use Unity framework with CMock for mocking - -### Documentation -- Install requirements: `pip install -r docs/requirements.txt` -- Build docs: `cd docs && sphinx-build -b html . _build` -- takes 2-3 seconds. NEVER CANCEL. Set timeout to 10+ minutes. - -### Code Quality and Validation -- Format code: `clang-format -i path/to/file.c` (uses `.clang-format` config) -- Check spelling: `pip install codespell && codespell` (uses `.codespellrc` config) -- Pre-commit hooks validate unit tests and code quality automatically - -## Validation - -### ALWAYS Run These After Making Changes -1. **Pre-commit validation** (RECOMMENDED): `pre-commit run --all-files` - - Install pre-commit: `pip install pre-commit && pre-commit install` - - Runs all quality checks, unit tests, spell checking, and formatting - - Takes 10-15 seconds. NEVER CANCEL. Set timeout to 15+ minutes. -2. **Build validation**: Build at least one example that exercises your changes - ```bash - cd examples/device/cdc_msc - make BOARD=stm32f407disco all - ``` - -### Manual Testing Scenarios -- **Device examples**: Cannot be fully tested without real hardware, but must build successfully -- **Unit tests**: Exercise core stack functionality - ALL tests must pass -- **Build system**: Must be able to build examples for multiple board families - -### Board Selection for Testing -- **STM32F4**: `stm32f407disco` - no external SDK required, good for testing -- **RP2040**: `pico_sdk` - requires Pico SDK, commonly used -- **Other families**: Check `hw/bsp/FAMILY/boards/` for available boards - -## Common Tasks and Time Expectations - -### Repository Structure Quick Reference -``` -├── src/ # Core TinyUSB stack -│ ├── class/ # USB device classes (CDC, HID, MSC, Audio, etc.) -│ ├── portable/ # MCU-specific drivers (organized by vendor) -│ ├── device/ # USB device stack core -│ ├── host/ # USB host stack core -│ └── common/ # Shared utilities (FIFO, etc.) -├── examples/ # Example applications -│ ├── device/ # Device examples (cdc_msc, hid_generic, etc.) -│ ├── host/ # Host examples -│ └── dual/ # Dual-role examples -├── hw/bsp/ # Board Support Packages -│ └── FAMILY/boards/ # Board-specific configurations -├── test/unit-test/ # Unit tests using Ceedling -├── tools/ # Build and utility scripts -└── docs/ # Sphinx documentation -``` - -### Build Time Reference -- **Dependency fetch**: <1 second -- **Single example build**: 1-3 seconds -- **Unit tests**: ~4 seconds -- **Documentation build**: ~2.5 seconds -- **Full board examples**: 15-20 seconds -- **Toolchain installation**: 2-5 minutes (one-time) - -### Key Files to Know -- `tools/get_deps.py`: Manages dependencies for MCU families -- `tools/build.py`: Builds multiple examples, supports make/cmake -- `src/tusb.h`: Main TinyUSB header file -- `src/tusb_config.h`: Configuration template -- `examples/device/cdc_msc/`: Most commonly used example for testing -- `test/unit-test/project.yml`: Ceedling test configuration - -### Debugging Build Issues -- **Missing compiler**: Install `gcc-arm-none-eabi` package -- **Missing dependencies**: Run `python3 tools/get_deps.py FAMILY` -- **Board not found**: Check `hw/bsp/FAMILY/boards/` for valid board names -- **objcopy errors**: Often non-critical in full builds, try individual example builds - -### Working with USB Device Classes -- **CDC (Serial)**: `src/class/cdc/` - Virtual serial port -- **HID**: `src/class/hid/` - Human Interface Device (keyboard, mouse, etc.) -- **MSC**: `src/class/msc/` - Mass Storage Class (USB drive) -- **Audio**: `src/class/audio/` - USB Audio Class -- Each class has device (`*_device.c`) and host (`*_host.c`) implementations - -### MCU Family Support -- **STM32**: Largest support (F0, F1, F2, F3, F4, F7, G0, G4, H7, L4, U5, etc.) -- **Raspberry Pi**: RP2040, RP2350 with PIO-USB host support -- **NXP**: iMXRT, Kinetis, LPC families -- **Microchip**: SAM D/E/G/L families -- Check `hw/bsp/` for complete list and `docs/reference/boards.rst` for details - -Remember: TinyUSB is designed for embedded systems - builds are fast, tests are focused, and the codebase is optimized for resource-constrained environments. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff59421ce..0495ba6a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -161,8 +161,8 @@ jobs: - name: Build run: | - west build -b pca10056 -d examples/device/cdc_msc/build examples/device/cdc_msc -- -DRTOS=zephyr - west build -b pca10056 -d examples/device/msc_dual_lun/build examples/device/msc_dual_lun -- -DRTOS=zephyr + west build -b nrf52840dk -d examples/device/cdc_msc/build examples/device/cdc_msc -- -DRTOS=zephyr + west build -b nrf52840dk -d examples/device/msc_dual_lun/build examples/device/msc_dual_lun -- -DRTOS=zephyr # --------------------------------------- # Hardware in the loop (HIL) @@ -198,37 +198,34 @@ jobs: needs: hil-build runs-on: [self-hosted, X64, hathach, hardware-in-the-loop] steps: + - name: Get Skip Boards from previous run + if: github.run_attempt != '1' + run: | + if [ -f "${{ env.HIL_JSON }}.skip" ]; then + SKIP_BOARDS=$(cat "${{ env.HIL_JSON }}.skip") + else + SKIP_BOARDS="" + fi + echo "SKIP_BOARDS=$SKIP_BOARDS" + echo "SKIP_BOARDS=$SKIP_BOARDS" >> $GITHUB_ENV + - name: Clean workspace - if: github.run_attempt == '1' run: | echo "Cleaning up for the first run" rm -rf "${{ github.workspace }}" mkdir -p "${{ github.workspace }}" - name: Checkout TinyUSB - if: github.run_attempt == '1' uses: actions/checkout@v4 - with: - sparse-checkout: test/hil - name: Download Artifacts - if: github.run_attempt == '1' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: path: cmake-build merge-multiple: true - name: Test on actual hardware run: | - ls cmake-build/ - - # Skip boards that passed with previous run, file is generated by hil_test.py - SKIP_BOARDS="" - if [ -f ${{ env.HIL_JSON }}.skip ]; then - SKIP_BOARDS=$(cat "${HIL_JSON}.skip") - fi - echo "SKIP_BOARDS=$SKIP_BOARDS" - python3 test/hil/hil_test.py ${{ env.HIL_JSON }} $SKIP_BOARDS # --------------------------------------- diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml index a2c96f3c0..55901b838 100644 --- a/.github/workflows/build_util.yml +++ b/.github/workflows/build_util.yml @@ -60,8 +60,9 @@ jobs: - name: Build env: IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} + TOOLCHAIN: ${{ inputs.toolchain }} run: | - if [ "${{ inputs.toolchain }}" == "esp-idf" ]; then + if [ "$TOOLCHAIN" == "esp-idf" ]; then docker run --rm -v $PWD:/project -w /project espressif/idf:tinyusb python tools/build.py ${{ matrix.arg }} else python tools/build.py -s ${{ inputs.build-system }} ${{ steps.setup-toolchain.outputs.build_option }} ${{ steps.set-one-per-family.outputs.build_option }} ${{ matrix.arg }} diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 3559909ba..9d0e42c2e 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -31,20 +31,21 @@ family_list = { "msp430": ["msp430-gcc"], "msp432e4 tm4c": ["arm-gcc"], "nrf": ["arm-gcc", "arm-clang"], + "nuc100_120 nuc121_125 nuc126 nuc505": ["arm-gcc"], "ra": ["arm-gcc"], "rp2040": ["arm-gcc"], "rx": ["rx-gcc"], - "samd11 saml2x": ["arm-gcc", "arm-clang"], - "samd21": ["arm-gcc", "arm-clang"], + "samd11 samd2x_l2x": ["arm-gcc", "arm-clang"], "samd5x_e5x samg": ["arm-gcc", "arm-clang"], "stm32c0 stm32f0 stm32f1 stm32f2 stm32f3": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f7": ["arm-gcc", "arm-clang", "arm-iar"], "stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang", "arm-iar"], - "stm32h7 stm32h7rs": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32h7": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32h7rs": ["arm-gcc", "arm-clang", "arm-iar"], "stm32l0 stm32l4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32n6": ["arm-gcc"], - "stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32u0 stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], "stm32wba": ["arm-gcc", "arm-clang"], "xmc4000": ["arm-gcc"], "-bespressif_s2_devkitc": ["esp-idf"], diff --git a/.github/workflows/codeql-buildscript.sh b/.github/workflows/codeql-buildscript.sh deleted file mode 100644 index 272b55d22..000000000 --- a/.github/workflows/codeql-buildscript.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -FAMILY=stm32l4 -pip install click -python3 tools/get_deps.py $FAMILY -python3 tools/build.py -s make $FAMILY diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index dfcca6315..000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,137 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ 'master' ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - '.github/workflows/codeql.yml' - pull_request: - branches: [ 'master' ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - '.github/workflows/codeql.yml' - schedule: - - cron: '0 0 * * *' - -jobs: - analyze: - name: Analyze - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners - # Consider using larger runners for possible analysis time improvements. - runs-on: ubuntu-latest - timeout-minutes: 360 - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'c-cpp' ] - # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] - # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Toolchain - uses: ./.github/actions/setup_toolchain - with: - toolchain: 'arm-gcc' - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - queries: security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). - # If this step fails, then you should remove it and run the build manually (see below) - #- name: Autobuild - # uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - - run: | - ./.github/workflows/codeql-buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" - upload: false - id: step1 - - # Filter out rules with low severity or high false positive rate - # Also filter out warnings in third-party code - - name: Filter out unwanted errors and warnings - uses: advanced-security/filter-sarif@v1 - with: - patterns: | - -**:cpp/path-injection - -**:cpp/world-writable-file-creation - -**:cpp/poorly-documented-function - -**:cpp/potentially-dangerous-function - -**:cpp/use-of-goto - -**:cpp/integer-multiplication-cast-to-long - -**:cpp/comparison-with-wider-type - -**:cpp/leap-year/* - -**:cpp/ambiguously-signed-bit-field - -**:cpp/suspicious-pointer-scaling - -**:cpp/suspicious-pointer-scaling-void - -**:cpp/unsigned-comparison-zero - -**/third*party/** - -**/3rd*party/** - -**/external/** - input: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif - output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif - - - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: ${{ steps.step1.outputs.sarif-output }} - category: "/language:${{matrix.language}}" - - - name: Upload CodeQL results as an artifact - uses: actions/upload-artifact@v4 - with: - name: codeql-results - path: ${{ steps.step1.outputs.sarif-output }} - retention-days: 5 diff --git a/.github/workflows/fail_on_error.py b/.github/workflows/fail_on_error.py deleted file mode 100755 index 29791742b..000000000 --- a/.github/workflows/fail_on_error.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 - -import json -import sys - -# Return whether SARIF file contains error-level results -def codeql_sarif_contain_error(filename): - with open(filename, 'r') as f: - s = json.load(f) - - for run in s.get('runs', []): - rules_metadata = run['tool']['driver']['rules'] - if not rules_metadata: - rules_metadata = run['tool']['extensions'][0]['rules'] - - for res in run.get('results', []): - if 'ruleIndex' in res: - rule_index = res['ruleIndex'] - elif 'rule' in res and 'index' in res['rule']: - rule_index = res['rule']['index'] - else: - continue - try: - rule_level = rules_metadata[rule_index]['defaultConfiguration']['level'] - except IndexError as e: - print(e, rule_index, len(rules_metadata)) - else: - if rule_level == 'error': - return True - return False - -if __name__ == "__main__": - if codeql_sarif_contain_error(sys.argv[1]): - sys.exit(1) diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml new file mode 100644 index 000000000..4db267517 --- /dev/null +++ b/.github/workflows/static_analysis.yml @@ -0,0 +1,242 @@ +name: Static Analysis +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - 'src/**' + - 'examples/**' + - 'hw/bsp/**' + - '.github/workflows/static_analysis.yml' + pull_request: + branches: [ master ] + paths: + - 'src/**' + - 'examples/**' + - 'hw/bsp/**' + - '.github/workflows/static_analysis.yml' + +permissions: + actions: read + contents: read + security-events: write +# pull-requests: write +# checks: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + CodeQL: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + board: + - 'metro_m4_express' + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Get Dependencies + uses: ./.github/actions/get_deps + with: + arg: -b${{ matrix.board }} + + - name: Setup Toolchain + uses: ./.github/actions/setup_toolchain + with: + toolchain: 'arm-gcc' + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: 'c-cpp' + queries: security-and-quality + + - name: Build + run: | + mkdir -p build + cmake examples -B build -G Ninja -DBOARD=${{ matrix.board }} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=MinSizeRel + cmake --build build + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: CodeQL + upload: false + id: analyze + + - name: Filter SARIF report + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -hw/mcu/** + -lib/** + input: ${{ steps.analyze.outputs.sarif-output }}/cpp.sarif + output: ${{ steps.analyze.outputs.sarif-output }}/cpp.sarif + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: ${{ steps.analyze.outputs.sarif-output }} + category: CodeQL + + - name: Upload artifact + uses: actions/upload-artifact@v5 + with: + name: codeql-${{ matrix.board }} + path: ${{ steps.analyze.outputs.sarif-output }} + + PVS-Studio: + # Only run on non-forked PR since secrets token is required + if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + board: + - 'raspberry_pi_pico' + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Get Dependencies + uses: ./.github/actions/get_deps + with: + arg: -b${{ matrix.board }} + + - name: Setup Toolchain + uses: ./.github/actions/setup_toolchain + with: + toolchain: 'arm-gcc' + + - name: Install Tools + run: | + wget -q -O - https://files.pvs-studio.com/etc/pubkey.txt | sudo apt-key add - + sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.pvs-studio.com/etc/viva64.list + sudo apt update + sudo apt install pvs-studio + pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} + pvs-studio-analyzer --version + + - name: Analyze + run: | + mkdir -p build + cmake examples -B build -G Ninja -DBOARD=${{ matrix.board }} -DCMAKE_BUILD_TYPE=MinSizeRel + cmake --build build + pvs-studio-analyzer analyze -f build/compile_commands.json -R .PVS-Studio/.pvsconfig -j4 --security-related-issues --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser -e lib/ -e hw/mcu/ -e */iar/cxarm/ -e pico-sdk/ + plog-converter -t sarif -o pvs-studio-${{ matrix.board }}.sarif PVS-Studio.log + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: pvs-studio-${{ matrix.board }}.sarif + category: PVS-Studio + + - name: Upload artifact + uses: actions/upload-artifact@v5 + with: + name: pvs-studio-${{ matrix.board }} + path: pvs-studio-${{ matrix.board }}.sarif + + SonarQube: + # Only run on non-forked PR since secrets token is required + if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false + runs-on: ubuntu-latest + env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory + strategy: + fail-fast: false + matrix: + board: + - 'stm32h743eval' + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + + - name: Get Dependencies + uses: ./.github/actions/get_deps + with: + arg: -b${{ matrix.board }} + + - name: Setup Toolchain + uses: ./.github/actions/setup_toolchain + with: + toolchain: 'arm-gcc' + + - name: Install Build Wrapper + uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v6 + + - name: Run Build Wrapper + run: | + cmake examples -B build -G Ninja -DBOARD=${{ matrix.board }} -DCMAKE_BUILD_TYPE=MinSizeRel + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build/ + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@v6 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + with: + # Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options + args: > + --define sonar.cfamily.compile-commands=${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json + + IAR-CStat: + # Only run on non-forked PR since secrets token is required + #if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false + if: false + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + board: + - 'b_g474e_dpow1' + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Get Dependencies + uses: ./.github/actions/get_deps + with: + arg: -b${{ matrix.board }} + + - name: Setup Toolchain + uses: ./.github/actions/setup_toolchain + with: + toolchain: 'arm-iar' + + - name: Install CMake 4.2 + run: | + # IAR CSTAT requires CMake >= 4.1 + wget -q https://github.com/Kitware/CMake/releases/download/v4.2.0-rc1/cmake-4.2.0-rc1-linux-x86_64.tar.gz + tar -xzf cmake-4.2.0-rc1-linux-x86_64.tar.gz + echo "${{ github.workspace }}/cmake-4.2.0-rc1-linux-x86_64/bin" >> $GITHUB_PATH + + - name: Build and run IAR C-STAT Analysis + env: + IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} + run: | + # CMake run post build to generate C-STAT SARIF report + cmake --version + mkdir -p build + cmake examples/device/cdc_msc -B build -G Ninja -DBOARD=${{ matrix.board }} -DTOOLCHAIN=iar -DIAR_CSTAT=1 -DCMAKE_BUILD_TYPE=MinSizeRel + cmake --build build + # Merge sarif files for codeql upload + npm i -g @microsoft/sarif-multitool + npx @microsoft/sarif-multitool merge --merge-runs --output-file iar-cstat-${{ matrix.board }}.sarif build/cstat_sarif/*.sarif + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: iar-cstat-${{ matrix.board }}.sarif + category: IAR-CStat + + - name: Upload artifact + uses: actions/upload-artifact@v5 + with: + name: iar-cstat-${{ matrix.board }} + path: iar-cstat-${{ matrix.board }}.sarif diff --git a/.gitignore b/.gitignore index a4045f120..977911dff 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ latex *.ewt *.ewd *.hex +.venv/ cmake_install.cmake CMakeCache.txt settings/ diff --git a/.idea/debugServers/lpc1769.xml b/.idea/debugServers/lpc1769.xml new file mode 100644 index 000000000..4acfe6afe --- /dev/null +++ b/.idea/debugServers/lpc1769.xml @@ -0,0 +1,13 @@ +<component name="DebugServers"> + <jlink-debug-target name="lpc1769" uniqueID="8f746157-a0c3-435f-b417-10f26c3b2699"> + <debugger version="1"> + <debugger kind="GDB" isBundled="true" /> + <env /> + </debugger> + <gdbserver exe="/usr/bin/JLinkGDBServerCLExe" /> + <console port="19021" /> + <target device="LPC1769" reset-before="false" frequency="12000" /> + <connection extended-remote="false" port="4444" warmup-ms="500" /> + <swo /> + </jlink-debug-target> +</component>
\ No newline at end of file diff --git a/.idea/debugServers/lpc55s69.xml b/.idea/debugServers/lpc55s69.xml new file mode 100644 index 000000000..ceedab0af --- /dev/null +++ b/.idea/debugServers/lpc55s69.xml @@ -0,0 +1,13 @@ +<component name="DebugServers"> + <jlink-debug-target name="lpc55s69" uniqueID="7de47452-94f1-4f1d-b03c-0f4ad3556d01"> + <debugger version="1"> + <debugger kind="GDB" isBundled="true" /> + <env /> + </debugger> + <gdbserver exe="/usr/bin/JLinkGDBServerCLExe" /> + <console port="19021" /> + <target device="LPC55S69_M33_0" reset-before="false" frequency="12000" /> + <connection extended-remote="false" port="4444" warmup-ms="500" /> + <swo /> + </jlink-debug-target> +</component>
\ No newline at end of file diff --git a/.idea/debugServers/nrf52833.xml b/.idea/debugServers/nrf52833.xml new file mode 100644 index 000000000..09d2ae3d3 --- /dev/null +++ b/.idea/debugServers/nrf52833.xml @@ -0,0 +1,13 @@ +<component name="DebugServers"> + <jlink-debug-target name="nrf52833" uniqueID="19eede9f-2096-4b30-9390-14d415964264"> + <debugger version="1"> + <debugger kind="GDB" isBundled="true" /> + <env /> + </debugger> + <gdbserver exe="/usr/bin/JLinkGDBServerCLExe" /> + <console port="19021" /> + <target device="nRF52833_xxAA" reset-before="false" frequency="12000" /> + <connection extended-remote="false" port="4444" warmup-ms="500" /> + <swo /> + </jlink-debug-target> +</component>
\ No newline at end of file diff --git a/.idea/debugServers/nrf5340.xml b/.idea/debugServers/nrf5340.xml new file mode 100644 index 000000000..ac3bd59fa --- /dev/null +++ b/.idea/debugServers/nrf5340.xml @@ -0,0 +1,13 @@ +<component name="DebugServers"> + <jlink-debug-target name="nrf5340" uniqueID="d82e668b-1307-4266-8a5c-3752be6795c9" selected="true"> + <debugger version="1"> + <debugger kind="GDB" isBundled="true" /> + <env /> + </debugger> + <gdbserver exe="/usr/bin/JLinkGDBServerCLExe" /> + <console port="19021" /> + <target device="nRF5340_xxAA_APP" reset-before="false" frequency="12000" /> + <connection extended-remote="false" port="4444" warmup-ms="500" /> + <swo /> + </jlink-debug-target> +</component>
\ No newline at end of file diff --git a/.idea/debugServers/stm32f411.xml b/.idea/debugServers/stm32f411.xml new file mode 100644 index 000000000..2bcdf3829 --- /dev/null +++ b/.idea/debugServers/stm32f411.xml @@ -0,0 +1,13 @@ +<component name="DebugServers"> + <jlink-debug-target name="stm32f411" uniqueID="c48950a7-634c-49b6-b136-204ed0b71718"> + <debugger version="1"> + <debugger kind="GDB" isBundled="true" /> + <env /> + </debugger> + <gdbserver exe="/usr/bin/JLinkGDBServerCLExe" /> + <console port="19021" /> + <target device="STM32F411VE" reset-before="false" frequency="12000" /> + <connection extended-remote="false" port="4444" warmup-ms="500" /> + <swo /> + </jlink-debug-target> +</component>
\ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..a6163dd42 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,272 @@ +# TinyUSB Agent Instructions + +TinyUSB is an open-source cross-platform USB Host/Device stack for embedded systems, designed to be memory-safe with no +dynamic allocation and thread-safe with all interrupt events deferred to non-ISR task functions. + +Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected +information that does not match the info here. + +## Shared Ground Rules +- Keep TinyUSB memory-safe: avoid dynamic allocation, defer ISR work to task context, and follow C99 with two-space indentation/no tabs. +- Match file organization: core stack under `src`, MCU/BSP support in `hw/{mcu,bsp}`, examples under `examples/{device,host,dual}`, docs in `docs`, tests under `test/{unit-test,fuzz,hil}`. +- Use descriptive snake_case for helpers, reserve `tud_`/`tuh_` for public APIs, `TU_` for macros, and keep headers self-contained with `#if CFG_TUSB_MCU` guards where needed. +- Prefer `.clang-format` for C/C++ formatting, run `pre-commit run --all-files` before submitting, and document board/HIL coverage when applicable. +- Commit in imperative mood, keep changes scoped, and supply PRs with linked issues plus test/build evidence. + + +## Bootstrap and Build Setup + +- Install ARM GCC toolchain: `sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi` +- Fetch core dependencies: `python3 tools/get_deps.py` -- takes <1 second. NEVER CANCEL. +- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4) +- Dependencies are cached in `lib/` and `hw/mcu/` directories + +## Build Examples + +Choose ONE of these approaches: + +**Option 1: Individual Example with CMake (RECOMMENDED)** + +```bash +cd examples/device/cdc_msc +mkdir -p build && cd build +cmake -DBOARD=raspberry_pi_pico -DCMAKE_BUILD_TYPE=MinSizeRel .. +cmake --build . -j4 +``` + +-- takes 1-2 seconds. NEVER CANCEL. Set timeout to 5+ minutes. + +**CMake with Ninja (Alternative)** + +```bash +cd examples/device/cdc_msc +mkdir build && cd build +cmake -G Ninja -DBOARD=raspberry_pi_pico .. +ninja +``` + +**Option 2: Individual Example with Make** + +```bash +cd examples/device/cdc_msc +make BOARD=raspberry_pi_pico all +``` + +-- takes 2-3 seconds. NEVER CANCEL. Set timeout to 5+ minutes. + +**Option 3: All Examples for a Board** + +```bash +python3 tools/build.py -b BOARD_NAME +``` + +-- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes. + +## Build Options + +- **Debug build**: + - CMake: `-DCMAKE_BUILD_TYPE=Debug` + - Make: `DEBUG=1` +- **With logging**: + - CMake: `-DLOG=2` + - Make: `LOG=2` +- **With RTT logger**: + - CMake: `-DLOG=2 -DLOGGER=rtt` + - Make: `LOG=2 LOGGER=rtt` +- **RootHub port selection**: + - CMake: `-DRHPORT_DEVICE=1` + - Make: `RHPORT_DEVICE=1` +- **Port speed**: + - CMake: `-DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` + - Make: `RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` + +## Flashing and Deployment + +- **Flash with JLink**: + - CMake: `ninja cdc_msc-jlink` + - Make: `make BOARD=raspberry_pi_pico flash-jlink` +- **Flash with OpenOCD**: + - CMake: `ninja cdc_msc-openocd` + - Make: `make BOARD=raspberry_pi_pico flash-openocd` +- **Generate UF2**: + - CMake: `ninja cdc_msc-uf2` + - Make: `make BOARD=raspberry_pi_pico all uf2` +- **List all targets** (CMake/Ninja): `ninja -t targets` + +## Unit Testing + +- Install Ceedling: `sudo gem install ceedling` +- Run all unit tests: `cd test/unit-test && ceedling` or `cd test/unit-test && ceedling test:all` -- takes 4 seconds. + NEVER CANCEL. Set timeout to 10+ minutes. +- Run specific test: `cd test/unit-test && ceedling test:test_fifo` +- Tests use Unity framework with CMock for mocking + +## Documentation + +- Install requirements: `pip install -r docs/requirements.txt` +- Build docs: `cd docs && sphinx-build -b html . _build` -- takes 2-3 seconds. NEVER CANCEL. Set timeout to 10+ minutes. + +## Code Quality and Validation + +- Format code: `clang-format -i path/to/file.c` (uses `.clang-format` config) +- Check spelling: `pip install codespell && codespell` (uses `.codespellrc` config) +- Pre-commit hooks validate unit tests and code quality automatically + +## Static Analysis with PVS-Studio + +- **Analyze whole project**: + ```bash + pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser + ``` +- **Analyze specific source files**: + ```bash + pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -S path/to/file.c -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser + ``` +- **Multiple specific files**: + ```bash + pvs-studio-analyzer analyze -f examples/cmake-build-raspberry_pi_pico/compile_commands.json -R .PVS-Studio/.pvsconfig -S src/file1.c -S src/file2.c -o pvs-report.log -j12 --dump-files --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser + ``` +- Requires `compile_commands.json` in the build directory (generated by CMake with `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON`) +- Use `-f` option to specify path to `compile_commands.json` +- Use `-R .PVS-Studio/.pvsconfig` to specify rule configuration file +- Use `-j12` for parallel analysis with 12 threads +- `--dump-files` saves preprocessed files for debugging +- `--misra-c-version 2023` enables MISRA C:2023 checks +- `--misra-cpp-version 2008` enables MISRA C++:2008 checks +- `--use-old-parser` uses legacy parser for compatibility +- Analysis takes ~10-30 seconds depending on project size. Set timeout to 5+ minutes. +- View results: `plog-converter -a GA:1,2 -t errorfile pvs-report.log` or open in PVS-Studio GUI + +## Validation Checklist + +### ALWAYS Run These After Making Changes + +1. **Pre-commit validation** (RECOMMENDED): `pre-commit run --all-files` + - Install pre-commit: `pip install pre-commit && pre-commit install` + - Runs all quality checks, unit tests, spell checking, and formatting + - Takes 10-15 seconds. NEVER CANCEL. Set timeout to 15+ minutes. +2. **Build validation**: Build at least one example that exercises your changes + ```bash + cd examples/device/cdc_msc + make BOARD=raspberry_pi_pico all + ``` +3. Run unit tests relevant to touched modules; add fuzz/HIL coverage when modifying parsers or protocol state machines. + +### Manual Testing Scenarios +- **Device examples**: Cannot be fully tested without real hardware, but must build successfully +- **Unit tests**: Exercise core stack functionality - ALL tests must pass +- **Build system**: Must be able to build examples for multiple board families + +### Board Selection for Testing +- **STM32F4**: `stm32f407disco` - no external SDK required, good for testing +- **RP2040**: `raspberry_pi_pico` - requires Pico SDK, commonly used +- **Other families**: Check `hw/bsp/FAMILY/boards/` for available boards + +## Release Instructions + +**DO NOT commit files automatically - only modify files and let the maintainer review before committing.** + +1. Bump the release version variable at the top of `tools/make_release.py`. +2. Execute `python3 tools/make_release.py` to refresh: + - `src/tusb_option.h` (version defines) + - `repository.yml` (version mapping) + - `library.json` (PlatformIO version) + - `sonar-project.properties` (SonarQube version) + - `docs/reference/boards.rst` (generated board documentation) + - `hw/bsp/BoardPresets.json` (CMake presets) +3. Generate release notes for `docs/info/changelog.rst`: + - Get commit list: `git log <last-release-tag>..HEAD --oneline` + - **Visit GitHub PRs** for merged pull requests to understand context and gather details + - Use GitHub tools to search/read PRs: `github-mcp-server-list_pull_requests`, `github-mcp-server-pull_request_read` + - Extract key changes, API modifications, bug fixes, and new features from PR descriptions + - Add new changelog entry following the existing format: + - Version heading with equals underline (e.g., `0.20.0` followed by `======`) + - Release date in italics (e.g., `*November 19, 2024*`) + - Major sections: General, API Changes, Controller Driver (DCD & HCD), Device Stack, Host Stack, Testing + - Use bullet lists with descriptive categorization + - Reference function names, config macros, and file paths using RST inline code (double backticks) + - Include meaningful descriptions, not just commit messages +4. **Validation before commit**: + - Run unit tests: `cd test/unit-test && ceedling test:all` + - Build at least one example: `cd examples/device/cdc_msc && make BOARD=stm32f407disco all` + - Verify changed files look correct: `git diff --stat` +5. **Leave files unstaged** for maintainer to review, modify if needed, and commit with message: `Bump version to X.Y.Z` +6. **After maintainer commits**: Create annotated tag with `git tag -a vX.Y.Z -m "Release X.Y.Z"` +7. Push commit and tag: `git push origin <branch> && git push origin vX.Y.Z` +8. Create GitHub release from the tag with changelog content + +## Repository Structure Quick Reference +``` +├── src/ # Core TinyUSB stack +│ ├── class/ # USB device classes (CDC, HID, MSC, Audio, etc.) +│ ├── portable/ # MCU-specific drivers (organized by vendor) +│ ├── device/ # USB device stack core +│ ├── host/ # USB host stack core +│ └── common/ # Shared utilities (FIFO, etc.) +├── examples/ # Example applications +│ ├── device/ # Device examples (cdc_msc, hid_generic, etc.) +│ ├── host/ # Host examples +│ └── dual/ # Dual-role examples +├── hw/bsp/ # Board Support Packages +│ └── FAMILY/boards/ # Board-specific configurations +├── test/unit-test/ # Unit tests using Ceedling +├── tools/ # Build and utility scripts +└── docs/ # Sphinx documentation +``` + +#### Build Time Reference +- **Dependency fetch**: <1 second +- **Single example build**: 1-3 seconds +- **Unit tests**: ~4 seconds +- **Documentation build**: ~2.5 seconds +- **Full board examples**: 15-20 seconds +- **Toolchain installation**: 2-5 minutes (one-time) + +#### Key Files to Know +- `tools/get_deps.py`: Manages dependencies for MCU families +- `tools/build.py`: Builds multiple examples, supports make/cmake +- `src/tusb.h`: Main TinyUSB header file +- `src/tusb_config.h`: Configuration template +- `examples/device/cdc_msc/`: Most commonly used example for testing +- `test/unit-test/project.yml`: Ceedling test configuration + +#### Debugging Build Issues +- **Missing compiler**: Install `gcc-arm-none-eabi` package +- **Missing dependencies**: Run `python3 tools/get_deps.py FAMILY` +- **Board not found**: Check `hw/bsp/FAMILY/boards/` for valid board names +- **objcopy errors**: Often non-critical in full builds, try individual example builds + +#### Working with USB Device Classes +- **CDC (Serial)**: `src/class/cdc/` - Virtual serial port +- **HID**: `src/class/hid/` - Human Interface Device (keyboard, mouse, etc.) +- **MSC**: `src/class/msc/` - Mass Storage Class (USB drive) +- **Audio**: `src/class/audio/` - USB Audio Class +- Each class has device (`*_device.c`) and host (`*_host.c`) implementations + +#### MCU Family Support +- **STM32**: Largest support (F0, F1, F2, F3, F4, F7, G0, G4, H7, L4, U5, etc.) +- **Raspberry Pi**: RP2040, RP2350 with PIO-USB host support +- **NXP**: iMXRT, Kinetis, LPC families +- **Microchip**: SAM D/E/G/L families +- Check `hw/bsp/` for complete list and `docs/reference/boards.rst` for details + +### Code Style Guidelines + +#### General Coding Standards +- Use C99 standard +- Memory-safe: no dynamic allocation +- Thread-safe: defer all interrupt events to non-ISR task functions +- 2-space indentation, no tabs +- Use snake_case for variables/functions +- Use UPPER_CASE for macros and constants +- Follow existing variable naming patterns in files you're modifying +- Include proper header comments with MIT license +- Add descriptive comments for non-obvious functions + +#### Best Practices +- When including headers, group in order: C stdlib, tusb common, drivers, classes +- Always check return values from functions that can fail +- Use TU_ASSERT() for error checking with return statements +- Follow the existing code patterns in the files you're modifying + +Remember: TinyUSB is designed for embedded systems - builds are fast, tests are focused, and the codebase is optimized for resource-constrained environments. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..6c6baa246 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,78 @@ +# TinyUSB Development Guide + +## Build Commands + +### CMake Build System (Preferred) +CMake with Ninja is the preferred build method for TinyUSB development. + +- Build example with Ninja: + ```bash + cd examples/device/cdc_msc + mkdir build && cd build + cmake -G Ninja -DBOARD=raspberry_pi_pico .. + ninja + ``` +- Debug build: `cmake -G Ninja -DBOARD=raspberry_pi_pico -DCMAKE_BUILD_TYPE=Debug ..` +- With logging: `cmake -G Ninja -DBOARD=raspberry_pi_pico -DLOG=2 ..` +- With RTT logger: `cmake -G Ninja -DBOARD=raspberry_pi_pico -DLOG=2 -DLOGGER=rtt ..` +- Flash with JLink: `ninja cdc_msc-jlink` +- Flash with OpenOCD: `ninja cdc_msc-openocd` +- Generate UF2: `ninja cdc_msc-uf2` +- List all targets: `ninja -t targets` + +### Make Build System (Alternative) +- Build example: `cd examples/device/cdc_msc && make BOARD=raspberry_pi_pico all` +- For specific example: `cd examples/{device|host|dual}/{example_name} && make BOARD=raspberry_pi_pico all` +- Flash with JLink: `make BOARD=raspberry_pi_pico flash-jlink` +- Flash with OpenOCD: `make BOARD=raspberry_pi_pico flash-openocd` +- Debug build: `make BOARD=raspberry_pi_pico DEBUG=1 all` +- With logging: `make BOARD=raspberry_pi_pico LOG=2 all` +- With RTT logger: `make BOARD=raspberry_pi_pico LOG=2 LOGGER=rtt all` +- Generate UF2: `make BOARD=raspberry_pi_pico all uf2` + +### Additional Options +- Select RootHub port: `RHPORT_DEVICE=1` (make) or `-DRHPORT_DEVICE=1` (cmake) +- Set port speed: `RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` (make) or `-DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED` (cmake) + +### Dependencies +- Get dependencies: `python tools/get_deps.py rp2040` +- Or from example: `cd examples/device/cdc_msc && make BOARD=raspberry_pi_pico get-deps` + +### Testing +- Run unit tests: `cd test/unit-test && ceedling test:all` +- Run specific test: `cd test/unit-test && ceedling test:test_fifo` + +### Pre-commit Hooks +Before building, it's recommended to run pre-commit to ensure code quality: +- Run pre-commit on all files: `pre-commit run --all-files` +- Run pre-commit on staged files: `pre-commit run` +- Install pre-commit hook: `pre-commit install` + +## Code Style Guidelines +- Use C99 standard +- Memory-safe: no dynamic allocation +- Thread-safe: defer all interrupt events to non-ISR task functions +- 2-space indentation, no tabs +- Use snake_case for variables/functions +- Use UPPER_CASE for macros and constants +- Follow existing variable naming patterns in files you're modifying +- Include proper header comments with MIT license +- Add descriptive comments for non-obvious functions +- When including headers, group in order: C stdlib, tusb common, drivers, classes +- Always check return values from functions that can fail +- Use TU_ASSERT() for error checking with return statements + +## Project Structure +- src/: Core TinyUSB stack code +- hw/: Board support packages and MCU drivers +- examples/: Reference examples for device/host/dual +- test/: Unit tests and hardware integration tests + +## Release Process +To prepare a new release: +1. Update the `version` variable in `tools/make_release.py` to the new version number +2. Run the release script: `python tools/make_release.py` + - This will update version numbers in `src/tusb_option.h`, `repository.yml`, and `library.json` + - It will also regenerate documentation +3. Update `docs/info/changelog.rst` with release notes +4. Commit changes and create release tag diff --git a/README.rst b/README.rst index d089bc3be..6a6f07825 100644 --- a/README.rst +++ b/README.rst @@ -1,26 +1,55 @@ -|Build Status| |CircleCI Status| |Documentation Status| |Fuzzing Status| |License| +TinyUSB +======= + +|Build Status| |CircleCI Status| |Documentation Status| |Static Analysis| |Fuzzing Status| |License| Sponsors -======== +-------- TinyUSB is funded by: Adafruit. Purchasing products from them helps to support this project. .. figure:: docs/assets/adafruit_logo.svg :alt: Adafruit Logo + :align: left :target: https://www.adafruit.com -TinyUSB Project -=============== +.. raw:: html + + <div class="clear-both"></div> + +Overview +-------- .. figure:: docs/assets/logo.svg :alt: TinyUSB + :align: left + +.. raw:: html + + <div class="clear-both"></div> -TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function. Check out the online `documentation <https://docs.tinyusb.org/>`__ for more details. +TinyUSB is an open-source cross-platform USB Host/Device stack for embedded systems. It’s designed for memory safety +(no dynamic allocation) and thread safety (all interrupts deferred to non-ISR task functions). The stack emphasizes portability, +small footprint, and real-time performance across 50+ MCU families. + +Key Features +------------ + +* **Thread-safe:** USB interrupts deferred to task context +* **Memory-safe:** No dynamic allocation, all buffers static +* **Portable:** Supports 50+ MCU families +* **Comprehensive:** Includes CDC, HID, MSC, Audio, and Host support +* **RTOS-friendly:** Works with bare metal, FreeRTOS, RT-Thread, and Mynewt .. figure:: docs/assets/stack.svg :width: 500px + :align: left :alt: stackup +.. raw:: html + + <div class="clear-both"></div> + :: . @@ -36,7 +65,7 @@ TinyUSB is an open-source cross-platform USB Host/Device stack for embedded syst Getting started -=============== +--------------- See the `online documentation <https://docs.tinyusb.org>`_ for information about using TinyUSB and how it is implemented. @@ -49,7 +78,7 @@ For bugs and feature requests, please `raise an issue <https://github.com/hathac See `Porting`_ guide for adding support for new MCUs and boards. Device Stack -============ +------------ Supports multiple device configurations by dynamically changing USB descriptors, low power functions such like suspend, resume, and remote wakeup. The following device classes are supported: @@ -60,6 +89,7 @@ Supports multiple device configurations by dynamically changing USB descriptors, - Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... - Mass Storage Class (MSC): with multiple LUNs - Musical Instrument Digital Interface (MIDI) +- Media Transfer Protocol (MTP/PTP) - Network with RNDIS, Ethernet Control Model (ECM), Network Control Model (NCM) - Test and Measurement Class (USBTMC) - Video class 1.5 (UVC): work in progress @@ -69,7 +99,7 @@ Supports multiple device configurations by dynamically changing USB descriptors, If you have a special requirement, ``usbd_app_driver_get_cb()`` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 <https://github.com/raspberrypi/pico-sdk/pull/197>`_ Host Stack -========== +---------- - Human Interface Device (HID): Keyboard, Mouse, Generic - Mass Storage Class (MSC) @@ -80,14 +110,14 @@ Host Stack Similar to the Device Stack, if you have a special requirement, ``usbh_app_driver_get_cb()`` can be used to write your own class driver without modifying the stack. Power Delivery Stack -==================== +-------------------- - Power Delivery 3.0 (PD3.0) with USB Type-C support (WIP) - Super early stage, only for testing purpose - Only support STM32 G4 OS Abstraction layer -==================== +-------------------- TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) events into a central queue, then processing them later in the non-ISR context task function. It also uses semaphore/mutex to access shared resources such as Communication Device Class (CDC) FIFO. Therefore the stack needs to use some of the OS's basic APIs. Following OSes are already supported out of the box. @@ -97,7 +127,7 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR) - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo <https://github.com/hathach/mynewt-tinyusb-example>`_ Supported CPUs -============== +-------------- +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Manufacturer | Family | Device | Host | Highspeed | Driver | Note | @@ -115,13 +145,13 @@ Supported CPUs | +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Brigetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | +| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 or esp32sx | | +| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | | | ESP32 +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | P4 | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+-------------------+ @@ -147,7 +177,7 @@ Supported CPUs | | +-----------------------+--------+------+-----------+------------------------+-------------------+ | | | 32mz | ✔ | | | pic32mz | musb variant | +--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ -| Mind Montion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | +| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant | +--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ | NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is ISO | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ @@ -159,7 +189,7 @@ Supported CPUs | +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | NUC505 | ✔ | | ✔ | nuc505 | | +--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs | | +| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | | | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ | | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ @@ -167,15 +197,15 @@ Supported CPUs | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ | | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40 | | +| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ -| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs | | +| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs | | +| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | | | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | A15 | ✔ | | | ci_fs | | +--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ @@ -202,8 +232,6 @@ Supported CPUs | | C0, G0, H5 | ✔ | | ✖ | stm32_fsdev | | | +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | G4 | ✔ | ✖ | ✖ | stm32_fsdev | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | L0, L1 | ✔ | ✖ | ✖ | stm32_fsdev | | | +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | | | +------------------------+--------+------+-----------+------------------------+-------------------+ @@ -211,6 +239,10 @@ Supported CPUs | +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | N6 | ✔ | ✔ | ✔ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+-------------------+ +| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+-------------------+ +| | U3 | ✔ | | ✖ | stm32_fsdev | | +| +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | U5 | 535, 545 | ✔ | | ✖ | stm32_fsdev | | | | +------------------------+--------+------+-----------+------------------------+-------------------+ | | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | @@ -231,7 +263,7 @@ Supported CPUs +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ Table Legend ------------- +^^^^^^^^^^^^ ========= ========================= ✔ Supported @@ -240,13 +272,24 @@ Table Legend \[empty\] Unknown ========= ========================= +Development Tools +----------------- + +The following tools are provided freely to support the development of the TinyUSB project: + +- `IAR Build Tools (CX) <https://iar.com>`_ Professional IDE and compiler for embedded development. +- `JetBrains CLion <https://www.jetbrains.com/clion/>`_ Cross-platform IDE for C and C++ development. +- `PVS-Studio <https://pvs-studio.com/en/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source>`_ static analyzer for C, C++, C#, and Java code. + .. |Build Status| image:: https://github.com/hathach/tinyusb/actions/workflows/build.yml/badge.svg - :target: https://github.com/hathach/tinyusb/actions + :target: https://github.com/hathach/tinyusb/actions/workflows/build.yml .. |CircleCI Status| image:: https://dl.circleci.com/status-badge/img/circleci/4AYHvUhFxdnY4rA7LEsdqW/QmrpoL2AjGqetvFQNqtWyq/tree/master.svg?style=svg :target: https://dl.circleci.com/status-badge/redirect/circleci/4AYHvUhFxdnY4rA7LEsdqW/QmrpoL2AjGqetvFQNqtWyq/tree/master .. |Documentation Status| image:: https://readthedocs.org/projects/tinyusb/badge/?version=latest :target: https://docs.tinyusb.org/en/latest/?badge=latest +.. |Static Analysis| image:: https://github.com/hathach/tinyusb/actions/workflows/static_analysis.yml/badge.svg + :target: https://github.com/hathach/tinyusb/actions/workflows/static_analysis.yml .. |Fuzzing Status| image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/tinyusb.svg :target: https://oss-fuzz-build-logs.storage.googleapis.com/index.html#tinyusb .. |License| image:: https://img.shields.io/badge/license-MIT-brightgreen.svg @@ -255,10 +298,9 @@ Table Legend .. _Changelog: docs/info/changelog.rst .. _Contributors: CONTRIBUTORS.rst -.. _Getting Started: docs/reference/getting_started.rst +.. _Getting Started: docs/getting_started.rst .. _Supported Boards: docs/reference/boards.rst .. _Dependencies: docs/reference/dependencies.rst .. _Concurrency: docs/reference/concurrency.rst -.. _Contributing: docs/contributing/index.rst .. _Code of Conduct: CODE_OF_CONDUCT.rst -.. _Porting: docs/contributing/porting.rst +.. _Porting: docs/porting.rst diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 000000000..d64d26047 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,3 @@ +.clear-both { + clear: both; +} diff --git a/docs/conf.py b/docs/conf.py index 4249d41f7..cd0338413 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,7 +14,7 @@ from pathlib import Path # -- Project information ----------------------------------------------------- project = 'TinyUSB' -copyright = '2024, Ha Thach' +copyright = '2025, Ha Thach' author = 'Ha Thach' @@ -41,6 +41,8 @@ html_favicon = 'assets/logo.svg' html_theme_options = { 'sidebar_hide_name': True, } +html_static_path = ['_static'] +html_css_files = ['custom.css'] todo_include_todos = True @@ -52,7 +54,9 @@ def preprocess_readme(): if src.exists(): content = src.read_text() content = re.sub(r"docs/", r"", content) - content = re.sub(r".rst", r".html", content) + content = re.sub(r"\.rst\b", r".html", content) + if not content.endswith("\n"): + content += "\n" tgt.write_text(content) preprocess_readme() diff --git a/docs/contributing/code_of_conduct.rst b/docs/contributing/code_of_conduct.rst deleted file mode 100644 index fb1859c75..000000000 --- a/docs/contributing/code_of_conduct.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../CODE_OF_CONDUCT.rst
\ No newline at end of file diff --git a/docs/contributing/index.rst b/docs/contributing/index.rst deleted file mode 100644 index 78933a3ca..000000000 --- a/docs/contributing/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -************ -Contributing -************ - -Contributing can be highly rewarding, but it can also be frustrating at times. -It takes time to review patches, and as this is an open source project, that -sometimes can take a while. The reviewing process depends on the availability -of the maintainers, who may not be always available. Please try to be -understanding through the process. - -There a few guidelines you need to keep in mind when contributing. Please have -a look at them as that will make the contribution process easier for all -parties. - -Index -===== - -.. toctree:: - :maxdepth: 2 - - code_of_conduct - porting diff --git a/docs/faq.rst b/docs/faq.rst new file mode 100644 index 000000000..a5fe09495 --- /dev/null +++ b/docs/faq.rst @@ -0,0 +1,180 @@ +************************** +Frequently Asked Questions +************************** + +General Questions +================= + +**Q: What microcontrollers does TinyUSB support?** + +TinyUSB supports 50+ MCU families including STM32, RP2040, NXP (iMXRT, Kinetis, LPC), Microchip SAM, Nordic nRF5x, ESP32, and many others. See :doc:`reference/boards` for the complete list. + +**Q: Can I use TinyUSB in commercial projects?** + +Yes, TinyUSB is released under the MIT license, allowing commercial use with minimal restrictions. + +**Q: Does TinyUSB require an RTOS?** + +No, TinyUSB works in bare metal environments. It also supports FreeRTOS, RT-Thread, and Mynewt. + +**Q: How much memory does TinyUSB use?** + +Typical usage: 8-20KB flash, 1-4KB RAM depending on enabled classes and configuration. The stack uses static allocation only. + +Build and Setup +================ + +**Q: Why do I get "arm-none-eabi-gcc: command not found"?** + +Install the ARM GCC toolchain: ``sudo apt-get install gcc-arm-none-eabi`` on Ubuntu/Debian, or download from ARM's website for other platforms. + +**Q: Build fails with "Board 'X' not found"** + +Check available boards: ``ls hw/bsp/FAMILY/boards/`` or run ``python tools/build.py -l`` to list all supported boards. + +**Q: What are the dependencies and how do I get them?** + +Run ``python tools/get_deps.py FAMILY`` where FAMILY is your MCU family (e.g., stm32f4, rp2040). This downloads MCU-specific drivers and libraries. + +**Q: Can I use my own build system instead of Make/CMake?** + +Yes, just add all ``.c`` files from ``src/`` to your project and configure include paths. See :doc:`getting_started` for details. + +**Q: Error: "tusb_config.h: No such file or directory"** + +This is a very common issue. You need to create ``tusb_config.h`` in your project and ensure it's in your include path. The file must define ``CFG_TUSB_MCU`` and ``CFG_TUSB_OS`` at minimum. Copy from ``examples/device/*/tusb_config.h`` as a starting point. + +**Q: RP2040 + pico-sdk ignores my tusb_config.h settings** + +The pico-sdk build system can override ``tusb_config.h`` settings. The ``CFG_TUSB_OS`` setting is often ignored because pico-sdk sets it to ``OPT_OS_PICO`` internally. Use pico-sdk specific configuration methods or modify the CMake configuration. + +**Q: "multiple definition of dcd_..." errors with STM32** + +This happens when multiple USB drivers are included. Ensure you're only including the correct portable driver for your STM32 family. Check that ``CFG_TUSB_MCU`` is set correctly and you don't have conflicting source files. + +Device Development +================== + +**Q: My USB device isn't recognized by the host** + +Common causes: +- Invalid USB descriptors - validate with ``LOG=2`` build +- ``tud_task()`` not called regularly in main loop +- Incorrect ``tusb_config.h`` settings +- USB cable doesn't support data (charging-only cable) + +**Q: Windows shows "Device Descriptor Request Failed"** + +This typically indicates: +- Malformed device descriptor +- USB timing issues (check crystal/clock configuration) +- Power supply problems during enumeration +- Conflicting devices on the same USB hub + +**Q: How do I implement a custom USB class?** + +Use the vendor class interface (``CFG_TUD_VENDOR``) or implement a custom class driver. See ``src/class/vendor/`` for examples. + +**Q: Can I have multiple configurations or interfaces?** + +Yes, TinyUSB supports multiple configurations and composite devices. Modify the descriptors in ``usb_descriptors.c`` accordingly. + +**Q: How do I change Vendor ID/Product ID?** + +Edit the device descriptor in ``usb_descriptors.c``. For production, obtain your own VID from USB-IF or use one from your silicon vendor. + +**Q: Device works alone but fails when connected through USB hub** + +This is a known issue where some devices interfere with each other when connected to the same hub. Try: +- Using different USB hubs +- Connecting devices to separate USB ports +- Checking for power supply issues with the hub + +Host Development +================ + +**Q: Why doesn't my host application detect any devices?** + +Check: +- Power supply - host mode requires more power than device mode +- USB connector type - use USB-A for host applications +- Board supports host mode on the selected port +- Enable logging with ``LOG=2`` to see enumeration details + +**Q: Can I connect multiple devices simultaneously?** + +Yes, through a USB hub. TinyUSB supports multi-level hubs and multiple device connections. + +**Q: Does TinyUSB support USB 3.0?** + +No, TinyUSB currently supports USB 2.0 and earlier. USB 3.0 devices typically work in USB 2.0 compatibility mode. + +Configuration and Features +========================== + +**Q: How do I enable/disable specific USB classes?** + +Edit ``tusb_config.h`` and set the corresponding ``CFG_TUD_*`` or ``CFG_TUH_*`` macros to 1 (enable) or 0 (disable). + +**Q: Can I use both device and host modes simultaneously?** + +Yes, with dual-role/OTG capable hardware. See ``examples/dual/`` for implementation examples. + +**Q: How do I optimize for code size?** + +- Disable unused classes in ``tusb_config.h`` +- Use ``CFG_TUSB_DEBUG = 0`` for release builds +- Compile with ``-Os`` optimization +- Consider using only required endpoints/interfaces + +**Q: Does TinyUSB support low power/suspend modes?** + +Yes, TinyUSB handles USB suspend/resume. Implement ``tud_suspend_cb()`` and ``tud_resume_cb()`` for custom power management. + +**Q: What CFG_TUSB_MCU should I use for x86/PC platforms?** + +For PC/motherboard applications, there's no standard MCU option. You may need to use a generic option or modify TinyUSB for your specific use case. Consider using libusb or other PC-specific USB libraries instead. + +**Q: RP2040 FreeRTOS configuration issues** + +The RP2040 pico-sdk has specific requirements for FreeRTOS integration. The ``CFG_TUSB_OS`` setting may be overridden by the SDK. Use pico-sdk specific configuration methods and ensure proper task stack sizes for the USB task. + +Debugging and Troubleshooting +============================= + +**Q: How do I debug USB communication issues?** + +1. Enable logging: build with ``LOG=2`` +2. Use ``LOGGER=rtt`` or ``LOGGER=swo`` for high-speed logging +3. Use USB protocol analyzers for detailed traffic analysis +4. Check with different host systems (Windows/Linux/macOS) + +**Q: My application crashes or hard faults** + +Common causes: +- Stack overflow - increase stack size in linker script +- Incorrect interrupt configuration +- Buffer overruns in USB callbacks +- Build with ``DEBUG=1`` and use a debugger + +**Q: Performance is poor or USB transfers are slow** + +- Ensure ``tud_task()``/``tuh_task()`` called frequently (< 1ms intervals) +- Use DMA for USB transfers if supported by your MCU +- Optimize endpoint buffer sizes +- Consider using high-speed USB if available + +**Q: Some USB devices don't work with my host application** + +- Not all devices follow USB standards perfectly +- Some may need device-specific handling +- Composite devices may have partial support +- Check device descriptors and implement custom drivers if needed + +**Q: ESP32-S3 USB host/device issues** + +ESP32-S3 has specific USB implementation challenges: +- Ensure proper USB pin configuration +- Check power supply requirements for host mode +- Some features may be limited compared to other MCUs +- Use ESP32-S3 specific examples and documentation diff --git a/docs/getting_started.rst b/docs/getting_started.rst new file mode 100644 index 000000000..0c3fcec80 --- /dev/null +++ b/docs/getting_started.rst @@ -0,0 +1,188 @@ +*************** +Getting Started +*************** + +This guide will get you up and running with TinyUSB quickly with working examples. + +Project Structure +==================== + +TinyUSB separates example applications from board-specific hardware configurations: + +* **Example applications**: Located in `examples/ <https://github.com/hathach/tinyusb/tree/master/examples/>`_ directories +* **Board Support Packages (BSP)**: Located in ``hw/bsp/FAMILY/boards/BOARD_NAME/`` with hardware abstraction including pin mappings, clock settings, and linker scripts +* **Build system**: Located in `examples/build_system/ <https://github.com/hathach/tinyusb/tree/master/examples/build_system>`_ which supports both Make and CMake. Though some MCU families such as espressif or rp2040 only support cmake + +For example, stm32h743eval is located in `hw/bsp/stm32h7/boards/stm32h743eval <https://github.com/hathach/tinyusb/tree/master/hw/bsp/stm32h7/boards/stm32h743eval>`_ where ``FAMILY=stm32h7`` and ``BOARD=stm32h743eval``. When you build with ``BOARD=stm32h743eval``, the build system automatically finds the corresponding BSP using the FAMILY. + +For guidance on integrating TinyUSB into your own firmware (configuration, descriptors, initialization, and callback workflow), see :doc:`integration`. + +Quick Start Examples +==================== + +The fastest way to understand TinyUSB is to see it working. These examples demonstrate core functionality and can be built immediately. + +We'll assume you are using the **STM32H743 Eval board** (BOARD=stm32h743eval) under the **stm32h7** family. For other boards, see ``Board Support Packages`` below. + +Get the Code +------------ + +.. code-block:: bash + + $ git clone https://github.com/hathach/tinyusb tinyusb + $ cd tinyusb + $ python tools/get_deps.py -b stm32h743eval # or python tools/get_deps.py stm32h7 + +.. note:: + For rp2040 `pico-sdk <https://github.com/raspberrypi/pico-sdk>`_ or `esp-idf <https://github.com/espressif/esp-idf>`_ for Espressif targets are required; install them per vendor instructions. + +Simple Device Example +--------------------- + +The `cdc_msc <https://github.com/hathach/tinyusb/tree/master/examples/device/cdc_msc>`_ example creates a USB device with both a virtual serial port (CDC) and mass storage (MSC). + +**What it does:** + +* Appears as a serial port that echoes back any text you send +* Appears as a small USB drive with a README.TXT file +* Blinks an LED to show activity + +**Build and run with CMake:** + +.. code-block:: bash + + $ cd examples/device/cdc_msc + $ cmake -DBOARD=stm32h743eval -B build # add "-G Ninja" to use Ninja build + $ cmake --build build + # cmake --build build --target cdc_msc-jlink + +.. tip:: + Flashed/Debugger can be selected with --target ``-jlink``, ``-stlink`` or ``-openocd`` depending on your board. Use ``--target help`` to list all supported targets. + +**Build and run with Make:** + +.. code-block:: bash + + $ cd examples/device/cdc_msc + $ make BOARD=stm32h743eval all + $ make BOARD=stm32h743eval flash-jlink + +.. tip:: + Flashed/Debugger can be selected with target ``flash-jlink``, ``flash-stlink`` or ``flash-openocd`` depending on your board. + +Connect the device to your computer and you'll see both a new serial port and a small USB drive appear. + +Simple Host Example +------------------- + +The `cdc_msc_hid <https://github.com/hathach/tinyusb/tree/master/examples/host/cdc_msc_hid>`_ example creates a USB host that can connect to USB devices with CDC, MSC, or HID interfaces. + +**What it does:** + +* Detects and enumerates connected USB devices +* Communicates with CDC devices (like USB-to-serial adapters) +* Reads from MSC devices (like USB drives) +* Receives input from HID devices (like keyboards and mice) + +**Build and run with CMake:** + +.. code-block:: bash + + $ cd examples/host/cdc_msc_hid + $ cmake -DBOARD=stm32h743eval -B build + $ cmake --build build + +**Build and run with Make:** + +.. code-block:: bash + + $ cd examples/host/cdc_msc_hid + $ make BOARD=stm32h743eval all + $ make BOARD=stm32h743eval flash-jlink + +Connect USB devices to see enumeration messages and device-specific interactions in the serial output. + +Additional Build Options +------------------------ + +Debug and Logging +^^^^^^^^^^^^^^^^^ + +TinyUSB built-in logging can be enabled by setting `CFG_TUSB_DEBUG` which is done by passing ``LOG=level``. The higher the level, the more verbose the logging. + +In addition to traditional hw uart as default, logging with debugger such as `Segger RTT <https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/>`_ (10x faster) is also supported with `LOGGER=rtt` option. + +.. code-block:: bash + + $ cmake -B build -DBOARD=stm32h743eval -DLOG=2 # logging level 2 with uart + $ cmake -B build -DBOARD=stm32h743eval -DLOG=2 -DLOGGER=rtt # logging level 2 with RTT + +.. code-block:: bash + + $ make BOARD=stm32h743eval LOG=2 all # logging level 2 with uart + $ make BOARD=stm32h743eval LOG=2 LOGGER=rtt all # logging level 2 with RTT + +RootHub Port Selection +^^^^^^^^^^^^^^^^^^^^^^ + +Some boards support multiple usb controllers (roothub ports), by default one rh port is used as device, another as host in ``board.mk/board.cmake``. This can be overridden with option ``RHPORT_DEVICE=n`` or ``RHPORT_HOST=n`` To choose another port. For example to select the HS port of a STM32F746Disco board, use: + +.. code-block:: bash + + $ cmake -B build -DBOARD=stm32h743eval -DRHPORT_DEVICE=1 # select roothub port 1 as device + +.. code-block:: bash + + $ make BOARD=stm32h743eval RHPORT_DEVICE=1 all # select roothub port 1 as device + +RootHub 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 ``RHPORT_DEVICE_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` or ``RHPORT_HOST_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` e.g To force operating speed + +.. code-block:: bash + + $ cmake -B build -DBOARD=stm32h743eval -DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED + +.. code-block:: bash + + $ make BOARD=stm32h743eval RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED all + + +IAR Embedded Workbench +---------------------- + +For IAR users, project connection files are available. Import `tools/iar_template.ipcf <https://github.com/hathach/tinyusb/tree/master/tools/iar_template.ipcf>`_ or use native CMake support (IAR 9.50.1+). See `tools/iar_gen.py <https://github.com/hathach/tinyusb/tree/master/tools/iar_gen.py>`_ for automated project generation. + + +Common Issues and Solutions +--------------------------- + +**Build Errors** + +* **"arm-none-eabi-gcc: command not found"**: Install ARM GCC toolchain: ``sudo apt-get install gcc-arm-none-eabi`` +* **"Board 'X' not found"**: Check the available boards in ``hw/bsp/FAMILY/boards/`` or run ``python tools/build.py -l`` +* **Missing dependencies**: Run ``python tools/get_deps.py FAMILY`` where FAMILY matches your board or ``python tools/get_deps.py -b BOARD`` + +**Runtime Issues** + +* **Device not recognized**: Check USB descriptors implementation and ``tusb_config.h`` settings +* **Enumeration failure**: Enable logging with ``LOG=2`` and check for USB protocol errors +* **Hard faults/crashes**: Verify interrupt handler setup and stack size allocation + +**Linux Permissions** + +Some examples require udev permissions to access USB devices: + +.. code-block:: bash + + $ cp `examples/device/99-tinyusb.rules <https://github.com/hathach/tinyusb/tree/master/examples/device/99-tinyusb.rules>`_ /etc/udev/rules.d/ + $ sudo udevadm control --reload-rules && sudo udevadm trigger + +Next Steps +========== + +* Check :doc:`integration` for integrating TinyUSB into your own firmware +* Check :doc:`reference/boards` for board-specific information +* Explore more examples in `examples/device/ <https://github.com/hathach/tinyusb/tree/master/examples/device>`_ and `examples/host/ <https://github.com/hathach/tinyusb/tree/master/examples/host>`_ directories +* Read :doc:`reference/usb_concepts` to understand USB fundamentals diff --git a/docs/index.rst b/docs/index.rst index c1c8e4d99..39d30a038 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,14 +1,21 @@ -:hide-toc: - .. include:: ../README_processed.rst .. toctree:: - :caption: Index - :hidden: + :maxdepth: 2 + :caption: Information + + getting_started + integration + porting + reference/index + faq + troubleshooting + +.. toctree:: + :maxdepth: 1 + :caption: Project Info - Info <info/index> - Reference <reference/index> - Contributing <contributing/index> + info/index .. toctree:: :caption: External Links diff --git a/docs/info/changelog.rst b/docs/info/changelog.rst index 6024bb9e3..df23ce7d8 100644 --- a/docs/info/changelog.rst +++ b/docs/info/changelog.rst @@ -2,6 +2,313 @@ Changelog ********* +0.20.0 +====== + +*November 19, 2024* + +General +------- + +- New MCUs and Boards: + + - Add STM32U3 device support (adjusted from STM32U0) + - Add nRF54H20 support with initial board configuration + - Rename board names: pca10056→nrf52840dk, pca10059→nrf52840dongle, pca10095→nrf5340dk + - Improve CMake: Move startup and linker files from board target to executable. Enhance target warning flags and fix various build warnings + +- Code Quality and Static Analysis: + + - Add PVS-Studio static analysis to CI + - Add SonarQube scan support + - Add IAR C-Stat analysis capability + - Add ``.clang-format`` for consistent code formatting + - Fix numerous alerts and warnings found by static analysis tools + +- Documentation: + + - Improve Getting Started documentation structure and flow + - Add naming conventions and buffer handling documentation + +Controller Driver (DCD & HCD) +----------------------------- + +- DWC2 + + - Fix incorrect handling of Zero-Length Packets (ZLP) in the DWC2 driver when receiving data (OUT transfers) + - Improve EP0 multi-packet logic + - Support EP0 with max packet size = 8 + - For IN endpoint, write initial packet directly to FIFO and only use TXFE interrupt for subsequent packets + - Fix ISO with bInterval > 2 using incomplete IN interrupt handling. + - Fix compile issues when enabling both host and device + - Clear pending suspend interrupt after USB reset (enum end) + - Improve host closing endpoint and channel handling when device is unplugged + +- FSDEV (STM32) + + - Fix AT32 USB interrupt remapping in ``dcd_int_enable()`` + +- OHCI + + - Add initial LPC55 OHCI support + - Improve data cache support + +Device Stack +------------ + +- USBD Core + + - Support configurable EP0 buffer size CFG_TUD_ENDPOINT0_BUFSIZE + - Make dcd_edpt_iso_alloc/activate as default API for ISO endpoint + +- Audio + + - Add UAC1 support + - Implement RX FIFO threshold adjustment with `tud_audio_get/set_ep_in_fifo_threshold()` + +- CDC + + - Migrate to endpoint stream API + +- HID + + - Fix HID stylus descriptor + +- MIDI + + - Migrate to endpoint stream API + - Add ``tud_midi_n_packet_write_n()`` and ``tud_midi_n_packet_read_n()`` + +- MTP + + - Fix incorrect MTP xact_len calculation + +- Video + + - Add bufferless operation callback for dynamic frame generation with tud_video_prepare_payload_cb() + +Host Stack +---------- + +No changes + +0.19.0 +====== + +General +------- + +- New MCUs and Boards: + + - Add ESP32-H4, ESP32-C5, ESP32-C61 support + - Add STM32U0, STM32WBA, STM32N6 + - Add AT32F405, AT32F403A, AT32F415, AT32F423 support + - Add CH32V305 support and CH32V20x USB host support + - Add MCXA156 SDK 2.16 support and FRDM-MCXA156 board + +API Changes +----------- + +- Core APIs + + - Add weak callbacks with new syntax for better compiler compatibility + - Add ``tusb_deinit()`` to cleanup stack + - Add time functions: ``tusb_time_millis_api()`` and ``tusb_time_delay_ms_api()`` + - Add ``osal_critical`` APIs for critical section handling + - Introduce ``xfer_isr()`` callback for ISO transfer optimization in device classes + +- Device APIs + + - CDC: Add notification support ``tud_cdc_configure()``, ``tud_cdc_n_notify_uart_state()``, + ``tud_cdc_n_notify_conn_speed_change()``, ``tud_cdc_notify_complete_cb()`` + - MSC: Add ``tud_msc_inquiry2_cb()`` with bufsize parameter, update ``tud_msc_async_io_done()`` + with ``in_isr`` parameter + - Audio: Add ``tud_audio_n_mounted()`` and various FIFO access functions + - MTP: Add ``tud_mtp_mounted()``, ``tud_mtp_data_send()``, ``tud_mtp_data_receive()``, + ``tud_mtp_response_send()``, ``tud_mtp_event_send()`` + +- Host APIs + + - Core: Add ``tuh_edpt_close()``, ``tuh_address_set()``, ``tuh_descriptor_get_device_local()``, + ``tuh_descriptor_get_string_langid()``, ``tuh_connected()``, ``tuh_bus_info_get()`` + - Add enumeration callbacks: ``tuh_enum_descriptor_device_cb()``, + ``tuh_enum_descriptor_configuration_cb()`` + - CDC: Add ``tuh_cdc_get_control_line_state_local()``, ``tuh_cdc_get/set_dtr/rts()``, + ``tuh_cdc_connect/disconnect()`` and sync versions of all control APIs + - MIDI: Add ``tuh_midi_itf_get_info()``, ``tuh_midi_packet_read_n()``, + ``tuh_midi_packet_write_n()``, ``tuh_midi_read_available()``, ``tuh_midi_write_flush()``, + ``tuh_midi_descriptor_cb()`` + +Controller Driver (DCD & HCD) +----------------------------- + +- DWC2 + + - Support DWC2 v4.30a with improved reset procedure + - Fix core reset: wait for AHB idle before reset + - Add STM32 DWC2 data cache support with proper alignment + - Host improvements: + - Fix disconnect detection and SOF flag handling + - Fix HFIR timing off-by-one error + - Retry IN token immediately for bInterval=1 + - Proper attach debouncing (200ms) + - Fix all retry intervals + - Resume OUT transfer when PING ACKed + - Fix enumeration racing conditions + - Refactor bitfields for better code generation + +- FSDEV (STM32) + + - Fix AT32 compile issues after single-buffered endpoint changes + - Add configurable single-buffered isochronous endpoints + - Fix STM32H7 recurrent suspend ISR + - Fix STM32L4 GPIOD clock enable for variants without GPIOD + - Fix STM32 PHYC PLL stability wait + - Improve PMA size handling for STM32U0 + +- EHCI + + - Fix removed QHD getting reused + - Fix NXP USBPHY disconnection detection + +- Chipidea/NXP + + - Fix race condition with spinlock + - Improve iMXRT support: fix build, disable BOARD_ConfigMPU, fix attach debouncing on port1 highspeed + - Fix iMXRT1064 and add to HIL test pool + +- MAX3421E + + - Use spinlock for thread safety instead of atomic flag + - Implement ``hcd_edpt_close()`` + +- RP2040 + + - Fix audio ISO transfer: reset state before notifying stack + - Fix CMake RTOS cache variable + - Abort transfer if active in ``iso_activate()`` + +- SAMD + + - Add host controller driver support + +Device Stack +------------ + +- USBD Core + + - Introduce ``xfer_isr()`` callback for interrupt-time transfer handling + - Add ``usbd_edpt_xfer_fifo()`` stub + - Revert endpoint busy/claim status if ``xfer_isr()`` defers to ``xfer_cb()`` + +- Audio + + - Major simplification of UAC driver and alt settings management + - Move ISO transfers into ``xfer_isr()`` for better performance + - Remove FIFO mutex (single producer/consumer optimization) + - Add implicit feedback support for data IN endpoints + - Fix alignment issues + - Update buffer macros with cache line size alignment + +- CDC + + - Add notification support: ``CFG_TUD_CDC_NOTIFY``, ``tud_cdc_n_notify_conn_speed_change()``, ``tud_cdc_notify_complete_cb()`` + - Reduce default bInterval from 16ms to 1ms for better responsiveness + - Rename ``tud_cdc_configure_fifo()`` to ``tud_cdc_configure()`` and add ``tx_overwritable_if_not_connected`` option + - Fix web serial robustness with major overhaul and logic cleanup + +- HID + + - Add Usage Page and Table for Power Devices (0x84 - 0x85) + - Fix HID descriptor parser variable size and 4-byte item handling + - Add consumer page configurations + +- MIDI + + - Fix MIDI interface descriptor handling after audio streaming interface + - Skip RX data with all zeroes + +- MSC + + - Add async I/O support for MSC using ``tud_msc_async_io_done()`` + - Add ``tud_msc_inquiry2_cb()`` with bufsize for full inquiry response + +- MTP + + - Add new Media Transfer Protocol (MTP) device class driver + - Support MTP operations: GetDeviceInfo, SendObjectInfo, SendObject + - Add MTP event support with ``tud_mtp_event_send()`` + - Implement filesystem example with callbacks + - Add hardware-in-the-loop testing support + +- NCM + + - Add USB NCM link state control support + - Fix DHCP offer/ACK destination + +- USBTMC + + - Add vendor-specific message support + +- Vendor + + - Fix vendor device reset and open issues + - Fix descriptor parsing for ``CFG_TUD_VENDOR > 1`` + - Fix vendor FIFO argument calculation + +Host Stack +---------- + +- USBH Core + + - Major enumeration improvements: + - Fix enumeration racing conditions + - Add proper attach debouncing with hub/rootport handling (200ms delay) + - Reduce ``ENUM_DEBOUNCING_DELAY_MS`` to 200ms + - Always get language ID, manufacturer, product, and serial strings during enumeration + - Always get first 2 bytes of string descriptor to determine length (prevents buffer overflow) + - Support devices with multiple configurations + - Add ``tuh_enum_descriptor_device_cb()`` and ``tuh_enum_descriptor_configuration_cb()`` callbacks + - Add ``tuh_descriptor_get_string_langid()`` API + - Hub improvements: + - Check status before getting first device descriptor + - Properly handle port status and change detection + - Queue status endpoint for detach/remove events + - Fix hub status change endpoint handling + - Fix endpoint management: + - ``hcd_edpt_open()`` returns false if endpoint already opened + - Add ``hcd_edpt_close()`` implementation + - Abort pending transfers on close + - Add roothub debouncing flag to ignore attach/remove during debouncing + - Move address setting and bus info management to separate structures + - Force removed devices in same bus info before setting address + +- CDC Serial Host + + - Major refactor to generalize CDC serial drivers (FTDI, CP210x, CH34x, PL2303, ACM) + - Add explicit ``sync()`` API with ``TU_API_SYNC()`` returning ``tusb_xfer_result_t`` + - Rename ``tuh_cdc_get_local_line_coding()`` to ``tuh_cdc_get_line_coding_local()`` + - Add ``tuh_cdc_get_control_line_state_local()`` + - Implement ``tuh_cdc_get/set_dtr/rts()`` as inline functions + +- MIDI Host + + - Major API changes: + - Rename ``tuh_midi_stream_flush()`` to ``tuh_midi_write_flush()`` + - Add ``tuh_midi_packet_read_n()`` and ``tuh_midi_packet_write_n()`` + - Add ``CFG_TUH_MIDI_STREAM_API`` to opt out of stream API + - Change API to use index instead of device address (supports multiple MIDI per device) + - Rename ``tuh_midi_get_num_rx/tx_cables()`` to ``tuh_midi_get_rx/tx_cable_count()`` + - Add ``tuh_midi_descriptor_cb()`` and ``tuh_midi_itf_get_info()`` + +- MSC Host + + - Continue async I/O improvements + +- HID Host + + - Fix version string to actually show version + 0.18.0 ====== @@ -34,6 +341,7 @@ Controller Driver (DCD & HCD) ----------------------------- - DWC2 + - Add DMA support for both device and host controller - Add host driver support including: full/high speed, control/bulk/interrupt (CBI) transfer, split CBI i.e FS/LS attached via highspeed hub, hub support @@ -503,6 +811,7 @@ Controller Driver (DCD & HCD) ----------------------------- - [DWC2] Generalize synopsys dwc2 with synopsys/dwc2 which support both FS and HS phy (UTMI and ULPI) for various MCUs. + - Broadcom 28/27xx on raspberrypi SBC - Silicon Labs EFM32 - Espressif ESP32 Sx @@ -724,6 +1033,7 @@ HID - Add more hid keys constant from 0x6B to 0xA4 - [Breaking] rename API + - ``HID_PROTOCOL_NONE/KEYBOARD/MOUSE`` to ``HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE`` - ``tud_hid_boot_mode()`` to ``tud_hid_get_protocol()`` - ``tud_hid_boot_mode_cb()`` to ``tud_hid_set_protocol_cb()`` @@ -733,6 +1043,7 @@ MIDI - Fix MIDI buffer overflow issue - [Breaking] rename API + - Rename ``tud_midi_read()`` to ``tud_midi_stream_read()`` - Rename ``tud_midi_write()`` to ``tud_midi_stream_write()`` - Rename ``tud_midi_receive()`` to ``tud_midi_packet_read()`` @@ -883,15 +1194,19 @@ Device Controller Driver - Use ``dcd_event_bus_reset()`` with link speed to replace bus_signal - ESP32-S2: + - Add bus suspend and wakeup support - SAMD21: + - Fix (walkaround) samd21 setup_packet overflow by USB DMA - STM32 Synopsys: + - Rework USB FIFO allocation scheme and allow RX FIFO size reduction - Sony CXD56 + - Update Update Spresense SDK to 2.0.2 - Fix dcd issues with setup packets - Correct EP number for cdc_msc example @@ -908,19 +1223,24 @@ USB Device **Class Driver** - CDC + - Allow to transmit data, even if the host does not support control line states i.e set DTR - HID + - change default ``CFG_TUD_HID_EP_BUFSIZE`` from 16 to 64 - MIDI + - Fix midi sysex sending bug - MSC + - Invoke only scsi complete callback after status transaction is complete. - Fix ``scsi_mode_sense6_t`` padding, which cause IAR compiler internal error. - USBTMC + - Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu **Example** @@ -962,6 +1282,7 @@ Device Controller Driver - Enhance STM32 Synopsys - Support bus events disconnection/suspend/resume/wakeup + - Improve transfer performance with optimizing xfer and fifo size - Support Highspeed port (OTG_HS) with both internal and external PHY - Support multiple usb ports with rhport=1 is highspeed on selected MCUs e.g H743, F23. It is possible to have OTG_HS to run on Fullspeed PHY (e.g lacking external PHY) @@ -971,6 +1292,7 @@ Device Controller Driver - Support F105, F107 - Enhance STM32 fsdev + - Improve dcd fifo allocation - Fix ISTR race condition - Support remap USB IRQ on supported MCUs @@ -979,6 +1301,7 @@ Device Controller Driver - Enhance NUC 505: enhance set configure behavior - Enhance SAMD + - Fix race condition with setup packet - Add SAMD11 option ``OPT_MCU_SAMD11`` - Add SAME5x option ``OPT_MCU_SAME5X`` @@ -986,6 +1309,7 @@ Device Controller Driver - Fix SAMG control data toggle and stall race condition - Enhance nRF + - Fix hanged when ``tud_task()`` is called within critical section (disabled interrupt) - Fix disconnect bus event not submitted - Implement ISO transfer and ``dcd_edpt_close()`` @@ -1011,6 +1335,7 @@ USB Device - Improve USB Highspeed support with actual link speed detection with ``dcd_event_bus_reset()`` - Enhance class driver management + - ``usbd_driver_open()`` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver - Add application implemented class driver via ``usbd_app_driver_get_cb()`` - IAD is handled to assign driver id @@ -1027,11 +1352,13 @@ USB Device - USBTMC: fix descriptors when INT EP is disabled - CDC: + - Send zero length packet for end of data when needed - Add ``tud_cdc_tx_complete_cb()`` callback - Change ``tud_cdc_n_write_flush()`` return number of bytes forced to transfer, and flush when writing enough data to fifo - MIDI: + - Add packet interface - Add multiple jack descriptors - Fix MIDI driver for sysex @@ -1039,12 +1366,14 @@ USB Device - DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request - Rename some configure macro to make it clear that those are used directly for endpoint transfer + - ``CFG_TUD_HID_BUFSIZE`` to ``CFG_TUD_HID_EP_BUFSIZE`` - ``CFG_TUD_CDC_EPSIZE`` to ``CFG_TUD_CDC_EP_BUFSIZE`` - ``CFG_TUD_MSC_BUFSIZE`` to ``CFG_TUD_MSC_EP_BUFSIZE`` - ``CFG_TUD_MIDI_EPSIZE`` to ``CFG_TUD_MIDI_EP_BUFSIZE`` - HID: + - Fix gamepad template descriptor - Add multiple HID interface API - Add extra comma to HID_REPORT_ID @@ -1066,6 +1395,7 @@ Examples - Add new ``hid_multiple_interface`` - Enhance ``net_lwip_webserver`` example + - Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both) - Update lwip to STABLE-2_1_2_RELEASE for ``net_lwip_webserver`` diff --git a/docs/info/code_of_conduct.rst b/docs/info/code_of_conduct.rst new file mode 100644 index 000000000..2d70708d4 --- /dev/null +++ b/docs/info/code_of_conduct.rst @@ -0,0 +1 @@ +.. include:: ../../CODE_OF_CONDUCT.rst diff --git a/docs/info/index.rst b/docs/info/index.rst index a636f37dc..b6d30b432 100644 --- a/docs/info/index.rst +++ b/docs/info/index.rst @@ -10,3 +10,4 @@ Index changelog contributors + code_of_conduct diff --git a/docs/integration.rst b/docs/integration.rst new file mode 100644 index 000000000..f7c5be2ca --- /dev/null +++ b/docs/integration.rst @@ -0,0 +1,93 @@ +******************* +Integrating TinyUSB +******************* + +Once you've seen TinyUSB working in the examples, use this guide to wire the stack into your own firmware. + +Integration Steps +================= + +1. **Get TinyUSB**: Copy this repository or add it as a git submodule to your project at ``your_project/tinyusb``. +2. **Add source files**: Add every ``.c`` file from ``tinyusb/src/`` to your project build system. + +.. note:: + Only supported dcd/hcd drivers for your CPU sources under ``tinyusb/src/portable/vendor/usbip/`` are needed. Add + +3. **Configure TinyUSB**: Create ``tusb_config.h`` with macros such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS``, and class enable flags. Start from any example's ``tusb_config.h`` and tweak. +4. **Configure include paths**: Add ``your_project/tinyusb/src`` (and the folder holding ``tusb_config.h``) to your include paths. +5. **Implement USB descriptors**: For device stack, implement the ``tud_descriptor_*_cb()`` callbacks (device) or host descriptor helpers that match your product. +6. **Initialize TinyUSB**: Call ``tusb_init()`` once the clocks/peripherals are ready. Pass ``tusb_rhport_init_t`` if you need per-port settings. +7. **Handle interrupts**: From the USB ISR call ``tusb_int_handler(rhport, true)`` so the stack can process events. +8. **Run USB tasks**: Call ``tud_task()`` (device) or ``tuh_task()`` (host) regularly from the main loop, RTOS task. +9. **Implement class callbacks**: Provide the callbacks for the classes you enabled (e.g., ``tud_cdc_rx_cb()``, ``tuh_msc_mount_cb()``). + +Minimal Example +=============== + +.. code-block:: c + + #include "tusb.h" + + int main(void) { + board_init(); // Your board initialization + + // Init device stack on roothub port 0 for highspeed device + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_HIGH + }; + tusb_init(0, &dev_init); + + // init host stack on roothub port 1 for fullspeed host + tusb_rhport_init_t host_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_FULL + }; + tusb_init(1, &host_init); + + while (1) { + tud_task(); // device task + tuh_task(); // host task + + app_task(); // Your application logic + } + } + + void USB0_IRQHandler(void) { + // forward interrupt port 0 to TinyUSB stack + tusb_int_handler(0, true); + } + + void USB1_IRQHandler(void) { + // forward interrupt port 1 to TinyUSB stack + tusb_int_handler(1, true); + } + +.. note:: + Unlike many libraries, TinyUSB callbacks don't need to be registered. Implement functions with the prescribed names (for example ``tud_cdc_rx_cb()``) and the stack will invoke them automatically. + +.. note:: + Naming follows ``tud_*`` for device APIs and ``tuh_*`` for host APIs. Refer to :doc:`reference/glossary` for a summary of the prefixes and callback naming rules. + + +STM32CubeIDE Integration +======================== + +To integrate TinyUSB device stack with STM32CubeIDE + +1. In STM32CubeMX, enable USB_OTG_FS/HS under Connectivity, set to "Device_Only" mode +2. Enable the USB global interrupt in NVIC Settings +3. Add ``tusb.h`` include and call ``tusb_init()`` in main.c +4. Call ``tud_task()`` in your main loop +5. In the generated ``stm32xxx_it.c``, modify the USB IRQ handler to call ``tud_int_handler(0)`` + +.. code-block:: c + + void OTG_FS_IRQHandler(void) { + tud_int_handler(0); + } + +6. Create ``tusb_config.h`` and ``usb_descriptors.c`` files + +.. tip:: + STM32CubeIDE generated code conflicts with TinyUSB. Don't use STM32's built-in USB middleware (USB Device Library) when using TinyUSB. Disable USB code generation in STM32CubeMX and let TinyUSB handle all USB functionality. diff --git a/docs/contributing/porting.rst b/docs/porting.rst index c3076354c..9b60ec5a2 100644 --- a/docs/contributing/porting.rst +++ b/docs/porting.rst @@ -173,12 +173,22 @@ Also make sure to enable endpoint specific interrupts. ``dcd_edpt_close()`` """""""""""""""""""" +.. warning:: + This function is deprecated, ISO transfer should implement dcd_edpt_iso_alloc() and dcd_edpt_iso_activate() instead. + Close an endpoint. his function is used for implementing alternate settings. After calling this, the device should not respond to any packets directed towards this endpoint. When called, this function must abort any transfers in progress through this endpoint, before returning. Implementation is optional. Must be called from the USB task. Interrupts could be disabled or enabled during the call. +``dcd_edpt_iso_alloc() / dcd_edpt_iso_activate()`` +"""""""""""""""""""""""""""""""""""""""""""""""""" + +dcd_edpt_iso_alloc() is used to allocate largest buffer (for all alternative interfaces) for ISO endpoints when device is enumerated. This allows DCD to allocate necessary resources for ISO endpoints in the future. + +dcd_edpt_iso_activate() is used to activate or deactivate ISO endpoint when alternate setting is set with active max packet size. + ``dcd_edpt_xfer()`` """"""""""""""""""" diff --git a/docs/reference/architecture.rst b/docs/reference/architecture.rst new file mode 100644 index 000000000..70ea17ed4 --- /dev/null +++ b/docs/reference/architecture.rst @@ -0,0 +1,282 @@ +************ +Architecture +************ + +This document explains TinyUSB's internal architecture, design principles, and how different components work together. + +Design Principles +================= + +Memory Safety +------------- + +TinyUSB is designed for resource-constrained embedded systems with strict memory requirements: + +TinyUSB uses **no dynamic allocation** - all memory is statically allocated at compile time for predictability. All buffers have bounded, compile-time defined sizes to prevent overflow issues. The TinyUSB core avoids heap allocation, resulting in **predictable memory usage** where consumption is fully deterministic. + +Thread Safety +------------- + +TinyUSB achieves thread safety through a deferred interrupt model: + +- **ISR deferral**: USB interrupts are captured and deferred to task context +- **Single-threaded processing**: All USB protocol handling occurs in task context +- **Queue-based design**: Events are queued from ISR and processed in ``tud_task()`` +- **RTOS integration**: Proper semaphore/mutex usage for shared resources + +Portability +----------- + +The stack is designed to work across diverse microcontroller families: + +- **Hardware abstraction**: MCU-specific code isolated in portable drivers +- **OS abstraction**: RTOS dependencies isolated in OSAL layer +- **Modular design**: Features can be enabled/disabled at compile time +- **Standard compliance**: Strict adherence to USB specifications + +Core Architecture +================= + +Layer Structure +--------------- + +TinyUSB follows a layered architecture from hardware to application: + +.. figure:: ../assets/stack.svg + :width: 500px + :align: left + :alt: stackup + +.. raw:: html + + <div class="clear-both"></div> + +Component Overview +------------------ + +- **Application Layer**: Your main application code that uses TinyUSB APIs. +- **Class Drivers**: Implement specific USB device classes (CDC, HID, MSC, etc.) and handle class-specific requests. +- **Device/Host Core**: Implements USB protocol state machines, endpoint management, and core USB functionality. +- **OS Abstraction**: Provides threading primitives and synchronization for different RTOS environments. +- **Device/Host Controller Driver**: drivers that interface with MCU USB peripherals. Several MCUs may share a common driver. + +Device Stack Architecture +========================= + +This section is concerned with the **Device Stack**, i.e., the component of TinyUSB used in USB devices (that talk to a USB host). + +Core Components +--------------- + +**Device Controller Driver (DCD)**: +- MCU-specific USB device peripheral driver +- Handles endpoint configuration and data transfers +- Abstracts hardware differences between MCU families +- Located in ``src/portable/VENDOR/USBIP/`` + +**USB Device Core (USBD)**: +- Implements USB device state machine +- Handles standard USB requests (Chapter 9) +- Manages device configuration and enumeration +- Located in ``src/device/`` + +**Class Drivers**: +- Implement USB class specifications +- Handle class-specific requests and data transfer +- Provide application APIs +- Located in ``src/class/*/`` + +Data Flow +--------- + +**Control Transfers (Setup Requests)**: + +.. code-block:: none + + USB Bus → DCD → USBD Core → Class Driver → Application + ↓ + Standard requests handled in core + ↓ + Class-specific requests → Class Driver + +**Data Transfers**: + +.. code-block:: none + + Application → Class Driver → USBD Core → DCD → USB Bus + USB Bus → DCD → USBD Core → Class Driver → Application + +Event Processing +---------------- + +TinyUSB uses a deferred interrupt model for thread safety: + +1. **Interrupt Occurs**: USB hardware generates interrupt +2. **ISR Handler**: ``dcd_int_handler()`` captures event, minimal processing +3. **Event Queuing**: Events queued for later processing +4. **Task Processing**: ``tud_task()`` (called by application code) processes queued events +5. **Callback Execution**: Application callbacks executed in task context + +.. code-block:: none + + USB IRQ → ISR → Event Queue → tud_task() → Class Callbacks → Application + +Host Stack Architecture +======================= + +This section is concerned with the **Host Stack**, i.e., the component of TinyUSB used in USB hosts, managing connected USB devices. + +Core Components +--------------- + +**Host Controller Driver (HCD)**: +- MCU-specific USB host peripheral driver +- Manages USB pipes and data transfers +- Handles host controller hardware +- Located in ``src/portable/VENDOR/FAMILY/`` + +**USB Host Core (USBH)**: +- Implements USB host functionality +- Manages device enumeration and configuration +- Handles pipe management and scheduling +- Located in ``src/host/`` + +**Hub Driver**: +- Manages USB hub devices +- Handles port management and device detection +- Supports multi-level hub topologies +- Located in ``src/host/`` + +Device Enumeration +------------------ + +The host stack follows USB enumeration process: + +1. **Device Detection**: Hub or root hub detects device connection +2. **Reset and Address**: Reset device, assign unique address +3. **Descriptor Retrieval**: Get device, configuration, and class descriptors +4. **Driver Matching**: Find appropriate class driver for device +5. **Configuration**: Configure device and start communication +6. **Class Operation**: Normal class-specific communication + +.. code-block:: none + + Device Connect → Reset → Get Descriptors → Load Driver → Configure → Operate + +Class Architecture +================== + +Common Class Structure +---------------------- + +All USB classes follow a similar architecture: + +**Device Classes**: +- ``*_device.c``: Device-side implementation +- ``*_device.h``: Device API definitions +- Implement class-specific descriptors +- Handle class requests and data transfer + +**Host Classes**: +- ``*_host.c``: Host-side implementation +- ``*_host.h``: Host API definitions +- Manage connected devices of this class +- Provide application interface + +Class Driver Interface +---------------------- + +See ``usbd.c``. + +**Required Functions**: +- ``init()``: Initialize class driver +- ``reset()``: Reset class state +- ``open()``: Configure class endpoints +- ``control_xfer_cb()``: Handle control requests +- ``xfer_cb()``: Handle data transfer completion + +**Optional Functions**: +- ``close()``: Clean up class resources +- ``deinit()``: Deinitialize class driver +- ``sof()``: Start-of-frame processing +- ``xfer_isr()``: Called from USB ISR context on transfer completion. Data will get queued for ``xfer_cb()`` only if this returns ``false``. + +Descriptor Management +--------------------- + +Each class is responsible for: +- **Interface Descriptors**: Define class type and endpoints +- **Class-Specific Descriptors**: Additional class requirements +- **Endpoint Descriptors**: Define data transfer characteristics + +Memory Management +================= + +Static Allocation Model +----------------------- + +TinyUSB uses only static memory allocation; it allocates fixed-size endpoint buffers for each configured endpoint, static buffers for class-specific data handling, a fixed buffer dedicated to control transfers, and static event queues for deferred interrupt processing. + +Buffer Management +----------------- + +**Endpoint Buffers**: +- Allocated per endpoint at compile time +- Size defined by ``CFG_TUD_*_EP_BUFSIZE`` macros +- Used for USB data transfers + +**FIFO Buffers**: +- Ring buffers for streaming data +- Size defined by ``CFG_TUD_*_RX/TX_BUFSIZE`` macros +- Separate read/write pointers + +Threading Model +=============== + +Task-Based Design +----------------- + +TinyUSB uses a cooperative task model; it provides main tasks - ``tud_task()`` for device and ``tuh_task()`` for host operation. These tasks must be called regularly (typically less than 1ms intervals) to ensure all USB events are processed in task context, where application callbacks also execute. + +RTOS Integration +---------------- + +**Bare Metal**: +- Application calls ``tud_task()`` in main loop +- No threading primitives needed +- Simplest integration method + +**FreeRTOS**: +- USB task runs at high priority +- Semaphores used for synchronization +- Queue for inter-task communication + +**Other RTOS**: +- Similar patterns with RTOS-specific primitives +- OSAL layer abstracts RTOS differences + +Interrupt Handling +------------------ + +**Interrupt Service Routine**: +- Minimal processing in ISR +- Event capture and queuing only +- Quick return to avoid blocking + +**Deferred Processing**: +- All complex processing in task context +- Thread-safe access to data structures +- Application callbacks in known context + +Memory Usage Patterns +--------------------- + +**Flash Memory**: +- Core stack: 8-15KB depending on features +- Each class: 1-4KB additional +- Portable driver: 2-8KB depending on MCU + +**RAM Usage**: +- Core stack: 1-2KB +- Endpoint buffers: User configurable +- Class buffers: Depends on configuration diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 25542264c..12da5c90b 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -107,17 +107,20 @@ olimex_emz64 Olimex PIC32-EMZ64 pic32mz http olimex_hmz144 Olimex PIC32-HMZ144 pic32mz https://www.olimex.com/Products/PIC/Development/PIC32-HMZ144/open-source-hardware cynthion_d11 Great Scott Gadgets Cynthion samd11 https://greatscottgadgets.com/cynthion/ samd11_xplained SAMD11 Xplained Pro samd11 https://www.microchip.com/en-us/development-tool/ATSAMD11-XPRO -atsamd21_xpro SAMD21 Xplained Pro samd21 https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAMD21-XPRO -circuitplayground_express Adafruit Circuit Playground Express samd21 https://www.adafruit.com/product/3333 -curiosity_nano SAMD21 Curiosty Nano samd21 https://www.microchip.com/en-us/development-tool/dm320119 -cynthion_d21 Great Scott Gadgets Cynthion samd21 https://greatscottgadgets.com/cynthion/ -feather_m0_express Adafruit Feather M0 Express samd21 https://www.adafruit.com/product/3403 -itsybitsy_m0 Adafruit ItsyBitsy M0 samd21 https://www.adafruit.com/product/3727 -metro_m0_express Adafruit Metro M0 Express samd21 https://www.adafruit.com/product/3505 -qtpy Adafruit QT Py samd21 https://www.adafruit.com/product/4600 -seeeduino_xiao Seeeduino XIAO samd21 https://wiki.seeedstudio.com/Seeeduino-XIAO/ -sparkfun_samd21_mini_usb SparkFun SAMD21 Mini samd21 https://www.sparkfun.com/products/13664 -trinket_m0 Adafruit Trinket M0 samd21 https://www.adafruit.com/product/3500 +atsamd21_xpro SAMD21 Xplained Pro samd2x_l2x https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAMD21-XPRO +atsaml21_xpro SAML21 Xplained Pro samd2x_l2x https://www.microchip.com/en-us/development-tool/atsaml21-xpro-b +circuitplayground_express Adafruit Circuit Playground Express samd2x_l2x https://www.adafruit.com/product/3333 +curiosity_nano SAMD21 Curiosty Nano samd2x_l2x https://www.microchip.com/en-us/development-tool/dm320119 +cynthion_d21 Great Scott Gadgets Cynthion samd2x_l2x https://greatscottgadgets.com/cynthion/ +feather_m0_express Adafruit Feather M0 Express samd2x_l2x https://www.adafruit.com/product/3403 +itsybitsy_m0 Adafruit ItsyBitsy M0 samd2x_l2x https://www.adafruit.com/product/3727 +metro_m0_express Adafruit Metro M0 Express samd2x_l2x https://www.adafruit.com/product/3505 +qtpy Adafruit QT Py samd2x_l2x https://www.adafruit.com/product/4600 +saml22_feather SAML22 Feather samd2x_l2x https://github.com/joeycastillo/Feather-Projects/tree/main/SAML22%20Feather +seeeduino_xiao Seeeduino XIAO samd2x_l2x https://wiki.seeedstudio.com/Seeeduino-XIAO/ +sensorwatch_m0 SensorWatch samd2x_l2x https://github.com/joeycastillo/Sensor-Watch +sparkfun_samd21_mini_usb SparkFun SAMD21 Mini samd2x_l2x https://www.sparkfun.com/products/13664 +trinket_m0 Adafruit Trinket M0 samd2x_l2x https://www.adafruit.com/product/3500 d5035_01 D5035-01 samd5x_e5x https://github.com/RudolphRiedel/USB_CAN-FD feather_m4_express Adafruit Feather M4 Express samd5x_e5x https://www.adafruit.com/product/3857 itsybitsy_m4 Adafruit ItsyBitsy M4 samd5x_e5x https://www.adafruit.com/product/3800 @@ -125,10 +128,9 @@ metro_m4_express Adafruit Metro M4 Express samd5x_e5x http pybadge Adafruit PyBadge samd5x_e5x https://www.adafruit.com/product/4200 pyportal Adafruit PyPortal samd5x_e5x https://www.adafruit.com/product/4116 same54_xplained SAME54 Xplained Pro samd5x_e5x https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAME54-XPRO +same70_qmtech SAME70 QMTech same7x https://www.aliexpress.com/item/1005003173783268.html +same70_xplained SAME70 Xplained same7x https://www.microchip.com/en-us/development-tool/atsame70-xpld samg55_xplained SAMG55 Xplained Pro samg https://www.microchip.com/DevelopmentTools/ProductDetails/ATSAMG55-XPRO -atsaml21_xpro SAML21 Xplained Pro saml2x https://www.microchip.com/en-us/development-tool/atsaml21-xpro-b -saml22_feather SAML22 Feather saml2x https://github.com/joeycastillo/Feather-Projects/tree/main/SAML22%20Feather -sensorwatch_m0 SensorWatch saml2x https://github.com/joeycastillo/Sensor-Watch ========================= =================================== ========== ================================================================================= ====== MindMotion @@ -202,10 +204,11 @@ circuitplayground_bluefruit Adafruit Circuit Playground Bluefruit nrf ht feather_nrf52840_express Adafruit Feather nRF52840 Express nrf https://www.adafruit.com/product/4062 feather_nrf52840_sense Adafruit Feather nRF52840 Sense nrf https://www.adafruit.com/product/4516 itsybitsy_nrf52840 Adafruit ItsyBitsy nRF52840 Express nrf https://www.adafruit.com/product/4481 -pca10056 Nordic nRF52840DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK -pca10059 Nordic nRF52840 Dongle nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle -pca10095 Nordic nRF5340 DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK -pca10100 Nordic nRF52833 DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK +nrf52833dk Nordic nRF52833 DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK +nrf52840dk Nordic nRF52840DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK +nrf52840dongle Nordic nRF52840 Dongle nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle +nrf5340dk Nordic nRF5340 DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK +nrf54h20dk Nordic nRF54H20 DK nrf https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK =========================== ===================================== ======== ============================================================================== ====== Raspberry Pi @@ -294,10 +297,12 @@ stm32l052dap52 STM32 L052 DAP stm32l0 n/a stm32l0538disco STM32 L0538 Discovery stm32l0 https://www.st.com/en/evaluation-tools/32l0538discovery.html stm32l412nucleo STM32 L412 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l412kb.html stm32l476disco STM32 L476 Disco stm32l4 https://www.st.com/en/evaluation-tools/32l476gdiscovery.html +stm32l496nucleo STM32 L496 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l496ZG-P.html stm32l4p5nucleo STM32 L4P5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html stm32l4r5nucleo STM32 L4R5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html stm32n6570dk STM32 N6570-DK stm32n6 https://www.st.com/en/evaluation-tools/stm32n6570-dk.html stm32n657nucleo STM32 N657X0-Q Nucleo stm32n6 https://www.st.com/en/evaluation-tools/nucleo-n657x0-q.html +stm32u083cdk STM32U083C-DK Discovery Kit stm32u0 https://www.st.com/en/evaluation-tools/stm32u083c-dk.html b_u585i_iot2a STM32 B-U585i IOT2A Discovery kit stm32u5 https://www.st.com/en/evaluation-tools/b-u585i-iot02a.html stm32u545nucleo STM32 U545 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u545re-q.html stm32u575eval STM32 U575 Eval stm32u5 https://www.st.com/en/evaluation-tools/stm32u575i-ev.html diff --git a/docs/reference/concurrency.rst b/docs/reference/concurrency.rst index 776fa4b6d..99e7e7b70 100644 --- a/docs/reference/concurrency.rst +++ b/docs/reference/concurrency.rst @@ -3,17 +3,17 @@ Concurrency *********** The TinyUSB library is designed to operate on single-core MCUs with multi-threaded applications in mind. Interaction with interrupts is especially important to pay attention to. -It is compatible with optionally using a RTOS. +It is compatible with optionally using an RTOS. General ------- -When writing code, keep in mind that the OS (if using a RTOS) may swap out your code at any time. Also, your code can be preempted by an interrupt at any time. +When writing code, keep in mind that the OS (if using an RTOS) may swap out your code at any time. Also, your code can be preempted by an interrupt at any time. Application Code ---------------- -The USB core does not execute application callbacks while in an interrupt context. Calls to application code are from within the USB core task context. Note that the application core will call class drivers from within their own task. +The USB core does not execute application callbacks while in an interrupt context. Calls to application code are from within the USB core task context. Note that the application core will call class drivers from within its own task. Class Drivers ------------- @@ -38,5 +38,5 @@ Much of the processing of the USB stack is done in an interrupt context, and car In particular: -* Ensure that all memory-mapped registers (including packet memory) are marked as volatile. GCC's optimizer will even combine memory access (like two 16-bit to be a 32-bit) if you don't mark the pointers as volatile. On some architectures, this can use macros like _I , _O , or _IO. -* All defined global variables are marked as ``static``. +* Ensure that all memory-mapped registers (including packet memory) are marked as volatile. GCC's optimizer will even combine memory accesses (like two 16-bit to be a 32-bit) if you don't mark the pointers as volatile. On some architectures, this can use macros like _I , _O , or _IO. +* All defined global variables are marked as ``static``. diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index ca5c84151..de1603383 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -2,11 +2,11 @@ Dependencies ************ -MCU low-level peripheral driver and external libraries for building TinyUSB examples +MCU low-level peripheral drivers and external libraries for building TinyUSB examples -======================================== ================================================================ ======================================== ====================================================================================================================================================================================================================================================================================================================================================== +======================================== ================================================================ ======================================== ============================================================================================================================================================================================================================================================================================================================================================== Local Path Repo Commit Required by -======================================== ================================================================ ======================================== ====================================================================================================================================================================================================================================================================================================================================================== +======================================== ================================================================ ======================================== ============================================================================================================================================================================================================================================================================================================================================================== hw/mcu/allwinner https://github.com/hathach/allwinner_driver.git 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 fc100s hw/mcu/analog/msdk https://github.com/analogdevicesinc/msdk.git b20b398d3e5e2007594e54a74ba3d2a2e50ddd75 maxim hw/mcu/artery/at32f402_405 https://github.com/ArteryTek/AT32F402_405_Firmware_Library.git 4424515c2663e82438654e0947695295df2abdfe at32f402_405 @@ -22,8 +22,8 @@ hw/mcu/gd/nuclei-sdk https://github.com/Nuclei-Software/nuc hw/mcu/infineon/mtb-xmclib-cat3 https://github.com/Infineon/mtb-xmclib-cat3.git daf5500d03cba23e68c2f241c30af79cd9d63880 xmc4000 hw/mcu/microchip https://github.com/hathach/microchip_driver.git 9e8b37e307d8404033bb881623a113931e1edf27 sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg hw/mcu/mindmotion/mm32sdk https://github.com/hathach/mm32sdk.git b93e856211060ae825216c6a1d6aa347ec758843 mm32 -hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor/nrfx.git 7c47cc0a56ce44658e6da2458e86cd8783ccc4a2 nrf -hw/mcu/nuvoton https://github.com/majbthrd/nuc_driver.git 2204191ec76283371419fbcec207da02e1bc22fa nuc +hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor/nrfx.git 11f57e578c7feea13f21c79ea0efab2630ac68c7 nrf +hw/mcu/nuvoton https://github.com/majbthrd/nuc_driver.git 2204191ec76283371419fbcec207da02e1bc22fa nuc100_120 nuc121_125 nuc126 nuc505 hw/mcu/nxp/lpcopen https://github.com/hathach/nxp_lpcopen.git b41cf930e65c734d8ec6de04f1d57d46787c76ae lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 hw/mcu/nxp/mcux-sdk https://github.com/nxp-mcuxpresso/mcux-sdk a1bdae309a14ec95a4f64a96d3315a4f89c397c6 kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git 675543bcc9baa8170f868ab7ba316d418dbcf41f rp2040 @@ -31,6 +31,7 @@ hw/mcu/renesas/fsp https://github.com/renesas/fsp.git hw/mcu/renesas/rx https://github.com/kkitayam/rx_device.git 706b4e0cf485605c32351e2f90f5698267996023 rx hw/mcu/silabs/cmsis-dfp-efm32gg12b https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b.git f1c31b7887669cb230b3ea63f9b56769078960bc efm32 hw/mcu/sony/cxd56/spresense-exported-sdk https://github.com/sonydevworld/spresense-exported-sdk.git 2ec2a1538362696118dc3fdf56f33dacaf8f4067 spresense +hw/mcu/st/cmsis-device-u0 https://github.com/STMicroelectronics/cmsis-device-u0.git e3a627c6a5bc4eb2388e1885a95cc155e1672253 stm32u0 hw/mcu/st/cmsis-device-wba https://github.com/STMicroelectronics/cmsis-device-wba.git 647d8522e5fd15049e9a1cc30ed19d85e5911eaf stm32wba hw/mcu/st/cmsis_device_c0 https://github.com/STMicroelectronics/cmsis_device_c0.git 517611273f835ffe95318947647bc1408f69120d stm32c0 hw/mcu/st/cmsis_device_f0 https://github.com/STMicroelectronics/cmsis_device_f0.git cbb5da5d48b4b5f2efacdc2f033be30f9d29889f stm32f0 @@ -70,6 +71,7 @@ hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/ hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git 3e039bbf62f54bbd834d578185521cff80596efe stm32l4 hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 3340b9a597bcf75cc173345a90a74aa2a4a37510 stm32l5 hw/mcu/st/stm32n6xx_hal_driver https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git bc6c41f8f67d61b47af26695d0bf67762a000666 stm32n6 +hw/mcu/st/stm32u0xx_hal_driver https://github.com/STMicroelectronics/stm32u0xx-hal-driver.git cbfb5ac654256445237fd32b3587ac6a238d24f1 stm32u0 hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 2c5e2568fbdb1900a13ca3b2901fdd302cac3444 stm32u5 hw/mcu/st/stm32wbaxx_hal_driver https://github.com/STMicroelectronics/stm32wbaxx_hal_driver.git 9442fbb71f855ff2e64fbf662b7726beba511a24 stm32wba hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git d60dd46996876506f1d2e9abd6b1cc110c8004cd stm32wb @@ -78,10 +80,10 @@ hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.gi hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git c4c38f507e258a4e69b059ccc2dc27dde33cea1b ch32v20x hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v30x -lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u5 stm32wb sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg tm4c -lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git b0bbb0423b278ca632cfe1474eb227961d835fd2 ra +lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u0 stm32u5 stm32wb stm32wbasam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg tm4c +lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git 6f0a58d01aa9bd2feba212097f9afe7acd991d52 ra stm32n6 lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git cc0e0707c0c748713485b870bb980852b210877f all lib/lwip https://github.com/lwip-tcpip/lwip.git 159e31b689577dbf69cf0683bbaffbd71fa5ee10 all lib/sct_neopixel https://github.com/gsteiert/sct_neopixel.git e73e04ca63495672d955f9268e003cffe168fcd8 lpc55 tools/uf2 https://github.com/microsoft/uf2.git c594542b2faa01cc33a2b97c9fbebc38549df80a all -======================================== ================================================================ ======================================== ====================================================================================================================================================================================================================================================================================================================================================== +======================================== ================================================================ ======================================== ============================================================================================================================================================================================================================================================================================================================================================== diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst deleted file mode 100644 index bb9ff1cb4..000000000 --- a/docs/reference/getting_started.rst +++ /dev/null @@ -1,269 +0,0 @@ -*************** -Getting Started -*************** - -Add 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 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 -* Implement all enabled classes's callbacks. -* If you don't use any RTOSes at all, you need to continuously and/or periodically call ``tud_task()``/``tuh_task()`` function. All of the callbacks and functionality are handled and invoked within the call of that task runner. - -.. code-block:: c - - int main(void) { - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; - tusb_init(0, &dev_init); // initialize device stack on roothub port 0 - - tusb_rhport_init_t host_init = { - .role = TUSB_ROLE_HOST, - .speed = TUSB_SPEED_AUTO - }; - tusb_init(1, &host_init); // initialize host stack on roothub port 1 - - while(1) { // the mainloop - your_application_code(); - tud_task(); // device task - tuh_task(); // host task - } - } - - void USB0_IRQHandler(void) { - tusb_int_handler(0, true); - } - - void USB1_IRQHandler(void) { - tusb_int_handler(1, true); - } - -Examples --------- - -For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API should be used. Most examples will work on most of `the supported boards <boards.rst>`_. Firstly we need to ``git clone`` if not already - -.. code-block:: bash - - $ git clone https://github.com/hathach/tinyusb tinyusb - $ cd tinyusb - -Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples. They are out of scope for tinyusb, you should download/install it first according to its manufacturer guide. - -Dependencies -^^^^^^^^^^^^ - -The hardware code is located in ``hw/bsp`` folder, and is organized by family/boards. e.g raspberry_pi_pico is located in ``hw/bsp/rp2040/boards/raspberry_pi_pico`` where ``FAMILY=rp2040`` and ``BOARD=raspberry_pi_pico``. Before building, we firstly need to download dependencies such as: MCU low-level peripheral driver and external libraries e.g FreeRTOS (required by some examples). We can do that by either ways: - -1. Run ``tools/get_deps.py {FAMILY}`` script to download all dependencies for a family as follow. Note: For TinyUSB developer to download all dependencies, use FAMILY=all. - -.. code-block:: bash - - $ python tools/get_deps.py rp2040 - -2. Or run the ``get-deps`` target in one of the example folder as follow. - -.. code-block:: bash - - $ cd examples/device/cdc_msc - $ 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 Examples -^^^^^^^^^^^^^^ - -Examples support make and cmake build system for most MCUs, however some MCU families such as espressif or rp2040 only support cmake. First change directory to an example folder. - -.. code-block:: bash - - $ cd examples/device/cdc_msc - -Then compile with make or cmake - -.. code-block:: bash - - $ # 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 - -.. code-block:: bash - - $ cp examples/device/99-tinyusb.rules /etc/udev/rules.d/ - $ sudo udevadm control --reload-rules && sudo udevadm trigger - -RootHub Port Selection -~~~~~~~~~~~~~~~~~~~~~~ - -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 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 ``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 RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED all - - $ cmake -DBOARD=stm32f746disco -DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED .. - -Size Analysis -~~~~~~~~~~~~~ - -First install `linkermap tool <https://github.com/hathach/linkermap>`_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since ``-flto`` merges code across ``.o`` files and make it difficult to analyze. - -.. code-block:: bash - - $ make BOARD=feather_nrf52840_express NO_LTO=1 all linkermap - -Debug -^^^^^ - -To compile for debugging add ``DEBUG=1``\ , for example - -.. code-block:: bash - - $ make BOARD=feather_nrf52840_express DEBUG=1 all - - $ cmake -DBOARD=feather_nrf52840_express -DCMAKE_BUILD_TYPE=Debug .. - -Log -~~~ - -Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. ``LOG=1`` will only print out error message, ``LOG=2`` print more information with on-going events. ``LOG=3`` or higher is not used yet. - -.. code-block:: bash - - $ make BOARD=feather_nrf52840_express LOG=2 all - - $ cmake -DBOARD=feather_nrf52840_express -DLOG=2 .. - -Logger -~~~~~~ - -By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols: - - -* `LOGGER=rtt`: use `Segger RTT protocol <https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/>`_ - - * Cons: requires jlink as the debugger. - * Pros: work with most if not all MCUs - * Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package. - -* ``LOGGER=swo``\ : Use dedicated SWO pin of ARM Cortex SWD debug header. - - * Cons: only work with ARM Cortex MCUs minus M0 - * Pros: should be compatible with more debugger that support SWO. - * Software viewer should be provided along with your debugger driver. - -.. code-block:: bash - - $ 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 -^^^^^ - -``flash`` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command - -.. code-block:: bash - - $ make BOARD=feather_nrf52840_express flash - $ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash - -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 - -.. code-block:: bash - - $ 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``. - - - ``STM32L0xx_HAL_Driver`` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs. - -* Open ``Tools -> Configure Custom Argument Variables`` (Switch to ``Global`` tab if you want to do it for all your projects) - 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** - -Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``. - -**Run examples** - -1. Run ``iar_gen.py`` to generate .ipcf files of examples: - - .. code-block:: - - > cd C:\tinyusb\tools - > python iar_gen.py - -2. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\examples\\(.ipcf of example)``. - For example ``C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf`` - -Native CMake support -~~~~~~~~~~~~~~~~~~~~ - -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. - -Following these steps: - -1. Add IAR compiler binary path to system ``PATH`` environment variable, such as ``C:\Program Files\IAR Systems\Embedded Workbench 9.2\arm\bin``. -2. Create new project in IAR, in Tool chain dropdown menu, choose CMake for Arm then Import ``CMakeLists.txt`` from chosen example directory. -3. Set up board option in ``Option - CMake/CMSIS-TOOLBOX - CMake``, for example ``-DBOARD=stm32f439nucleo -DTOOLCHAIN=iar``, **Uncheck 'Override tools in env'**. -4. (For debug only) Choose correct CPU model in ``Option - General Options - Target``, to profit register and memory view. diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst new file mode 100644 index 000000000..537769c43 --- /dev/null +++ b/docs/reference/glossary.rst @@ -0,0 +1,98 @@ +******** +Glossary +******** + +.. glossary:: + + BSP + Board Support Package. A collection of board-specific code that provides hardware abstraction for a particular development board, including pin mappings, clock settings, linker scripts, and hardware initialization routines. Located in ``hw/bsp/FAMILY/boards/BOARD_NAME``. + + Bulk Transfer + USB transfer type used for large amounts of data that doesn't require guaranteed timing. Used by mass storage devices and CDC class. + + CDC + Communications Device Class. USB class for devices that communicate serial data, creating virtual serial ports. + + Control Transfer + USB transfer type used for device configuration and control. All USB devices must support control transfers on endpoint 0. + + DCD + Device Controller Driver. The hardware abstraction layer for USB device controllers in TinyUSB. See also HCD. + + Descriptor + Data structures that describe USB device capabilities, configuration, and interfaces to the host. + + Device Class + USB specification defining how devices of a particular type (e.g., storage, audio, HID) communicate with hosts. + + DFU + Device Firmware Update. USB class that allows firmware updates over USB. + + Endpoint + Communication channel between host and device. Each endpoint has a direction (IN/OUT) and transfer type. + + Enumeration + Process where USB host discovers and configures a newly connected device. + + HCD + Host Controller Driver. The hardware abstraction layer for USB host controllers in TinyUSB. See also DCD. + + HID + Human Interface Device. USB class for input devices like keyboards, mice, and game controllers. + + High Speed + USB 2.0 speed mode operating at 480 Mbps. + + Full Speed + USB speed mode operating at 12 Mbps, supported by USB 1.1 and 2.0. + + Low Speed + USB speed mode operating at 1.5 Mbps, typically used by simple input devices. + + Interrupt Transfer + USB transfer type for small, time-sensitive data with guaranteed maximum latency. + + Isochronous Transfer + USB transfer type for time-critical data like audio/video with guaranteed bandwidth but no error correction. + + MSC + Mass Storage Class. USB class for storage devices like USB drives. + + OSAL + Operating System Abstraction Layer. TinyUSB component that abstracts RTOS differences. + + OTG + On-The-Go. USB specification allowing devices to act as both host and device. + + Pipe + Host-side communication channel to a device endpoint. + + Root Hub + The USB hub built into the host controller, where devices connect directly. + + Stall + USB protocol mechanism where an endpoint responds with a STALL handshake to indicate an error condition or unsupported request. Used for error handling, not flow control. + + Super Speed + USB 3.0 speed mode operating at 5 Gbps. Not supported by TinyUSB. + + tud + TinyUSB Device. Function prefix for all device stack APIs (e.g., ``tud_task()``, ``tud_cdc_write()``). + + tuh + TinyUSB Host. Function prefix for all host stack APIs (e.g., ``tuh_task()``, ``tuh_cdc_receive()``). + + UAC + USB Audio Class. USB class for audio devices. + + UVC + USB Video Class. USB class for video devices like cameras. + + VID + Vendor Identifier. 16-bit number assigned by USB-IF to identify device manufacturers. + + PID + Product Identifier. 16-bit number assigned by vendor to identify specific products. + + USB-IF + USB Implementers Forum. Organization that maintains USB specifications and assigns VIDs. diff --git a/docs/reference/index.rst b/docs/reference/index.rst index 8ac3cf924..d3c96eeee 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -1,10 +1,15 @@ -Index -===== +********* +Reference +********* + +Complete reference documentation for TinyUSB APIs, configuration, and supported hardware. .. toctree:: :maxdepth: 2 - getting_started + architecture + usb_concepts boards dependencies concurrency + glossary diff --git a/docs/reference/usb_concepts.rst b/docs/reference/usb_concepts.rst new file mode 100644 index 000000000..86ae97007 --- /dev/null +++ b/docs/reference/usb_concepts.rst @@ -0,0 +1,428 @@ +************ +USB Concepts +************ + +This document provides a brief introduction to USB protocol fundamentals that are essential for understanding TinyUSB development. + +TinyUSB API Naming Conventions +=============================== + +TinyUSB uses consistent function prefixes to organize its API: + +* **tusb_**: Core stack functions (initialization, interrupt handling) +* **tud_**: Device stack functions (e.g., ``tud_task()``, ``tud_cdc_write()``) +* **tuh_**: Host stack functions (e.g., ``tuh_task()``, ``tuh_cdc_receive()``) +* **tu_**: Internal utility functions (generally not used by applications) + +This naming makes it easy to identify which part of the stack a function belongs to and ensures there are no naming conflicts when using both device and host stacks together. + +USB Protocol Basics +==================== + +Universal Serial Bus (USB) is a standardized communication protocol designed for connecting devices to hosts (typically computers). Understanding these core concepts is essential for effective TinyUSB development. + +Host and Device Roles +---------------------- + +**USB Host**: The controlling side of a USB connection (typically a computer). The host: +- Initiates all communication +- Provides power to devices +- Manages the USB bus +- Enumerates and configures devices + +**TinyUSB Host Stack**: Enable with ``CFG_TUH_ENABLED=1`` in ``tusb_config.h``. Call ``tuh_task()`` regularly in your main loop. See the :doc:`../getting_started` Quick Start Examples for implementation details. + +**USB Device**: The peripheral side (keyboard, mouse, storage device, etc.). Devices: +- Respond to host requests +- Cannot initiate communication +- Receive power from the host +- Must be enumerated by the host before use + +**TinyUSB Device Stack**: Enable with ``CFG_TUD_ENABLED=1`` in ``tusb_config.h``. Call ``tud_task()`` regularly in your main loop. See the :doc:`../getting_started` Quick Start Examples for implementation details. + +**OTG (On-The-Go)**: Some devices can switch between host and device roles dynamically. **TinyUSB Support**: Both stacks can be enabled simultaneously on OTG-capable hardware. See ``examples/dual/`` for dual-role implementations. + +USB Transfers +============= + +Every USB transfer consists of the host issuing a request, and the device replying to that request. The host is the bus master and initiates all communication. +Devices cannot initiate sending data; for unsolicited incoming data, polling is used by the host. + +USB defines four transfer types, each intended for different use cases: + +Control Transfers +----------------- + +Used for device configuration and control commands. + +**Characteristics**: +- Bidirectional (uses both IN and OUT) +- Guaranteed delivery with error detection +- Limited data size (8-64 bytes per packet) +- All devices must support control transfers on endpoint 0 + +**Usage**: Device enumeration, configuration changes, class-specific commands + +**TinyUSB Context**: Handled automatically by the core stack for standard requests; class drivers handle class-specific requests. Endpoint 0 is managed by ``src/device/usbd.c`` and ``src/host/usbh.c``. Configure buffer size with ``CFG_TUD_ENDPOINT0_SIZE`` (typically 64 bytes). + +Bulk Transfers +-------------- + +Used for large amounts of data that don't require guaranteed timing. + +**Characteristics**: +- Unidirectional (separate IN and OUT endpoints) +- Guaranteed delivery with error detection +- Large packet sizes (up to 512 bytes for High Speed) +- Uses available bandwidth when no other transfers are active + +**Usage**: File transfers, large data communication, CDC serial data + +**TinyUSB Context**: Used by MSC (mass storage) and CDC classes for data transfer. Configure endpoint buffer sizes with ``CFG_TUD_MSC_EP_BUFSIZE`` and ``CFG_TUD_CDC_EP_BUFSIZE``. See ``src/class/msc/`` and ``src/class/cdc/`` for implementation details. + +Interrupt Transfers +------------------- + +Used for small, time-sensitive data with guaranteed maximum latency. + +**Characteristics**: +- Unidirectional (separate IN and OUT endpoints) +- Guaranteed delivery with error detection +- Small packet sizes (up to 64 bytes for Full Speed) +- Regular polling interval (1ms to 255ms) + +**Usage**: Keyboard/mouse input, sensor data, status updates + +**TinyUSB Context**: Used by HID class for input reports. Configure with ``CFG_TUD_HID`` and ``CFG_TUD_HID_EP_BUFSIZE``. Send reports using ``tud_hid_report()`` or ``tud_hid_keyboard_report()``. See ``src/class/hid/`` and HID examples in ``examples/device/hid_*/``. + +Isochronous Transfers +--------------------- + +Used for time-critical streaming data. + +**Characteristics**: +- Unidirectional (separate IN and OUT endpoints) +- No error correction (speed over reliability) +- Guaranteed bandwidth +- Real-time delivery + +**Usage**: Audio, video streaming + +**TinyUSB Context**: Used by Audio class for streaming audio data. Configure with ``CFG_TUD_AUDIO`` and related audio configuration macros. See ``src/class/audio/`` and audio examples in ``examples/device/audio_*/`` for UAC2 implementation. + +Endpoints and Addressing +========================= + +Endpoint Basics +--------------- + +**Endpoint**: A communication channel between host and device. + +- Each endpoint has a number (0-15) and direction +- Endpoint 0 is reserved for control transfers +- Other endpoints are assigned by device class requirements + +**TinyUSB Endpoint Management**: Configure maximum endpoints with ``CFG_TUD_ENDPOINT_MAX``. Endpoints are automatically allocated by enabled classes. See your board's ``usb_descriptors.c`` for endpoint assignments. + +**Direction**: +- **OUT**: Host to device (host sends data out) +- **IN**: Device to host (host reads data in) +- Note that in TinyUSB code, for ``tx``/``rx``, the device perspective is used typically: E.g., ``tud_cdc_tx_complete_cb()`` designates the callback executed once the device has completed sending data to the host (in device mode). + +**Addressing**: Endpoints are addressed as EPx IN/OUT (e.g., EP1 IN, EP2 OUT) + +Endpoint Configuration +---------------------- + +Each endpoint is configured with a specific **transfer type** (control, bulk, interrupt, or isochronous), a **direction** (IN, OUT, or bidirectional for control only), a **maximum packet size** that depends on USB speed and transfer type, and an **interval** for interrupt and isochronous endpoints. + +**TinyUSB Configuration**: Endpoint characteristics are defined in descriptors (``usb_descriptors.c``) and automatically configured by the stack. Buffer sizes are set via ``CFG_TUD_*_EP_BUFSIZE`` macros. + +Error Handling and Flow Control +------------------------------- + +**Transfer Results**: USB transfers can complete with different results. An **ACK** indicates a successful transfer, while a **NAK** signals that the device is not ready (commonly used for flow control). A **STALL** response indicates an error condition or unsupported request, and **Timeout** occurs when a transfer fails to complete within the expected time frame. + +**Flow Control in USB**: Unlike network protocols, USB doesn't use traditional congestion control. Instead, devices use NAK responses when not ready to receive data, applications implement buffering and proper timing strategies, and some classes (like CDC) support hardware flow control mechanisms such as RTS/CTS. + +**TinyUSB Handling**: Transfer results are represented as ``xfer_result_t`` enum values. The stack automatically handles NAK responses and timing. STALL conditions indicate application-level errors that should be addressed in class drivers. + +USB Device States +================= + +A USB device progresses through several states: + +1. **Attached**: Device is physically connected +2. **Powered**: Device receives power from host +3. **Default**: Device responds to address 0 +4. **Address**: Device has been assigned a unique address +5. **Configured**: Device is ready for normal operation +6. **Suspended**: Device is in low-power state + +**TinyUSB State Management**: State transitions are handled automatically by ``src/device/usbd.c``. You can implement ``tud_mount_cb()`` and ``tud_umount_cb()`` to respond to configuration changes, and ``tud_suspend_cb()``/``tud_resume_cb()`` for power management. + +Device Enumeration Process +========================== + +When a device is connected, the host follows this process: + +1. **Detection**: Host detects device connection +2. **Reset**: Host resets the device +3. **Descriptor Requests**: Host requests device descriptors +4. **Address Assignment**: Host assigns unique address to device +5. **Configuration**: Host selects and configures device +6. **Class Loading**: Host loads appropriate drivers +7. **Normal Operation**: Device is ready for use + +**TinyUSB Role**: The device stack handles steps 1-6 automatically; your application handles step 7. + +USB Descriptors +=============== + +Descriptors are data structures that describe device capabilities: + +Device Descriptor +----------------- +Describes the device (VID, PID, USB version, etc.) + +Configuration Descriptor +------------------------ +Describes device configuration (power requirements, interfaces, etc.) + +Interface Descriptor +-------------------- +Describes a functional interface (class, endpoints, etc.) + +Endpoint Descriptor +------------------- +Describes endpoint characteristics (type, direction, size, etc.) + +String Descriptors +------------------ +Human-readable strings (manufacturer, product name, etc.) + +**TinyUSB Implementation**: You provide descriptors in ``usb_descriptors.c`` via callback functions: +- ``tud_descriptor_device_cb()`` - Device descriptor +- ``tud_descriptor_configuration_cb()`` - Configuration descriptor +- ``tud_descriptor_string_cb()`` - String descriptors + +The stack automatically handles descriptor requests during enumeration. See examples in ``examples/device/*/usb_descriptors.c`` for reference implementations. + +USB Classes +=========== + +USB classes define standardized protocols for device types: + +**Class Code**: Identifies the device type in descriptors +**Class Driver**: Software that implements the class protocol +**Class Requests**: Standardized commands for the class + +**Common TinyUSB-Supported Classes**: +- **CDC (02h)**: Communication devices (virtual serial ports) - Enable with ``CFG_TUD_CDC`` +- **HID (03h)**: Human interface devices (keyboards, mice) - Enable with ``CFG_TUD_HID`` +- **MSC (08h)**: Mass storage devices (USB drives) - Enable with ``CFG_TUD_MSC`` +- **Audio (01h)**: Audio devices (speakers, microphones) - Enable with ``CFG_TUD_AUDIO`` +- **MIDI**: MIDI devices - Enable with ``CFG_TUD_MIDI`` +- **DFU**: Device Firmware Update - Enable with ``CFG_TUD_DFU`` +- **Vendor**: Custom vendor classes - Enable with ``CFG_TUD_VENDOR`` + +.. note:: + **Vendor Class Buffer Configuration**: Unlike other USB classes, the vendor class supports setting buffer sizes to 0 in ``tusb_config.h`` (``CFG_TUD_VENDOR_RX_BUFSIZE = 0``) to disable internal buffering. When disabled, data goes directly to ``tud_vendor_rx_cb()`` and the ``tud_vendor_read()``/``tud_vendor_write()`` functions are not available - applications must handle data directly in callbacks. + +See ``examples/device/*/tusb_config.h`` for configuration examples. + +USB Speeds +========== + +USB supports multiple speed modes: + +**Low Speed (1.5 Mbps)**: +- Simple devices (mice, keyboards) +- Limited endpoint types and sizes + +**Full Speed (12 Mbps)**: +- Most common for embedded devices +- All transfer types supported +- Maximum packet sizes: Control (64), Bulk (64), Interrupt (64) + +**High Speed (480 Mbps)**: +- High-performance devices +- Larger packet sizes: Control (64), Bulk (512), Interrupt (1024) +- Requires more complex hardware + +**Super Speed (5 Gbps)**: +- USB 3.0 and later +- Not supported by TinyUSB + +**TinyUSB Speed Support**: Most TinyUSB ports support Full Speed and High Speed. Speed is typically auto-detected by hardware. Configure speed requirements in board configuration (``hw/bsp/FAMILY/boards/BOARD/board.mk``) and ensure your MCU supports the desired speed. + +USB Controller Abstraction +=========================== + +USB controllers are hardware peripherals that handle the low-level USB protocol implementation. Understanding how they work helps explain TinyUSB's architecture and portability. + +Controller Fundamentals +----------------------- + +**What Controllers Do**: +- Handle USB signaling and protocol timing +- Manage endpoint buffers and data transfers +- Generate interrupts for USB events +- Implement USB electrical specifications + +**Key Components**: USB controllers consist of several key components working together. The **Physical Layer** provides USB signal drivers and receivers for electrical interfacing. The **Protocol Engine** handles USB packets and ACK/NAK responses according to the USB specification. **Endpoint Buffers** provide hardware FIFOs or RAM for data storage during transfers. Finally, the **Interrupt Controller** generates events for software processing when USB activities occur. + +Controller Architecture Types +----------------------------- + +Different MCU vendors implement USB controllers with varying architectures. +To list a few common patterns: + +**FIFO-Based Controllers** (e.g., STM32 OTG, NXP LPC): +- Shared or dedicated FIFOs for endpoint data +- Software manages FIFO allocation and data flow +- Common in higher-end MCUs with flexible configurations + +**Buffer-Based Controllers** (e.g., STM32 FSDEV, Microchip SAMD, RP2040): +- Fixed packet memory areas for each endpoint +- Hardware automatically handles packet placement +- Simpler programming model, common in smaller MCUs + +**Descriptor-Based Controllers** (e.g., NXP EHCI-style): +- Use descriptor chains to describe transfers +- Hardware processes transfer descriptors independently +- More complex but can handle larger transfers autonomously + +TinyUSB Controller Abstraction +------------------------------ + +TinyUSB abstracts controller differences through the TinyUSB **Device Controller Driver (DCD)** layer. +These internal details don't matter to users of TinyUSB typically; however, when debugging, knowledge about internal details helps sometimes. + +**Portable Interface** (``src/device/usbd.h``): +- Standardized function signatures for all controllers +- Common endpoint and transfer management APIs +- Unified interrupt and event handling + +**Controller-Specific Drivers** (``src/portable/VENDOR/FAMILY/``): +- Implement the DCD interface for specific hardware +- Handle vendor-specific register layouts and behaviors +- Manage controller-specific quirks and workarounds + +**Common DCD Functions**: +- ``dcd_init()`` - Initialize controller hardware +- ``dcd_edpt_open()`` - Configure endpoint with type and size +- ``dcd_edpt_xfer()`` - Start data transfer on endpoint +- ``dcd_int_handler()`` - Process USB interrupts +- ``dcd_connect()/dcd_disconnect()`` - Control USB bus connection + +Host Controller Driver (HCD) +----------------------------- + +TinyUSB also abstracts USB host controllers through the **Host Controller Driver (HCD)** layer for host mode applications. + +**Portable Interface** (``src/host/usbh.h``): +- Standardized interface for all host controllers +- Common device enumeration and pipe management +- Unified transfer scheduling and completion handling + +**Common HCD Functions**: +- ``hcd_init()`` - Initialize host controller hardware +- ``hcd_port_connect_status()`` - Check device connection status +- ``hcd_port_reset()`` - Reset connected device +- ``hcd_edpt_open()`` - Open communication pipe to device endpoint +- ``hcd_edpt_xfer()`` - Transfer data to/from connected device + +**Host vs Device Architecture**: While DCD is reactive (responds to host requests), HCD is active (initiates all communication). Host controllers manage device enumeration, driver loading, and transfer scheduling to multiple connected devices. + +TinyUSB Event System & Thread Safety +==================================== + +Deferred Interrupt Processing +----------------------------- + +**Core Architectural Principle**: TinyUSB uses a deferred interrupt processing model where all USB hardware events are captured in interrupt service routines (ISRs) but processed later in non-interrupt context. + +**Event Flow**: + +1. **Hardware Event**: USB controller generates interrupt (e.g., data received, transfer complete) +2. **ISR Handling**: TinyUSB ISR captures the event and pushes it to a central event queue +3. **Deferred Processing**: Application calls ``tud_task()`` or ``tuh_task()`` to process queued events +4. **Class Driver Callbacks**: Events trigger appropriate class driver functions and user callbacks + +**Buffer Integration**: The deferred processing model works seamlessly with TinyUSB's buffer/FIFO design. Since callbacks run in task context (not ISR), it's safe and straightforward to enqueue TX data directly in RX callbacks - for example, processing incoming CDC data and immediately sending a response. + +Controller Event Flow +--------------------- + +**Typical USB Event Processing**: + +1. **Hardware Event**: USB controller detects bus activity (setup packet, data transfer, etc.) +2. **Interrupt Generation**: Controller generates interrupt to CPU +3. **ISR Processing**: ``dcd_int_handler()`` reads controller status +4. **Event Queuing**: Events are queued for later processing (thread safety) +5. **Task Processing**: ``tud_task()`` processes queued events +6. **Class Notification**: Appropriate class drivers handle the event +7. **Application Callback**: User code responds to the event + +USB Class Driver Architecture +============================== + +TinyUSB implements USB classes through a standardized driver pattern that provides consistent integration with the core stack while allowing class-specific functionality. + +Class Driver Pattern +--------------------- + +**Standardized Entry Points**: Each class driver implements these core functions: + +- ``*_init()`` - Initialize class driver state and buffers +- ``*_reset()`` - Reset to initial state on USB bus reset +- ``*_open()`` - Parse and configure interfaces during enumeration +- ``*_control_xfer_cb()`` - Handle class-specific control requests +- ``*_xfer_cb()`` - Handle transfer completion callbacks + +**Multi-Instance Support**: Classes support multiple instances using ``_n`` suffixed APIs: + +.. code-block:: c + + // Single instance (default instance 0) + tud_cdc_write(data, len); + + // Multiple instances + tud_cdc_n_write(0, data, len); // Instance 0 + tud_cdc_n_write(1, data, len); // Instance 1 + +**Integration with Core Stack**: Class drivers are automatically discovered and integrated through function pointers in driver tables. The core stack calls class drivers during enumeration, control requests, and data transfers without requiring explicit registration. + +Class Driver Types +------------------- + +TinyUSB classes have different architectural patterns based on their buffering capabilities and callback designs. + +Most classes like CDC, MIDI, and HID always use internal buffers for data management. These classes provide notification-only callbacks such as ``tud_cdc_rx_cb(uint8_t itf)`` that signal when data is available, requiring applications to use class-specific APIs like ``tud_cdc_read()`` and ``tud_cdc_write()`` to access the data. HID is slightly different in that it provides direct buffer access in some callbacks (``tud_hid_set_report_cb()`` receives buffer and size parameters), but it still maintains internal endpoint buffering that cannot be disabled. + +The **Vendor Class** is unique in that it supports both buffered and direct modes. When buffered, vendor class behaves like other classes with ``tud_vendor_read()`` and ``tud_vendor_write()`` APIs. However, when buffering is disabled by setting buffer size to 0, the vendor class provides direct buffer access through ``tud_vendor_rx_cb(itf, buffer, bufsize)`` callbacks, eliminating internal FIFO overhead and providing direct endpoint control. + +**Block-Oriented Classes** like MSC operate differently by handling large data blocks through callback interfaces. The application implements storage access functions such as ``tud_msc_read10_cb()`` and ``tud_msc_write10_cb()``, while the TinyUSB stack manages the USB protocol aspects and the application manages the underlying storage. + +Power Management +================ + +USB provides power to devices: + +**Bus-Powered**: Device draws power from USB bus (up to 500mA) +**Self-Powered**: Device has its own power source +**Suspend/Resume**: Devices must enter low-power mode when bus is idle + +**TinyUSB Power Management**: +- Implement ``tud_suspend_cb()`` and ``tud_resume_cb()`` for power management +- Configure power requirements in device descriptor (``bMaxPower`` field) +- Use ``tud_remote_wakeup()`` to wake the host from suspend (if supported) +- Enable remote wakeup with ``CFG_TUD_USBD_ENABLE_REMOTE_WAKEUP`` + +Next Steps +========== + +- Start with :doc:`../getting_started` for basic setup +- Review ``examples/device/*/tusb_config.h`` for configuration examples +- Explore examples in ``examples/device/`` and ``examples/host/`` directories diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst new file mode 100644 index 000000000..bb9f15166 --- /dev/null +++ b/docs/troubleshooting.rst @@ -0,0 +1,304 @@ +*************** +Troubleshooting +*************** + +This guide helps you diagnose and fix common issues when developing with TinyUSB. + +Build Issues +============ + +Toolchain Problems +------------------ + +**"arm-none-eabi-gcc: command not found"** + +The ARM GCC toolchain is not installed or not in PATH. + +*Solution*: + +.. code-block:: bash + + # Ubuntu/Debian + $ sudo apt-get update && sudo apt-get install gcc-arm-none-eabi + + # macOS with Homebrew + $ brew install --cask gcc-arm-embedded + + # Windows: Download from ARM website and add to PATH + +**"make: command not found" or CMake errors** + +Build tools are missing. + +*Solution*: + +.. code-block:: bash + + # Ubuntu/Debian + $ sudo apt-get install build-essential cmake + + # macOS + $ xcode-select --install + $ brew install cmake + +Dependency Issues +----------------- + +**"No rule to make target" or missing header files** + +Dependencies for your MCU family are not downloaded. + +*Solution*: + +.. code-block:: bash + + # Download dependencies for specific board or family + $ python tools/get_deps.py -b stm32h743eval # Replace with your board + $ python tools/get_deps.py stm32f4 # Replace with your family + + # Or from example directory + cd examples/device/cdc_msc + make BOARD=your_board get-deps + +**Board Not Found** + +Invalid board name in build command. + +*Diagnosis*: + +.. code-block:: bash + + # List available boards for a family + ls hw/bsp/stm32f4/boards/ + +*Solution*: Use exact board name from the listing. + +Runtime Issues +============== + +Device Mode Problems +-------------------- + +**Device not recognized by host** + +The most common issue - host doesn't see your USB device. + +*Diagnosis steps*: + +1. Check USB cable (must support data, not just power) +2. Enable logging: build with ``LOG=2`` +3. Use different USB ports/hosts +4. Check device manager (Windows) or ``dmesg`` (Linux) + +*Common causes and solutions*: + +- **Invalid descriptors**: Review ``usb_descriptors.c`` carefully +- **``tud_task()`` not called**: Ensure regular calls in main loop (< 1ms interval) +- **Wrong USB configuration**: Check ``tusb_config.h`` settings +- **Hardware issues**: Verify USB pins, crystal/clock configuration + +**Enumeration starts but fails** + +Device is detected but configuration fails. + +*Diagnosis*: + +.. code-block:: bash + + # Build with logging enabled + make BOARD=your_board LOG=2 all + +*Look for*: + +- Setup request handling errors +- Endpoint configuration problems +- String descriptor issues + +*Solutions*: + +- Implement all required descriptors +- Check endpoint sizes match descriptors +- Ensure control endpoint (EP0) handling is correct + +**Data transfer issues** + +Device enumerates but data doesn't transfer correctly. + +*Common causes*: + +- Buffer overruns in class callbacks +- Incorrect endpoint usage (IN vs OUT) +- Flow control issues in CDC class + +*Solutions*: + +- Check buffer sizes in callbacks +- Verify endpoint directions in descriptors +- Implement proper flow control + +Host Mode Problems +------------------ + +**No devices detected** + +Host application doesn't see connected devices. + +*Hardware checks*: + +- Power supply adequate for host mode +- USB-A connector for host (not micro-USB) +- Board supports host mode on selected port + +*Software checks*: + +- ``tuh_task()`` called regularly +- Host stack enabled in ``tusb_config.h`` +- Correct root hub port configuration + +**Device enumeration fails** + +Devices connect but enumeration fails. + +*Diagnosis*: + +.. code-block:: bash + + # Enable host logging + make BOARD=your_board LOG=2 RHPORT_HOST=1 all + +*Common issues*: + +- Power supply insufficient during enumeration +- Timing issues with slow devices +- USB hub compatibility problems + +**Class driver issues** + +Device enumerates but class-specific communication fails. + +*Troubleshooting*: + +- Check device descriptors match expected class +- Verify interface/endpoint assignments +- Some devices need device-specific handling + +Performance Issues +================== + +Slow Transfer Speeds +-------------------- + +**Symptoms**: Lower than expected USB transfer rates + +*Causes and solutions*: Improve **task scheduling** by calling ``tud_task()``/``tuh_task()`` more frequently to ensure timely USB event processing. Consider increasing **endpoint buffer sizes** for bulk transfers to reduce the frequency of small transfers. Enable **DMA usage** for USB transfers if your hardware supports it to offload CPU processing. Finally, use **High Speed** (480 Mbps) instead of Full Speed (12 Mbps) when possible to achieve better throughput. + +High CPU Usage +-------------- + +**Symptoms**: MCU spending too much time in USB handling + +*Solutions*: + +- Use efficient logging (RTT/SWO instead of UART) +- Reduce log level in production builds +- Optimize descriptor parsing +- Use DMA for data transfers + +Hardware-Specific Issues +======================== + +STM32 Issues +------------ + +**Clock configuration problems**: + +- USB requires precise 48MHz clock +- HSE crystal must be configured correctly +- PLL settings affect USB timing + +**Pin configuration**: + +- USB pins need specific alternate function settings +- VBUS sensing configuration +- ID pin for OTG applications + +RP2040 Issues +------------- + +**PIO-USB for host mode**: + +- Requires specific pin assignments +- CPU overclocking may be needed for reliable operation +- Timing-sensitive - avoid long interrupt disable periods + +ESP32 Issues +------------ + +**USB peripheral differences**: + +- ESP32-S2/S3/P4 have different USB capabilities +- DMA configuration varies between models + +Advanced Debugging +================== + +Using USB Analyzers +------------------- + +For complex issues, hardware USB analyzers provide detailed protocol traces: + +- **Wireshark** with USBPcap (Windows) or usbmon (Linux) +- **Hardware analyzers**: Total Phase Beagle, LeCroy USB analyzers +- **Logic analyzers**: For timing analysis of USB signals + +Debugging with GDB +------------------ + +Debugging with traditional debuggers is limited due to the real time nature of USB. +However, especially for diagnosis of crashes, it can still be useful. + +.. code-block:: bash + + # Build with debug info + make BOARD=your_board DEBUG=1 all + + # Use with debugger + arm-none-eabi-gdb build/your_app.elf + +*Useful breakpoints*: + +- ``dcd_int_handler()`` - USB interrupt entry +- ``tud_task()`` - Main device task +- Class-specific callbacks + +Custom Logging +-------------- + +For production debugging, implement custom logging: + +.. code-block:: c + + // In tusb_config.h + #define CFG_TUSB_DEBUG_PRINTF my_printf + + // Your implementation + void my_printf(const char* format, ...) { + // Send to RTT, SWO, or custom interface + } + +Getting Help +============ + +When reporting issues: + +1. **Minimal reproducible example**: Simplify to bare minimum +2. **Build information**: Board, toolchain version, build flags +3. **Logs**: Include output with ``LOG=2`` enabled +4. **Hardware details**: Board revision, USB connections, power supply +5. **Host environment**: OS version, USB port type + +**Resources**: + +- GitHub Discussions: https://github.com/hathach/tinyusb/discussions +- Issue Tracker: https://github.com/hathach/tinyusb/issues +- Documentation: https://docs.tinyusb.org diff --git a/examples/build_system/cmake/toolchain/arm_clang.cmake b/examples/build_system/cmake/toolchain/arm_clang.cmake index fe3c2b453..dba637367 100644 --- a/examples/build_system/cmake/toolchain/arm_clang.cmake +++ b/examples/build_system/cmake/toolchain/arm_clang.cmake @@ -7,6 +7,8 @@ if (NOT DEFINED CMAKE_CXX_COMPILER) endif () set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +set(TOOLCHAIN_ASM_FLAGS "-x assembler-with-cpp") + find_program(CMAKE_SIZE llvm-size) find_program(CMAKE_OBJCOPY llvm-objcopy) find_program(CMAKE_OBJDUMP llvm-objdump) diff --git a/examples/build_system/cmake/toolchain/arm_iar.cmake b/examples/build_system/cmake/toolchain/arm_iar.cmake index 083815715..0b7e0b585 100644 --- a/examples/build_system/cmake/toolchain/arm_iar.cmake +++ b/examples/build_system/cmake/toolchain/arm_iar.cmake @@ -14,4 +14,18 @@ find_program(CMAKE_SIZE size) find_program(CMAKE_OBJCOPY ielftool) find_program(CMAKE_OBJDUMP iefdumparm) +find_program(CMAKE_IAR_CSTAT icstat) +find_program(CMAKE_IAR_CHECKS ichecks) +find_program(CMAKE_IAR_REPORT ireport) + +if (IAR_CSTAT) +cmake_minimum_required(VERSION 4.1) +set(CMAKE_C_ICSTAT ${CMAKE_IAR_CSTAT} + --checks=${CMAKE_CURRENT_LIST_DIR}/cstat_sel_checks.txt + --db=${CMAKE_BINARY_DIR}/cstat.db + --sarif_dir=${CMAKE_BINARY_DIR}/cstat_sarif + --exclude ${TOP}/hw/mcu --exclude ${TOP}/lib + ) +endif () + include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) diff --git a/examples/build_system/cmake/toolchain/common.cmake b/examples/build_system/cmake/toolchain/common.cmake index 4c181137b..14449b01d 100644 --- a/examples/build_system/cmake/toolchain/common.cmake +++ b/examples/build_system/cmake/toolchain/common.cmake @@ -20,11 +20,11 @@ include(${CMAKE_CURRENT_LIST_DIR}/../cpu/${CMAKE_SYSTEM_CPU}.cmake) # ---------------------------------------------------------------------------- # Compile flags # ---------------------------------------------------------------------------- -if (TOOLCHAIN STREQUAL "gcc") +if (TOOLCHAIN STREQUAL "gcc" OR TOOLCHAIN STREQUAL "clang") list(APPEND TOOLCHAIN_COMMON_FLAGS -fdata-sections -ffunction-sections - -fsingle-precision-constant +# -fsingle-precision-constant # not supported by clang -fno-strict-aliasing ) list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS @@ -32,24 +32,10 @@ if (TOOLCHAIN STREQUAL "gcc") -Wl,--gc-sections -Wl,--cref ) - elseif (TOOLCHAIN STREQUAL "iar") - #list(APPEND TOOLCHAIN_COMMON_FLAGS) list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS --diag_suppress=Li065 ) - -elseif (TOOLCHAIN STREQUAL "clang") - list(APPEND TOOLCHAIN_COMMON_FLAGS - -fdata-sections - -ffunction-sections - -fno-strict-aliasing - ) - list(APPEND TOOLCHAIN_EXE_LINKER_FLAGS - -Wl,--print-memory-usage - -Wl,--gc-sections - -Wl,--cref - ) endif () # join the toolchain flags into a single string @@ -61,5 +47,10 @@ foreach (LANG IN ITEMS C CXX ASM) #set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0") endforeach () +# Assembler +if (DEFINED TOOLCHAIN_ASM_FLAGS) + set(CMAKE_ASM_FLAGS_INIT "${CMAKE_ASM_FLAGS_INIT} ${TOOLCHAIN_ASM_FLAGS}") +endif () + # Linker list(JOIN TOOLCHAIN_EXE_LINKER_FLAGS " " CMAKE_EXE_LINKER_FLAGS_INIT) diff --git a/examples/build_system/cmake/toolchain/cstat_sel_checks.txt b/examples/build_system/cmake/toolchain/cstat_sel_checks.txt new file mode 100644 index 000000000..b7efba4ad --- /dev/null +++ b/examples/build_system/cmake/toolchain/cstat_sel_checks.txt @@ -0,0 +1,247 @@ +# IAR C-STAT Checks Manifest Handler V2.7.5.562 +# +MISRAC2012-Dir-4.3 +MISRAC2012-Dir-4.7_c +MISRAC2012-Dir-4.10 +MISRAC2012-Dir-4.11_a +MISRAC2012-Dir-4.11_b +MISRAC2012-Dir-4.11_c +MISRAC2012-Dir-4.11_d +MISRAC2012-Dir-4.11_e +MISRAC2012-Dir-4.11_f +MISRAC2012-Dir-4.11_g +MISRAC2012-Dir-4.11_h +MISRAC2012-Dir-4.11_i +MISRAC2012-Dir-4.12 +MISRAC2012-Dir-4.14_a +MISRAC2012-Dir-4.14_b +MISRAC2012-Dir-4.14_c +MISRAC2012-Dir-4.14_d +MISRAC2012-Dir-4.14_e +MISRAC2012-Dir-4.14_f +MISRAC2012-Dir-4.14_g +MISRAC2012-Dir-4.14_h +MISRAC2012-Dir-4.14_i +MISRAC2012-Dir-4.14_j +MISRAC2012-Dir-4.14_l +MISRAC2012-Dir-4.14_m +MISRAC2012-Dir-4.15 +MISRAC2012-Rule-1.3_a +MISRAC2012-Rule-1.3_b +MISRAC2012-Rule-1.3_c +MISRAC2012-Rule-1.3_d +MISRAC2012-Rule-1.3_e +MISRAC2012-Rule-1.3_f +MISRAC2012-Rule-1.3_g +MISRAC2012-Rule-1.3_h +MISRAC2012-Rule-1.3_i +MISRAC2012-Rule-1.3_j +MISRAC2012-Rule-1.3_k +MISRAC2012-Rule-1.3_l +MISRAC2012-Rule-1.3_m +MISRAC2012-Rule-1.3_n +MISRAC2012-Rule-1.3_o +MISRAC2012-Rule-1.3_p +MISRAC2012-Rule-1.3_q +MISRAC2012-Rule-1.3_r +MISRAC2012-Rule-1.3_s +MISRAC2012-Rule-1.3_t +MISRAC2012-Rule-1.3_u +MISRAC2012-Rule-1.3_v +MISRAC2012-Rule-1.4 +MISRAC2012-Rule-1.5_b +MISRAC2012-Rule-1.5_c +MISRAC2012-Rule-1.5_d +MISRAC2012-Rule-1.5_e +MISRAC2012-Rule-1.5_f +MISRAC2012-Rule-1.5_g +MISRAC2012-Rule-2.1_a +MISRAC2012-Rule-2.1_b +MISRAC2012-Rule-2.2_a +MISRAC2012-Rule-2.2_b +MISRAC2012-Rule-2.2_c +MISRAC2012-Rule-3.1 +MISRAC2012-Rule-3.2 +MISRAC2012-Rule-5.1 +MISRAC2012-Rule-5.2_c89 +MISRAC2012-Rule-5.2_c99 +MISRAC2012-Rule-5.3_c89 +MISRAC2012-Rule-5.3_c99 +MISRAC2012-Rule-5.4_c89 +MISRAC2012-Rule-5.4_c99 +MISRAC2012-Rule-5.5_c89 +MISRAC2012-Rule-5.5_c99 +MISRAC2012-Rule-5.6 +MISRAC2012-Rule-5.7 +MISRAC2012-Rule-5.8 +MISRAC2012-Rule-6.1 +MISRAC2012-Rule-6.2 +MISRAC2012-Rule-6.3 +MISRAC2012-Rule-7.1 +MISRAC2012-Rule-7.2 +MISRAC2012-Rule-7.3 +MISRAC2012-Rule-7.4_a +MISRAC2012-Rule-7.4_b +MISRAC2012-Rule-7.5 +MISRAC2012-Rule-7.6 +MISRAC2012-Rule-8.1 +MISRAC2012-Rule-8.2_a +MISRAC2012-Rule-8.2_b +MISRAC2012-Rule-8.3 +MISRAC2012-Rule-8.4 +MISRAC2012-Rule-8.5_a +MISRAC2012-Rule-8.5_b +MISRAC2012-Rule-8.10 +MISRAC2012-Rule-8.12 +MISRAC2012-Rule-8.14 +MISRAC2012-Rule-8.15 +MISRAC2012-Rule-9.1_a +MISRAC2012-Rule-9.1_b +MISRAC2012-Rule-9.1_d +MISRAC2012-Rule-9.1_e +MISRAC2012-Rule-9.2 +MISRAC2012-Rule-9.3 +MISRAC2012-Rule-9.4 +MISRAC2012-Rule-9.5_a +MISRAC2012-Rule-9.5_b +MISRAC2012-Rule-9.6 +MISRAC2012-Rule-9.7 +MISRAC2012-Rule-10.1_R2 +MISRAC2012-Rule-10.1_R3 +MISRAC2012-Rule-10.1_R4 +MISRAC2012-Rule-10.1_R5 +MISRAC2012-Rule-10.1_R6 +MISRAC2012-Rule-10.1_R7 +MISRAC2012-Rule-10.1_R8 +MISRAC2012-Rule-10.1_R10 +MISRAC2012-Rule-10.2 +MISRAC2012-Rule-10.3 +MISRAC2012-Rule-10.4_a +MISRAC2012-Rule-10.4_b +MISRAC2012-Rule-10.6 +MISRAC2012-Rule-10.7 +MISRAC2012-Rule-10.8 +MISRAC2012-Rule-11.1 +MISRAC2012-Rule-11.2 +MISRAC2012-Rule-11.3 +MISRAC2012-Rule-11.6 +MISRAC2012-Rule-11.7 +MISRAC2012-Rule-11.8 +MISRAC2012-Rule-11.9 +MISRAC2012-Rule-11.10 +MISRAC2012-Rule-12.2 +MISRAC2012-Rule-12.5 +MISRAC2012-Rule-12.6 +MISRAC2012-Rule-13.1 +MISRAC2012-Rule-13.2_a +MISRAC2012-Rule-13.2_b +MISRAC2012-Rule-13.2_c +MISRAC2012-Rule-13.5 +MISRAC2012-Rule-13.6 +MISRAC2012-Rule-14.1_a +MISRAC2012-Rule-14.1_b +MISRAC2012-Rule-14.2 +MISRAC2012-Rule-14.3_a +MISRAC2012-Rule-14.3_b +MISRAC2012-Rule-14.4_a +MISRAC2012-Rule-14.4_b +MISRAC2012-Rule-14.4_c +MISRAC2012-Rule-14.4_d +MISRAC2012-Rule-15.2 +MISRAC2012-Rule-15.3 +MISRAC2012-Rule-15.6_a +MISRAC2012-Rule-15.6_b +MISRAC2012-Rule-15.6_c +MISRAC2012-Rule-15.6_d +MISRAC2012-Rule-15.6_e +MISRAC2012-Rule-15.7 +MISRAC2012-Rule-16.1 +MISRAC2012-Rule-16.2 +MISRAC2012-Rule-16.3 +MISRAC2012-Rule-16.4 +MISRAC2012-Rule-16.5 +MISRAC2012-Rule-16.6 +MISRAC2012-Rule-16.7 +MISRAC2012-Rule-17.1 +MISRAC2012-Rule-17.2_a +MISRAC2012-Rule-17.2_b +MISRAC2012-Rule-17.3 +MISRAC2012-Rule-17.4 +MISRAC2012-Rule-17.5 +MISRAC2012-Rule-17.6 +MISRAC2012-Rule-17.7 +MISRAC2012-Rule-17.13 +MISRAC2012-Rule-18.1_a +MISRAC2012-Rule-18.1_b +MISRAC2012-Rule-18.1_c +MISRAC2012-Rule-18.1_d +MISRAC2012-Rule-18.2 +MISRAC2012-Rule-18.3 +MISRAC2012-Rule-18.4 +MISRAC2012-Rule-18.6_a +MISRAC2012-Rule-18.6_b +MISRAC2012-Rule-18.6_c +MISRAC2012-Rule-18.6_d +MISRAC2012-Rule-18.7 +MISRAC2012-Rule-18.8 +MISRAC2012-Rule-18.9 +MISRAC2012-Rule-18.10 +MISRAC2012-Rule-19.1 +MISRAC2012-Rule-20.2 +MISRAC2012-Rule-20.4_c89 +MISRAC2012-Rule-20.4_c99 +MISRAC2012-Rule-20.6_a +MISRAC2012-Rule-20.6_b +MISRAC2012-Rule-20.7 +MISRAC2012-Rule-21.1 +MISRAC2012-Rule-21.2 +MISRAC2012-Rule-21.3 +MISRAC2012-Rule-21.4 +MISRAC2012-Rule-21.5 +MISRAC2012-Rule-21.6 +MISRAC2012-Rule-21.7 +MISRAC2012-Rule-21.8 +MISRAC2012-Rule-21.9 +MISRAC2012-Rule-21.10 +MISRAC2012-Rule-21.12_a +MISRAC2012-Rule-21.12_b +MISRAC2012-Rule-21.12_c +MISRAC2012-Rule-21.13 +MISRAC2012-Rule-21.14 +MISRAC2012-Rule-21.15 +MISRAC2012-Rule-21.16 +MISRAC2012-Rule-21.17_a +MISRAC2012-Rule-21.17_b +MISRAC2012-Rule-21.17_c +MISRAC2012-Rule-21.17_d +MISRAC2012-Rule-21.17_e +MISRAC2012-Rule-21.17_f +MISRAC2012-Rule-21.18_a +MISRAC2012-Rule-21.18_b +MISRAC2012-Rule-21.19_a +MISRAC2012-Rule-21.19_b +MISRAC2012-Rule-21.20 +MISRAC2012-Rule-21.21 +MISRAC2012-Rule-21.22 +MISRAC2012-Rule-21.23 +MISRAC2012-Rule-21.24 +MISRAC2012-Rule-21.25 +MISRAC2012-Rule-22.1_a +MISRAC2012-Rule-22.1_b +MISRAC2012-Rule-22.2_a +MISRAC2012-Rule-22.2_b +MISRAC2012-Rule-22.2_c +MISRAC2012-Rule-22.3 +MISRAC2012-Rule-22.4 +MISRAC2012-Rule-22.5_a +MISRAC2012-Rule-22.5_b +MISRAC2012-Rule-22.6 +MISRAC2012-Rule-22.7_a +MISRAC2012-Rule-22.7_b +MISRAC2012-Rule-22.8 +MISRAC2012-Rule-22.9 +MISRAC2012-Rule-22.10 +MISRAC2012-Rule-23.2 +MISRAC2012-Rule-23.4 +MISRAC2012-Rule-23.6 +MISRAC2012-Rule-23.8 diff --git a/examples/device/CMakeLists.txt b/examples/device/CMakeLists.txt index bb7dd0a0f..eb625ea51 100644 --- a/examples/device/CMakeLists.txt +++ b/examples/device/CMakeLists.txt @@ -26,6 +26,7 @@ family_add_subdirectory(hid_generic_inout) family_add_subdirectory(hid_multiple_interface) family_add_subdirectory(midi_test) family_add_subdirectory(msc_dual_lun) +family_add_subdirectory(mtp) family_add_subdirectory(net_lwip_webserver) family_add_subdirectory(uac2_headset) family_add_subdirectory(uac2_speaker_fb) diff --git a/examples/device/audio_4_channel_mic/Makefile b/examples/device/audio_4_channel_mic/Makefile index 2c825bbf7..31e2c6f44 100644 --- a/examples/device/audio_4_channel_mic/Makefile +++ b/examples/device/audio_4_channel_mic/Makefile @@ -1,14 +1,14 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ src/main.c \ src/usb_descriptors.c \ -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 3e0f03a20..5767c7453 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -66,8 +66,8 @@ uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio20_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio20_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX * CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000]; @@ -156,7 +156,9 @@ void tud_resume_cb(void) { void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); } @@ -171,7 +173,7 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_req (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -191,7 +193,7 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_re (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -218,25 +220,25 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p (void) itf; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // If request is for our feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; + mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); return true; - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; + volume[channelNum] = (uint16_t) ((audio20_control_cur_2_t *) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); return true; @@ -297,13 +299,13 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Input terminal (Microphone input) if (entityID == 1) { switch (ctrlSel) { - case AUDIO_TE_CTRL_CONNECTOR: { + case AUDIO20_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. - audio_desc_channel_cluster_t ret; + audio20_desc_channel_cluster_t ret; // Those are dummy values for now ret.bNrChannels = 1; - ret.bmChannelConfig = (audio_channel_config_t) 0; + ret.bmChannelConfig = (audio20_channel_config_t) 0; ret.iChannelNames = 0; TU_LOG2(" Get terminal connector\r\n"); @@ -321,24 +323,23 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) - ret; + audio20_control_range_2_n_t(1) ret; ret.wNumSubRanges = 1; ret.subrange[0].bMin = -90;// -90 dB @@ -364,15 +365,15 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Clock Source unit if (entityID == 4) { switch (ctrlSel) { - case AUDIO_CS_CTRL_SAM_FREQ: + case AUDIO20_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); // Buffered control transfer is needed for IN flow control to work return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG2(" Get Sample Freq. range\r\n"); return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); @@ -383,7 +384,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } break; - case AUDIO_CS_CTRL_CLK_VALID: + case AUDIO20_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request TU_LOG2(" Get Sample Freq. valid\r\n"); return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); @@ -407,7 +408,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return;// not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index 0ee3ba2d0..085f9d168 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -105,14 +105,10 @@ extern "C" { // Have a look into audio_device.h for all configurations #define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN - -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 - #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 @@ -123,4 +119,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_4_channel_mic/src/usb_descriptors.c b/examples/device/audio_4_channel_mic/src/usb_descriptors.c index 728a5f9ce..00337eee7 100644 --- a/examples/device/audio_4_channel_mic/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -80,7 +80,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_FOUR_CH_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO20_MIC_FOUR_CH_DESC_LEN) #if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -101,7 +101,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) + TUD_AUDIO20_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -126,7 +126,7 @@ enum { }; // array of pointer to string descriptors -char const* string_desc_arr [] = { +static char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "PaniRCorp", // 1: Manufacturer "MicNode_4_Ch", // 2: Product @@ -156,18 +156,22 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if ( chr_count > max_count ) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { - _desc_str[1 + i] = str[i]; + _desc_str[1 + i] = (uint16_t) str[i]; } break; } diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile index bd625b345..3c421af74 100644 --- a/examples/device/audio_4_channel_mic_freertos/Makefile +++ b/examples/device/audio_4_channel_mic_freertos/Makefile @@ -1,15 +1,15 @@ RTOS = freertos -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ src/main.c \ src/usb_descriptors.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index 30cd46e7e..65925b32c 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -17,3 +17,4 @@ board:lpcxpresso11u37 board:lpcxpresso1347 family:broadcom_32bit family:broadcom_64bit +family:nuc121_125 diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 96eca0be9..4572bbb3c 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -102,8 +102,8 @@ uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio20_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio20_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX * CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000]; @@ -245,7 +245,7 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_req (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -265,7 +265,7 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_re (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -292,25 +292,25 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p (void) itf; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // If request is for our feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; + mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur; TU_LOG1(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); return true; - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - volume[channelNum] = ((audio_control_cur_2_t *) pBuff)->bCur; + volume[channelNum] = ((audio20_control_cur_2_t *) pBuff)->bCur; TU_LOG1(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); return true; @@ -368,9 +368,9 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Input terminal (Microphone input) if (entityID == 1) { switch (ctrlSel) { - case AUDIO_TE_CTRL_CONNECTOR: { + case AUDIO20_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. - audio_desc_channel_cluster_t ret; + audio20_desc_channel_cluster_t ret; // Those are dummy values for now ret.bNrChannels = 1; @@ -392,23 +392,23 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute TU_LOG1(" Get Mute of channel: %u\r\n", channelNum); return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG1(" Get Volume of channel: %u\r\n", channelNum); return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG1(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) ret; + audio20_control_range_2_n_t(1) ret; ret.wNumSubRanges = 1; ret.subrange[0].bMin = -90;// -90 dB @@ -434,15 +434,15 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Clock Source unit if (entityID == 4) { switch (ctrlSel) { - case AUDIO_CS_CTRL_SAM_FREQ: + case AUDIO20_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG1(" Get Sample Freq.\r\n"); // Buffered control transfer is needed for IN flow control to work return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG1(" Get Sample Freq. range\r\n"); return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); @@ -453,7 +453,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } break; - case AUDIO_CS_CTRL_CLK_VALID: + case AUDIO20_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request TU_LOG1(" Get Sample Freq. valid\r\n"); return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h index d973be2af..74729695f 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,14 +111,10 @@ extern "C" { // Have a look into audio_device.h for all configurations #define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN - -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 - #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 @@ -129,4 +125,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c index 728a5f9ce..3bb93f67d 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -80,7 +80,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_FOUR_CH_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO20_MIC_FOUR_CH_DESC_LEN) #if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -101,7 +101,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) + TUD_AUDIO20_MIC_FOUR_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -156,14 +156,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if ( chr_count > max_count ) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/audio_test/Makefile b/examples/device/audio_test/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/audio_test/Makefile +++ b/examples/device/audio_test/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 5b3beec24..2441eefbc 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -63,8 +63,8 @@ uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio20_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio20_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data uint16_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / 2]; @@ -139,7 +139,9 @@ void tud_resume_cb(void) { void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { test_buffer_audio[cnt] = startVal++; @@ -157,7 +159,7 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_req (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -177,7 +179,7 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_re (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -204,25 +206,25 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p (void) itf; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // If request is for our feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; + mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); return true; - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; + volume[channelNum] = (uint16_t) ((audio20_control_cur_2_t *) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); return true; @@ -283,13 +285,13 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Input terminal (Microphone input) if (entityID == 1) { switch (ctrlSel) { - case AUDIO_TE_CTRL_CONNECTOR: { + case AUDIO20_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. - audio_desc_channel_cluster_t ret; + audio20_desc_channel_cluster_t ret; // Those are dummy values for now ret.bNrChannels = 1; - ret.bmChannelConfig = (audio_channel_config_t) 0; + ret.bmChannelConfig = (audio20_channel_config_t) 0; ret.iChannelNames = 0; TU_LOG2(" Get terminal connector\r\n"); @@ -307,23 +309,23 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) + audio20_control_range_2_n_t(1) ret; ret.wNumSubRanges = 1; @@ -350,14 +352,14 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Clock Source unit if (entityID == 4) { switch (ctrlSel) { - case AUDIO_CS_CTRL_SAM_FREQ: + case AUDIO20_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG2(" Get Sample Freq. range\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); @@ -368,7 +370,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } break; - case AUDIO_CS_CTRL_CLK_VALID: + case AUDIO20_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request TU_LOG2(" Get Sample Freq. valid\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); @@ -400,7 +402,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return;// not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 10bf53809..e311d892f 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -108,13 +108,10 @@ extern "C" { // Have a look into audio_device.h for all configurations #define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer - #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! -#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device @@ -122,4 +119,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index 9864377f6..ad161939e 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -80,7 +80,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO20_MIC_ONE_CH_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -101,7 +101,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) + TUD_AUDIO20_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -158,14 +158,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/audio_test_freertos/Makefile b/examples/device/audio_test_freertos/Makefile index bd625b345..3c421af74 100644 --- a/examples/device/audio_test_freertos/Makefile +++ b/examples/device/audio_test_freertos/Makefile @@ -1,15 +1,15 @@ RTOS = freertos -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ src/main.c \ src/usb_descriptors.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 1f3d4281a..c9cdacad7 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -15,3 +15,4 @@ mcu:RAXXX family:broadcom_32bit family:broadcom_64bit board:stm32l0538disco +family:nuc121_125 diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index 1eab5dab8..cf2fb74d1 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -100,8 +100,8 @@ uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio20_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio20_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data uint16_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / 2]; @@ -231,7 +231,7 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_req (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -251,7 +251,7 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_re (void) pBuff; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // Page 91 in UAC2 specification uint8_t channelNum = TU_U16_LOW(p_request->wValue); @@ -278,25 +278,25 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p (void) itf; // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // If request is for our feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; + mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur; TU_LOG1(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); return true; - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; + volume[channelNum] = (uint16_t) ((audio20_control_cur_2_t *) pBuff)->bCur; TU_LOG1(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); return true; @@ -354,13 +354,13 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Input terminal (Microphone input) if (entityID == 1) { switch (ctrlSel) { - case AUDIO_TE_CTRL_CONNECTOR: { + case AUDIO20_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. - audio_desc_channel_cluster_t ret; + audio20_desc_channel_cluster_t ret; // Those are dummy values for now ret.bNrChannels = 1; - ret.bmChannelConfig = (audio_channel_config_t) 0; + ret.bmChannelConfig = (audio20_channel_config_t) 0; ret.iChannelNames = 0; TU_LOG1(" Get terminal connector\r\n"); @@ -378,23 +378,23 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Feature unit if (entityID == 2) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute TU_LOG1(" Get Mute of channel: %u\r\n", channelNum); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG1(" Get Volume of channel: %u\r\n", channelNum); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG1(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) + audio20_control_range_2_n_t(1) ret; ret.wNumSubRanges = 1; @@ -421,14 +421,14 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Clock Source unit if (entityID == 4) { switch (ctrlSel) { - case AUDIO_CS_CTRL_SAM_FREQ: + case AUDIO20_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG1(" Get Sample Freq.\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG1(" Get Sample Freq. range\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); @@ -439,7 +439,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } break; - case AUDIO_CS_CTRL_CLK_VALID: + case AUDIO20_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request TU_LOG1(" Get Sample Freq. valid\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h index c9dc50082..81f0c11f4 100644 --- a/examples/device/audio_test_freertos/src/tusb_config.h +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -114,13 +114,10 @@ extern "C" { // Have a look into audio_device.h for all configurations #define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_DESC_LEN -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer - #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! -#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device @@ -128,4 +125,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test_freertos/src/usb_descriptors.c b/examples/device/audio_test_freertos/src/usb_descriptors.c index 9864377f6..ad161939e 100644 --- a/examples/device/audio_test_freertos/src/usb_descriptors.c +++ b/examples/device/audio_test_freertos/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -80,7 +80,7 @@ enum ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO20_MIC_ONE_CH_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -101,7 +101,7 @@ uint8_t const desc_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) + TUD_AUDIO20_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, /*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX*8, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO_EP_SZ_IN) }; // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -158,14 +158,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/audio_test_multi_rate/Makefile b/examples/device/audio_test_multi_rate/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/audio_test_multi_rate/Makefile +++ b/examples/device/audio_test_multi_rate/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index 9d467991e..baeec870f 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -60,7 +60,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 +int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 uint32_t sampFreq; uint8_t bytesPerSample; uint8_t clkValid; @@ -80,9 +80,6 @@ static const uint8_t bytesPerSampleAltList[CFG_TUD_AUDIO_FUNC_1_N_FORMATS] = CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, }; -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state - - // Audio test data CFG_TUD_MEM_ALIGN uint8_t test_buffer_audio[(TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; uint16_t startVal = 0; @@ -111,9 +108,6 @@ int main(void) { led_blinking_task(); audio_task(); } - - - return 0; } //--------------------------------------------------------------------+ @@ -153,7 +147,9 @@ void tud_resume_cb(void) { void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; // 16bit if (bytesPerSample == 2) { @@ -176,91 +172,204 @@ void audio_task(void) { // Application Callback API Implementations //--------------------------------------------------------------------+ -// Invoked when set interface is called, typically on start/stop streaming or format change -bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - //uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); - uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); +//--------------------------------------------------------------------+ +// UAC1 Helper Functions +//--------------------------------------------------------------------+ - // Clear buffer when streaming format is changed - if (alt != 0) { - bytesPerSample = bytesPerSampleAltList[alt - 1]; +static bool audio10_set_req_ep(tusb_control_request_t const *p_request, uint8_t *pBuff) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + + switch (ctrlSel) { + case AUDIO10_EP_CTRL_SAMPLING_FREQ: + if (p_request->bRequest == AUDIO10_CS_REQ_SET_CUR) { + // Request uses 3 bytes + TU_VERIFY(p_request->wLength == 3); + + sampFreq = tu_unaligned_read32(pBuff) & 0x00FFFFFF; + + TU_LOG2("EP set current freq: %" PRIu32 "\r\n", sampFreq); + + return true; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; } - return true; + + return false; } -// Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - (void) pBuff; +static bool audio10_get_req_ep(uint8_t rhport, tusb_control_request_t const *p_request) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + switch (ctrlSel) { + case AUDIO10_EP_CTRL_SAMPLING_FREQ: + if (p_request->bRequest == AUDIO10_CS_REQ_GET_CUR) { + TU_LOG2("EP get current freq\r\n"); + + uint8_t freq[3]; + freq[0] = (uint8_t) (sampFreq & 0xFF); + freq[1] = (uint8_t) ((sampFreq >> 8) & 0xFF); + freq[2] = (uint8_t) ((sampFreq >> 16) & 0xFF); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, freq, sizeof(freq)); + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + + return false; +} - // Page 91 in UAC2 specification +static bool audio10_set_req_entity(tusb_control_request_t const *p_request, uint8_t *pBuff) { uint8_t channelNum = TU_U16_LOW(p_request->wValue); uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t ep = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - (void) channelNum; - (void) ctrlSel; - (void) ep; + // If request is for our feature unit (ID defined in usbd.h) + if (entityID == 0x02) { + switch (ctrlSel) { + case AUDIO10_FU_CTRL_MUTE: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_SET_CUR: + // Only 1st form is supported + TU_VERIFY(p_request->wLength ==1); - return false;// Yet not implemented -} + mute[channelNum] = pBuff[0]; -// Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; - (void) pBuff; + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + default: + return false; // not supported + } - // Page 91 in UAC2 specification + case AUDIO10_FU_CTRL_VOLUME: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_SET_CUR: + // Only 1st form is supported + TU_VERIFY(p_request->wLength == 2); + + volume[channelNum] = (int16_t)tu_unaligned_read16(pBuff) / 256; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; + + default: + return false; // not supported + } + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + return false; +} + +static bool audio10_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) { uint8_t channelNum = TU_U16_LOW(p_request->wValue); uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // If request is for our feature unit (ID defined in usbd.h) + if (entityID == 0x02) { + switch (ctrlSel) { + case AUDIO10_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); - (void) channelNum; - (void) ctrlSel; - (void) itf; + case AUDIO10_FU_CTRL_VOLUME: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_GET_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + { + int16_t vol = (int16_t) volume[channelNum]; + vol = vol * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &vol, sizeof(vol)); + } - return false;// Yet not implemented + case AUDIO10_CS_REQ_GET_MIN: + TU_LOG2(" Get Volume min of channel: %u\r\n", channelNum); + { + int16_t min = -90; // -90 dB + min = min * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &min, sizeof(min)); + } + + case AUDIO10_CS_REQ_GET_MAX: + TU_LOG2(" Get Volume max of channel: %u\r\n", channelNum); + { + int16_t max = 30; // +30 dB + max = max * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &max, sizeof(max)); + } + + case AUDIO10_CS_REQ_GET_RES: + TU_LOG2(" Get Volume res of channel: %u\r\n", channelNum); + { + int16_t res = 1; // 1 dB + res = res * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &res, sizeof(res)); + } + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + return false; } -// Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { - (void) rhport; +//--------------------------------------------------------------------+ +// UAC2 Helper Functions +//--------------------------------------------------------------------+ + +#if TUD_OPT_HIGH_SPEED - // Page 91 in UAC2 specification +static bool audio20_set_req_entity(tusb_control_request_t const *p_request, uint8_t *pBuff) { uint8_t channelNum = TU_U16_LOW(p_request->wValue); uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - (void) itf; - // We do not support any set range requests here, only current value requests - TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(p_request->bRequest == AUDIO20_CS_REQ_CUR); // If request is for our feature unit if (entityID == UAC2_ENTITY_FEATURE_UNIT) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Request uses format layout 1 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; + mute[channelNum] = ((audio20_control_cur_1_t *) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); return true; - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: // Request uses format layout 2 - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; + volume[channelNum] = (int16_t) ((audio20_control_cur_2_t *) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); return true; @@ -275,10 +384,10 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Clock Source unit if (entityID == UAC2_ENTITY_CLOCK) { switch (ctrlSel) { - case AUDIO_CS_CTRL_SAM_FREQ: - TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_4_t)); + case AUDIO20_CS_CTRL_SAM_FREQ: + TU_VERIFY(p_request->wLength == sizeof(audio20_control_cur_4_t)); - sampFreq = (uint32_t) ((audio_control_cur_4_t *) pBuff)->bCur; + sampFreq = (uint32_t) ((audio20_control_cur_4_t *) pBuff)->bCur; TU_LOG2("Clock set current freq: %" PRIu32 "\r\n", sampFreq); @@ -292,59 +401,20 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } } - return false;// Yet not implemented + return false; } -// Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification +static bool audio20_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) { uint8_t channelNum = TU_U16_LOW(p_request->wValue); uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t ep = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) ep; - - // return tud_control_xfer(rhport, p_request, &tmp, 1); - - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - uint8_t itf = TU_U16_LOW(p_request->wIndex); - - (void) channelNum; - (void) ctrlSel; - (void) itf; - - return false;// Yet not implemented -} - -// Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - // Page 91 in UAC2 specification - uint8_t channelNum = TU_U16_LOW(p_request->wValue); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - // uint8_t itf = TU_U16_LOW(p_request->wIndex); // Since we have only one audio function implemented, we do not need the itf value uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Input terminal (Microphone input) if (entityID == UAC2_ENTITY_INPUT_TERMINAL) { switch (ctrlSel) { - case AUDIO_TE_CTRL_CONNECTOR: { + case AUDIO20_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. - audio_desc_channel_cluster_t ret; + audio20_desc_channel_cluster_t ret; // Those are dummy values for now ret.bNrChannels = 1; @@ -366,23 +436,23 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Feature unit if (entityID == UAC2_ENTITY_FEATURE_UNIT) { switch (ctrlSel) { - case AUDIO_FU_CTRL_MUTE: + case AUDIO20_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); - case AUDIO_FU_CTRL_VOLUME: + case AUDIO20_FU_CTRL_VOLUME: switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); - case AUDIO_CS_REQ_RANGE: + case AUDIO20_CS_REQ_RANGE: TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) + audio20_control_range_2_n_t(1) ret; ret.wNumSubRanges = 1; @@ -409,16 +479,16 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p // Clock Source unit if (entityID == UAC2_ENTITY_CLOCK) { switch (ctrlSel) { - case AUDIO_CS_CTRL_SAM_FREQ: + case AUDIO20_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case switch (p_request->bRequest) { - case AUDIO_CS_REQ_CUR: + case AUDIO20_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: { + case AUDIO20_CS_REQ_RANGE: { TU_LOG2(" Get Sample Freq. range\r\n"); - audio_control_range_4_n_t(N_sampleRates) rangef = + audio20_control_range_4_n_t(N_sampleRates) rangef = { .wNumSubRanges = tu_htole16(N_sampleRates)}; TU_LOG1("Clock get %d freq ranges\r\n", N_sampleRates); @@ -437,7 +507,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } break; - case AUDIO_CS_CTRL_CLK_VALID: + case AUDIO20_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request TU_LOG2(" Get Sample Freq. valid\r\n"); return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); @@ -449,7 +519,82 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } } - TU_LOG2(" Unsupported entity: %d\r\n", entityID); + return false; +} + +#endif // TUD_OPT_HIGH_SPEED + +//--------------------------------------------------------------------+ +// Main Callback Functions +//--------------------------------------------------------------------+ + +// Invoked when set interface is called, typically on start/stop streaming or format change +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + //uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); + uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); + + // Clear buffer when streaming format is changed + if (alt != 0) { + bytesPerSample = bytesPerSampleAltList[alt - 1]; + } + return true; +} + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { + (void) rhport; + (void) pBuff; + + if (tud_audio_version() == 1) { + return audio10_set_req_ep(p_request, pBuff); + } else if (tud_audio_version() == 2) { + // We do not support any requests here + } + + return false;// Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_get_req_ep(rhport, p_request); + } else if (tud_audio_version() == 2) { + // We do not support any requests here + } + + return false;// Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_set_req_entity(p_request, pBuff); +#if TUD_OPT_HIGH_SPEED + } else if (tud_audio_version() == 2) { + return audio20_set_req_entity(p_request, pBuff); +#endif + } + + return false;// Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_get_req_entity(rhport, p_request); +#if TUD_OPT_HIGH_SPEED + } else if (tud_audio_version() == 2) { + return audio20_get_req_entity(rhport, p_request); +#endif + } + return false;// Yet not implemented } @@ -469,7 +614,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return;// not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/audio_test_multi_rate/src/tusb_config.h b/examples/device/audio_test_multi_rate/src/tusb_config.h index b48c0a0be..3587ae089 100644 --- a/examples/device/audio_test_multi_rate/src/tusb_config.h +++ b/examples/device/audio_test_multi_rate/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -116,26 +116,31 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX 2 #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16 -// 24bit in 32bit slots +// 24bit in 32bit slots (UAC2 only) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 4 #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 24 // Have a look into audio_device.h for all configurations -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESC_LEN -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // Size of control request buffer +#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! -#define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! +// UAC1 (Full-Speed) Endpoint size calculation +#define CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(false, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +// UAC2 (High-Speed) Endpoint size calculation +#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX // Example write FIFO every 1ms, so it should be 8 times larger for HS device +// Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, TU_MAX(CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN)) + +// Tx flow control needs buffer size >= 4* EP size to work correctly +// Example write FIFO every 1ms (8 HS frames), so buffer size should be 8 times larger for HS device +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(4 * CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, TU_MAX(32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, 32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN)) #ifdef __cplusplus } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.c b/examples/device/audio_test_multi_rate/src/usb_descriptors.c index f50e70a25..505936fdb 100644 --- a/examples/device/audio_test_multi_rate/src/usb_descriptors.c +++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.c @@ -34,15 +34,14 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, @@ -67,23 +66,19 @@ tusb_desc_device_t const desc_device = // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ +uint8_t const * tud_descriptor_device_cb(void) { return (uint8_t const *) &desc_device; } //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -enum -{ +enum { ITF_NUM_AUDIO_CONTROL = 0, ITF_NUM_AUDIO_STREAMING, ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESC_LEN) - #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... @@ -97,24 +92,81 @@ enum #define EPNUM_AUDIO 0x01 #endif -uint8_t const desc_configuration[] = -{ +#define CONFIG_UAC1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO10_MIC_ONE_CH_DESC_LEN(3)) + +uint8_t const desc_uac1_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC1_TOTAL_LEN, 0x00, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO10_MIC_ONE_CH_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_nBytesPerSample*/ 2, /*_nBitsUsedPerSample*/ 16, /*_epin*/ 0x80 | EPNUM_AUDIO, /*_epsize*/ CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, 32000, 48000, 96000) +}; + +TU_VERIFY_STATIC(sizeof(desc_uac1_configuration) == CONFIG_UAC1_TOTAL_LEN, "Incorrect size"); + +#if TUD_OPT_HIGH_SPEED +#define CONFIG_UAC2_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO20_MIC_ONE_CH_2_FORMAT_DESC_LEN) + +uint8_t const desc2_uac2_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC2_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_epin*/ 0x80 | EPNUM_AUDIO) + TUD_AUDIO20_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_stridx*/ 0, /*_epin*/ 0x80 | EPNUM_AUDIO) +}; + +TU_VERIFY_STATIC(sizeof(desc2_uac2_configuration) == CONFIG_UAC2_TOTAL_LEN, "Incorrect size"); + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = 0x0200, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 }; -TU_VERIFY_STATIC(sizeof(desc_configuration) == CONFIG_TOTAL_LEN, "Incorrect size"); +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const *tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const *) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index;// for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_uac1_configuration : desc2_uac2_configuration; +} + +#endif// highspeed // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + if(tud_speed_get() == TUSB_SPEED_FULL) { + return desc_uac1_configuration; + } else { + return desc2_uac2_configuration; + } +#else + return desc_uac1_configuration; +#endif } //--------------------------------------------------------------------+ @@ -130,8 +182,7 @@ enum { }; // array of pointer to string descriptors -char const* string_desc_arr [] = -{ +char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "PaniRCorp", // 1: Manufacturer "MicNode", // 2: Product @@ -162,14 +213,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.h b/examples/device/audio_test_multi_rate/src/usb_descriptors.h index 8381e31f5..948a7f4ae 100644 --- a/examples/device/audio_test_multi_rate/src/usb_descriptors.h +++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.h @@ -23,8 +23,8 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ // #include "tusb.h" @@ -35,68 +35,68 @@ #define UAC2_ENTITY_FEATURE_UNIT 0x02 -#define TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ +#define TUD_AUDIO20_MIC_ONE_CH_2_FORMAT_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\ + + TUD_AUDIO20_DESC_STD_AC_LEN\ + + TUD_AUDIO20_DESC_CS_AC_LEN\ + + TUD_AUDIO20_DESC_CLK_SRC_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1)\ /* Interface 1, Alternate 0 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ /* Interface 1, Alternate 1 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ /* Interface 1, Alternate 2 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(_itfnum, _stridx, _epin) \ +#define TUD_AUDIO20_MIC_ONE_CH_2_FORMAT_DESCRIPTOR(_itfnum, _stridx, _epin) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1), /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK, /*_ctrl*/ AUDIO_CTRL_RW << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS | AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS, /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ AUDIO20_CLOCK_SOURCE_ATT_INT_PRO_CLK, /*_ctrl*/ AUDIO20_CTRL_RW << AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS | AUDIO20_CTRL_R << AUDIO20_CLOCK_SOURCE_CTRL_CLK_VAL_POS, /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_INPUT_TERMINAL, /*_srcid*/ UAC2_ENTITY_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_INPUT_TERMINAL, /*_srcid*/ UAC2_ENTITY_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ UAC2_ENTITY_FEATURE_UNIT, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ UAC2_ENTITY_FEATURE_UNIT, /*_srcid*/ 0x01, /*_stridx*/ 0x00, /*_ctrlch0master*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Interface 1, Alternate 2 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN, /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) #endif diff --git a/examples/device/board_test/Makefile b/examples/device/board_test/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/board_test/Makefile +++ b/examples/device/board_test/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index d91a8760e..ee0829e5b 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -66,12 +66,12 @@ int main(void) { printf(HELLO_STR); #ifndef LOGGER_UART - board_uart_write(HELLO_STR, strlen(HELLO_STR)); + board_uart_write(HELLO_STR, sizeof(HELLO_STR)-1); #endif } board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = !led_state; // toggle } } } diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 81829d450..97ec65f66 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -74,4 +74,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_dual_ports/Makefile b/examples/device/cdc_dual_ports/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/cdc_dual_ports/Makefile +++ b/examples/device/cdc_dual_ports/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index 8fe003f21..5ccb06a8a 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -75,10 +75,14 @@ static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count) { for (uint32_t i = 0; i < count; i++) { if (itf == 0) { // echo back 1st port as lower case - if (isupper(buf[i])) buf[i] += case_diff; + if (isupper(buf[i])) { + buf[i] += case_diff; + } } else { // echo back 2nd port as upper case - if (islower(buf[i])) buf[i] -= case_diff; + if (islower(buf[i])) { + buf[i] -= case_diff; + } } tud_cdc_n_write_char(itf, buf[i]); @@ -153,7 +157,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 7f7df3909..0da4032a7 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -110,4 +110,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index bbcb479f5..e6011c35a 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -127,7 +127,7 @@ enum { #define EPNUM_CDC_1_IN 0x84 #endif -uint8_t const desc_fs_configuration[] = { +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -140,7 +140,7 @@ uint8_t const desc_fs_configuration[] = { #if TUD_OPT_HIGH_SPEED // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration -uint8_t const desc_hs_configuration[] = { +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -152,9 +152,9 @@ uint8_t const desc_hs_configuration[] = { }; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, +static tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = USB_BCD, .bDeviceClass = TUSB_CLASS_MISC, @@ -213,7 +213,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = { +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product diff --git a/examples/device/cdc_msc/Makefile b/examples/device/cdc_msc/Makefile index 0c2e37180..de50d118f 100644 --- a/examples/device/cdc_msc/Makefile +++ b/examples/device/cdc_msc/Makefile @@ -1,8 +1,8 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ @@ -10,6 +10,6 @@ EXAMPLE_SOURCE += \ src/msc_disk.c \ src/usb_descriptors.c \ -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index 4e7aa989e..e4a205533 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -37,11 +37,12 @@ */ enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; +static bool blink_enable = true; void led_blinking_task(void); void cdc_task(void); @@ -51,10 +52,7 @@ int main(void) { board_init(); // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); @@ -85,7 +83,7 @@ void tud_umount_cb(void) { // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus void tud_suspend_cb(bool remote_wakeup_en) { - (void) remote_wakeup_en; + (void)remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } @@ -106,9 +104,9 @@ void cdc_task(void) { // connected and there are data available if (tud_cdc_available()) { // read data - char buf[64]; + char buf[64]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); - (void) count; + (void)count; // Echo back // Note: Skip echo by commenting out write() and write_flush() @@ -119,10 +117,12 @@ void cdc_task(void) { } // Press on-board button to send Uart status notification + static cdc_notify_uart_state_t uart_state = {.value = 0}; + static uint32_t btn_prev = 0; - static cdc_notify_uart_state_t uart_state = { .value = 0 }; - const uint32_t btn = board_button_read(); - if (!btn_prev && btn) { + const uint32_t btn = board_button_read(); + + if ((btn_prev == 0u) && (btn != 0u)) { uart_state.dsr ^= 1; tud_cdc_notify_uart_state(&uart_state); } @@ -132,33 +132,39 @@ void cdc_task(void) { // Invoked when cdc when line state changed e.g connected/disconnected void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - (void) itf; - (void) rts; + (void)itf; + (void)rts; - // TODO set some indicator if (dtr) { // Terminal connected + blink_enable = false; + board_led_write(true); } else { // Terminal disconnected + blink_enable = true; } } // Invoked when CDC interface received data from host void tud_cdc_rx_cb(uint8_t itf) { - (void) itf; + (void)itf; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ void led_blinking_task(void) { - static uint32_t start_ms = 0; - static bool led_state = false; + static uint32_t start_ms = 0; + static bool led_state = false; - // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time - start_ms += blink_interval_ms; + if (blink_enable) { + // Blink every interval ms + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } + start_ms += blink_interval_ms; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + board_led_write(led_state); + led_state = !led_state; + } } diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 96f9f19ec..e091c2985 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -45,6 +45,7 @@ enum { DISK_BLOCK_SIZE = 512 }; +static #ifdef CFG_EXAMPLE_MSC_READONLY const #endif @@ -57,63 +58,64 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC"; // FAT magic code at offset 510-511 -{ - 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, - 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T', 'i', 'n', 'y', 'U', - 'S', 'B', ' ', 'M', 'S', 'C', 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, + { + 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, + 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T', 'i', 'n', 'y', 'U', + 'S', 'B', ' ', 'M', 'S', 'C', 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, - // Zero up to 2 last bytes of FAT magic code - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Zero up to 2 last bytes of FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA}, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA + }, //------------- Block1: FAT12 Table -------------// -{ - 0xF8, 0xFF, 0xFF, 0xFF, 0x0F// // first 2 entries must be F8FF, third entry is cluster end of readme file + { + 0xF8, 0xFF, 0xFF, 0xFF, 0x0F// first 2 entries must be F8FF, third entry is cluster end of readme file }, //------------- Block2: Root Directory -------------// -{ - // first entry is volume label - 'T', 'i', 'n', 'y', 'U', 'S', 'B', ' ', 'M', 'S', 'C', 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // second entry is readme file - 'R', 'E', 'A', 'D', 'M', 'E', ' ', ' ', 'T', 'X', 'T', 0x20, 0x00, 0xC6, 0x52, 0x6D, - 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, - sizeof(README_CONTENTS) - 1, 0x00, 0x00, 0x00// readme's files size (4 Bytes) + { + // first entry is volume label + 'T', 'i', 'n', 'y', 'U', 'S', 'B', ' ', 'M', 'S', 'C', 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // second entry is readme file + 'R', 'E', 'A', 'D', 'M', 'E', ' ', ' ', 'T', 'X', 'T', 0x20, 0x00, 0xC6, 0x52, 0x6D, + 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, + sizeof(README_CONTENTS) - 1, 0x00, 0x00, 0x00// readme's files size (4 Bytes) }, //------------- Block3: Readme Content -------------// - README_CONTENTS + {README_CONTENTS} }; // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response @@ -126,9 +128,9 @@ uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uin const char pid[] = "Mass Storage"; const char rev[] = "1.0"; - memcpy(inquiry_resp->vendor_id, vid, strlen(vid)); - memcpy(inquiry_resp->product_id, pid, strlen(pid)); - memcpy(inquiry_resp->product_rev, rev, strlen(rev)); + (void) strncpy((char*) inquiry_resp->vendor_id, vid, 8); + (void) strncpy((char*) inquiry_resp->product_id, pid, 16); + (void) strncpy((char*) inquiry_resp->product_rev, rev, 4); return sizeof(scsi_inquiry_resp_t); // 36 bytes } @@ -141,8 +143,7 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) { // RAM disk is ready until ejected if (ejected) { // Additional Sense 3A-00 is NOT_FOUND - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); - return false; + return tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); } return true; @@ -152,7 +153,6 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) { // Application update block count and block size void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) { (void) lun; - *block_count = DISK_BLOCK_NUM; *block_size = DISK_BLOCK_SIZE; } @@ -192,7 +192,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff } uint8_t const *addr = msc_disk[lba] + offset; - memcpy(buffer, addr, bufsize); + (void) memcpy(buffer, addr, bufsize); return (int32_t) bufsize; } @@ -213,11 +213,13 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * (void) lun; // out of ramdisk - if (lba >= DISK_BLOCK_NUM) return -1; + if (lba >= DISK_BLOCK_NUM) { + return -1; + } #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t *addr = msc_disk[lba] + offset; - memcpy(addr, buffer, bufsize); + (void) memcpy(addr, buffer, bufsize); #else (void) lba; (void) offset; @@ -231,17 +233,17 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) { + (void) lun; + (void) scsi_cmd; (void) buffer; (void) bufsize; - switch (scsi_cmd[0]) { - default: - // Set Sense = Invalid Command Operation - tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + // currently no other commands is supported - // negative means error -> tinyusb could stall and/or response with failed status - return -1; - } + // Set Sense = Invalid Command Operation + (void) tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + + return -1; // stall/failed command request; } #endif diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 811d464e9..fdb2ddf18 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -113,4 +113,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index edcee0462..c668ea3a7 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -125,7 +125,7 @@ enum { #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) // full speed configuration -uint8_t const desc_fs_configuration[] = { +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -140,7 +140,7 @@ uint8_t const desc_fs_configuration[] = { // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration // high speed configuration -uint8_t const desc_hs_configuration[] = { +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -152,10 +152,10 @@ uint8_t const desc_hs_configuration[] = { }; // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = USB_BCD, @@ -184,7 +184,7 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, CONFIG_TOTAL_LEN); @@ -223,7 +223,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = { +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile index 10cff57a0..dbab13395 100644 --- a/examples/device/cdc_msc_freertos/Makefile +++ b/examples/device/cdc_msc_freertos/Makefile @@ -1,9 +1,9 @@ RTOS = freertos -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ @@ -11,6 +11,6 @@ EXAMPLE_SOURCE = \ src/msc_disk.c \ src/usb_descriptors.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index b73a6d8dd..69fc883e6 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -15,3 +15,4 @@ mcu:RAXXX mcu:STM32L0 family:broadcom_32bit family:broadcom_64bit +family:nuc121_125 diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 69f2435ba..4fb209fd0 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -37,7 +37,7 @@ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define CDC_STACK_SIZE configMINIMAL_STACK_SIZE +#define CDC_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1)) #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index 849712e6a..29ff86281 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -76,6 +76,7 @@ enum { DISK_BLOCK_SIZE = 512 }; +static #ifdef CFG_EXAMPLE_MSC_READONLY const #endif @@ -198,9 +199,9 @@ uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp, uin const char pid[] = "Mass Storage"; const char rev[] = "1.0"; - memcpy(inquiry_resp->vendor_id, vid, strlen(vid)); - memcpy(inquiry_resp->product_id, pid, strlen(pid)); - memcpy(inquiry_resp->product_rev, rev, strlen(rev)); + strncpy((char*) inquiry_resp->vendor_id, vid, 8); + strncpy((char*) inquiry_resp->product_id, pid, 16); + strncpy((char*) inquiry_resp->product_rev, rev, 4); return sizeof(scsi_inquiry_resp_t); // 36 bytes } @@ -299,13 +300,11 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* return TUD_MSC_RET_ERROR; } - #ifdef CFG_EXAMPLE_MSC_READONLY +#ifdef CFG_EXAMPLE_MSC_READONLY (void) lun; (void) buffer; return bufsize; - #endif - - #if CFG_EXAMPLE_MSC_ASYNC_IO +#elif CFG_EXAMPLE_MSC_ASYNC_IO io_ops_t io_ops = {.is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize}; // Send IO operation to IO task @@ -318,7 +317,7 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); return bufsize; - #endif +#endif } // Callback invoked when received an SCSI command not in built-in list below @@ -326,12 +325,8 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // - READ10 and WRITE10 has their own callbacks int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { // read10 & write10 has their own callback and MUST not be handled here - - void const *response = NULL; - int32_t resplen = 0; - - // most scsi handled is input - bool in_xfer = true; + (void) buffer; + (void) bufsize; switch (scsi_cmd[0]) { default: @@ -339,22 +334,10 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // negative means error -> tinyusb could stall and/or response with failed status - resplen = -1; - break; - } - - // return resplen must not larger than bufsize - if (resplen > bufsize) { resplen = bufsize; } - - if (response && (resplen > 0)) { - if (in_xfer) { - memcpy(buffer, response, (size_t) resplen); - } else { - // SCSI output - } + return -1; } - return (int32_t) resplen; + return -1; } #endif diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index 9cc3a18d1..6b1937a8d 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -120,4 +120,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index a55fa3675..4950f02e0 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -124,7 +124,7 @@ enum { #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) -uint8_t const desc_fs_configuration[] = +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -140,7 +140,7 @@ uint8_t const desc_fs_configuration[] = // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration // high speed configuration -uint8_t const desc_hs_configuration[] = +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -153,10 +153,10 @@ uint8_t const desc_hs_configuration[] = }; // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, @@ -186,7 +186,7 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, CONFIG_TOTAL_LEN); @@ -225,7 +225,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = { +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product diff --git a/examples/device/cdc_uac2/Makefile b/examples/device/cdc_uac2/Makefile index 21dcdb0b2..6276be8d0 100644 --- a/examples/device/cdc_uac2/Makefile +++ b/examples/device/cdc_uac2/Makefile @@ -1,8 +1,8 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ @@ -11,6 +11,6 @@ EXAMPLE_SOURCE += \ src/uac2_app.c \ src/usb_descriptors.c \ -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/cdc_uac2/src/cdc_app.c b/examples/device/cdc_uac2/src/cdc_app.c index 2166c1d6b..6d18a0e69 100644 --- a/examples/device/cdc_uac2/src/cdc_app.c +++ b/examples/device/cdc_uac2/src/cdc_app.c @@ -29,33 +29,26 @@ #include "common.h" // Invoked when cdc when line state changed e.g connected/disconnected -void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) -{ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; (void) rts; - if (dtr) - { + if (dtr) { // Terminal connected - } - else - { + } else { // Terminal disconnected } } // Invoked when CDC interface received data from host -void tud_cdc_rx_cb(uint8_t itf) -{ +void tud_cdc_rx_cb(uint8_t itf) { uint8_t buf[64]; uint32_t count; // connected() check for DTR bit // Most but not all terminal client set this when making connection - if (tud_cdc_connected()) - { - if (tud_cdc_available()) // data is available - { + if (tud_cdc_connected()) { + if (tud_cdc_available() > 0) { count = tud_cdc_n_read(itf, buf, sizeof(buf)); (void) count; diff --git a/examples/device/cdc_uac2/src/common.h b/examples/device/cdc_uac2/src/common.h index f281024c7..ff8b7a953 100644 --- a/examples/device/cdc_uac2/src/common.h +++ b/examples/device/cdc_uac2/src/common.h @@ -31,4 +31,7 @@ enum VOLUME_CTRL_SILENCE = 0x8000, }; +void led_blinking_task(void); +void audio_task(void); + #endif diff --git a/examples/device/cdc_uac2/src/main.c b/examples/device/cdc_uac2/src/main.c index bc87f6e3c..22c462be7 100644 --- a/examples/device/cdc_uac2/src/main.c +++ b/examples/device/cdc_uac2/src/main.c @@ -38,9 +38,6 @@ extern uint32_t blink_interval_ms; #include "pico/stdlib.h" #endif -void led_blinking_task(void); -void audio_task(void); - /*------------- MAIN -------------*/ int main(void) { diff --git a/examples/device/cdc_uac2/src/tusb_config.h b/examples/device/cdc_uac2/src/tusb_config.h index 2e744f8d2..b7ece8b7c 100644 --- a/examples/device/cdc_uac2/src/tusb_config.h +++ b/examples/device/cdc_uac2/src/tusb_config.h @@ -24,8 +24,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -105,8 +105,6 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN - // How many formats are used, need to adjust USB descriptor if changed #define CFG_TUD_AUDIO_FUNC_1_N_FORMATS 2 @@ -142,8 +140,8 @@ extern "C" { // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device @@ -151,15 +149,12 @@ extern "C" { // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device -// Size of control request buffer -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 - // 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) @@ -171,4 +166,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index a1a0dd73d..73a262d0c 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -67,7 +67,9 @@ uint8_t current_resolution; void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; // When new data arrived, copy data from speaker buffer, to microphone buffer // and send it over @@ -80,22 +82,22 @@ void audio_task(void) { } // Helper for clock get requests -static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) +static bool tud_audio_clock_get_request(uint8_t rhport, audio20_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) + if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) { - if (request->bRequest == AUDIO_CS_REQ_CUR) + if (request->bRequest == AUDIO20_CS_REQ_CUR) { TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); - audio_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; + audio20_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); } - else if (request->bRequest == AUDIO_CS_REQ_RANGE) + else if (request->bRequest == AUDIO20_CS_REQ_RANGE) { - audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = + audio20_control_range_4_n_t(N_SAMPLE_RATES) rangef = { .wNumSubRanges = tu_htole16(N_SAMPLE_RATES) }; @@ -111,10 +113,10 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef)); } } - else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && - request->bRequest == AUDIO_CS_REQ_CUR) + else if (request->bControlSelector == AUDIO20_CS_CTRL_CLK_VALID && + request->bRequest == AUDIO20_CS_REQ_CUR) { - audio_control_cur_1_t cur_valid = { .bCur = 1 }; + audio20_control_cur_1_t cur_valid = { .bCur = 1 }; TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid)); } @@ -124,18 +126,18 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t } // Helper for clock set requests -static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) +static bool tud_audio_clock_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) { (void)rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) + if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_4_t)); - current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur; + current_sample_rate = (uint32_t) ((audio20_control_cur_4_t const *)buf)->bCur; TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); @@ -150,21 +152,21 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t } // Helper for feature unit get requests -static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) +static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio20_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) + if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE && request->bRequest == AUDIO20_CS_REQ_CUR) { - audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] }; + audio20_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] }; TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1)); } - else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) + else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) { - if (request->bRequest == AUDIO_CS_REQ_RANGE) + if (request->bRequest == AUDIO20_CS_REQ_RANGE) { - audio_control_range_2_n_t(1) range_vol = { + audio20_control_range_2_n_t(1) range_vol = { .wNumSubRanges = tu_htole16(1), .subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) } }; @@ -172,9 +174,9 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol)); } - else if (request->bRequest == AUDIO_CS_REQ_CUR) + else if (request->bRequest == AUDIO20_CS_REQ_CUR) { - audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) }; + audio20_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) }; TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol)); } @@ -186,28 +188,28 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req } // Helper for feature unit set requests -static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) +static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) { (void)rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); - TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) + if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t)); + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_1_t)); - mute[request->bChannelNumber] = ((audio_control_cur_1_t const *)buf)->bCur; + mute[request->bChannelNumber] = ((audio20_control_cur_1_t const *)buf)->bCur; TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; } - else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) + else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_2_t)); + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_2_t)); - volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur; + volume[request->bChannelNumber] = ((audio20_control_cur_2_t const *)buf)->bCur; TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); @@ -226,16 +228,15 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req //--------------------------------------------------------------------+ // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) -{ - audio_control_request_t const *request = (audio_control_request_t const *)p_request; +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + audio20_control_request_t const *request = (audio20_control_request_t const *)p_request; - if (request->bEntityID == UAC2_ENTITY_CLOCK) + if (request->bEntityID == UAC2_ENTITY_CLOCK) { return tud_audio_clock_get_request(rhport, request); - if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) + } + if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) { return tud_audio_feature_unit_get_request(rhport, request); - else - { + } else { TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); } @@ -243,14 +244,15 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) -{ - audio_control_request_t const *request = (audio_control_request_t const *)p_request; +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { + audio20_control_request_t const *request = (audio20_control_request_t const *)p_request; - if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) + if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) { return tud_audio_feature_unit_set_request(rhport, request, buf); - if (request->bEntityID == UAC2_ENTITY_CLOCK) + } + if (request->bEntityID == UAC2_ENTITY_CLOCK) { return tud_audio_clock_set_request(rhport, request, buf); + } TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); @@ -301,7 +303,9 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; + if (board_millis() - start_ms < blink_interval_ms) { + return; + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/cdc_uac2/src/usb_descriptors.c b/examples/device/cdc_uac2/src/usb_descriptors.c index 22d3cf05a..e6caaa971 100644 --- a/examples/device/cdc_uac2/src/usb_descriptors.c +++ b/examples/device/cdc_uac2/src/usb_descriptors.c @@ -35,14 +35,14 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -116,7 +116,7 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_CDC_IN 0x84 #endif -uint8_t const desc_fs_configuration[] = +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -132,7 +132,7 @@ uint8_t const desc_fs_configuration[] = // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration // high speed configuration -uint8_t const desc_hs_configuration[] = { +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -144,10 +144,10 @@ uint8_t const desc_hs_configuration[] = { }; // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = 0x0100, @@ -176,7 +176,7 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, CONFIG_TOTAL_LEN); @@ -215,7 +215,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer @@ -248,14 +248,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/cdc_uac2/src/usb_descriptors.h b/examples/device/cdc_uac2/src/usb_descriptors.h index 736feeefe..139384d3e 100644 --- a/examples/device/cdc_uac2/src/usb_descriptors.h +++ b/examples/device/cdc_uac2/src/usb_descriptors.h @@ -24,8 +24,8 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ // #include "tusb.h" @@ -49,110 +49,110 @@ enum ITF_NUM_TOTAL }; -#define TUD_AUDIO_HEADSET_STEREO_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ +#define TUD_AUDIO_HEADSET_STEREO_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\ + + TUD_AUDIO20_DESC_STD_AC_LEN\ + + TUD_AUDIO20_DESC_CS_AC_LEN\ + + TUD_AUDIO20_DESC_CLK_SRC_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(2)\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ /* Interface 1, Alternate 0 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ /* Interface 1, Alternate 0 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ /* Interface 1, Alternate 2 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ /* Interface 2, Alternate 0 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ /* Interface 2, Alternate 1 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ /* Interface 2, Alternate 2 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN) #define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ 3, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_IAD(/*_firstitfs*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ 3, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(2)+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ + TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrlch0master*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch2*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_stridx*/ 0x00, /*_ctrlch0master*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch2*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS)),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Interface 1, Alternate 2 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ADAPTIVE | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 2, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 2, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Interface 2, Alternate 2 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) (TUSB_XFER_ISOCHRONOUS | TUSB_ISO_EP_ATT_ASYNCHRONOUS | TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) #endif diff --git a/examples/device/dfu/Makefile b/examples/device/dfu/Makefile index 52a24cdb0..9e1eab4a2 100644 --- a/examples/device/dfu/Makefile +++ b/examples/device/dfu/Makefile @@ -1,14 +1,14 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ src/main.c \ src/usb_descriptors.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index c0c848837..77632bf1a 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -23,7 +23,7 @@ * */ - /* +/* * After device is enumerated in dfu mode run the following commands * * To transfer firmware from host to device (best to test with text file) @@ -48,21 +48,18 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -const char* upload_image[2]= -{ - "Hello world from TinyUSB DFU! - Partition 0", - "Hello world from TinyUSB DFU! - Partition 1" -}; +const char *upload_image[2] = {"Hello world from TinyUSB DFU! - Partition 0", + "Hello world from TinyUSB DFU! - Partition 1"}; /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; @@ -70,21 +67,16 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; void led_blinking_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); } @@ -95,29 +87,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void) remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -129,19 +117,17 @@ void tud_resume_cb(void) // Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) // Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. // During this period, USB host won't try to communicate with us. -uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) -{ - if ( state == DFU_DNBUSY ) - { +uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) { + if (state == DFU_DNBUSY) { // For this example // - Atl0 Flash is fast : 1 ms // - Alt1 EEPROM is slow: 100 ms return (alt == 0) ? 1 : 100; - } - else if (state == DFU_MANIFEST) - { + } else if (state == DFU_MANIFEST) { // since we don't buffer entire image and do any flashing in manifest stage return 0; + } else { + // nothing to do } return 0; @@ -150,15 +136,13 @@ uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) // Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests // This callback could be returned before flashing op is complete (async). // Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const* data, uint16_t length) -{ - (void) alt; - (void) block_num; +void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, const uint8_t *data, uint16_t length) { + (void)alt; + (void)block_num; //printf("\r\nReceived Alt %u BlockNum %u of length %u\r\n", alt, wBlockNum, length); - for(uint16_t i=0; i<length; i++) - { + for (uint16_t i = 0; i < length; i++) { printf("%c", data[i]); } @@ -169,9 +153,8 @@ void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const* data, u // Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) // Application can do checksum, or actual flashing if buffered entire image previously. // Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_manifest_cb(uint8_t alt) -{ - (void) alt; +void tud_dfu_manifest_cb(uint8_t alt) { + (void)alt; printf("Download completed, enter manifestation\r\n"); // flashing op for manifest is complete without error @@ -182,27 +165,28 @@ void tud_dfu_manifest_cb(uint8_t alt) // Invoked when received DFU_UPLOAD request // Application must populate data with up to length bytes and // Return the number of written bytes -uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length) -{ - (void) block_num; - (void) length; +uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t *data, uint16_t length) { + (void)block_num; + (void)length; - uint16_t const xfer_len = (uint16_t) strlen(upload_image[alt]); + if (block_num != 0u) { + return 0; // for this example we only support single block upload + } + + const uint16_t xfer_len = tu_min16((uint16_t)strlen(upload_image[alt]), length); memcpy(data, upload_image[alt], xfer_len); return xfer_len; } // Invoked when the Host has terminated a download or upload transfer -void tud_dfu_abort_cb(uint8_t alt) -{ - (void) alt; +void tud_dfu_abort_cb(uint8_t alt) { + (void)alt; printf("Host aborted transfer\r\n"); } // Invoked when a DFU_DETACH request is received -void tud_dfu_detach_cb(void) -{ +void tud_dfu_detach_cb(void) { printf("Host detach, we should probably reboot\r\n"); } @@ -210,13 +194,14 @@ void tud_dfu_detach_cb(void) // BLINKING TASK + Indicator pulse //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - static uint32_t start_ms = 0; - static bool led_state = false; +void led_blinking_task(void) { + static uint32_t start_ms = 0; + static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index fd469aaf2..e4291be2d 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -25,7 +25,6 @@ #include "bsp/board_api.h" #include "tusb.h" -#include "class/dfu/dfu_device.h" /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. @@ -33,49 +32,45 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4)) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, +static const tusb_desc_device_t desc_device = + {.bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0201, - #if CFG_TUD_CDC - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - #else - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - #endif +#if CFG_TUD_CDC + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, +#else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, +#endif - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0100, + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 -}; + .bNumConfigurations = 0x01}; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; +const uint8_t *tud_descriptor_device_cb(void) { + return (const uint8_t *)&desc_device; } //--------------------------------------------------------------------+ @@ -83,20 +78,17 @@ uint8_t const * tud_descriptor_device_cb(void) //--------------------------------------------------------------------+ // Number of Alternate Interface (each for 1 flash partition) -#define ALT_COUNT 2 +#define ALT_COUNT 2 -enum -{ +enum { ITF_NUM_DFU_MODE, ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(ALT_COUNT)) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(ALT_COUNT)) +#define FUNC_ATTRS (DFU_ATTR_CAN_UPLOAD | DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_MANIFESTATION_TOLERANT) -#define FUNC_ATTRS (DFU_ATTR_CAN_UPLOAD | DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_MANIFESTATION_TOLERANT) - -uint8_t const desc_configuration[] = -{ +uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -107,13 +99,91 @@ uint8_t const desc_configuration[] = // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations +const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; // for multiple configurations return desc_configuration; } //--------------------------------------------------------------------+ +// BOS Descriptor +//--------------------------------------------------------------------+ + +/* Microsoft OS 2.0 registry property descriptor + Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx + device should create DeviceInterfaceGUIDs. It can be done by driver and + in case of real PnP solution device should expose MS "Microsoft OS 2.0 + registry property descriptor". Such descriptor can insert any record + into Windows registry per device/configuration/interface. In our case it + will insert "DeviceInterfaceGUIDs" multistring property. + GUID is freshly generated and should be OK to use. + https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/ + (Section Microsoft OS compatibility descriptors) +*/ + +#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) +#define MS_OS_20_DESC_LEN 0xA2 +#define VENDOR_REQUEST_MICROSOFT 1 + +// BOS Descriptor is required for webUSB +const uint8_t desc_bos[] = { + // total length, number of device caps + TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 1), + + // Microsoft OS 2.0 descriptor + TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, 1)}; + +const uint8_t *tud_descriptor_bos_cb(void) { + return desc_bos; +} + +const uint8_t desc_ms_os_20[] = { + // Set header: length, type, windows version, total length + U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), + U16_TO_U8S_LE(MS_OS_20_DESC_LEN), + + // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID + U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible + + // MS OS 2.0 Registry property descriptor: length, type + U16_TO_U8S_LE(MS_OS_20_DESC_LEN - 0x0A - 0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), + U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A),// wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16 + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, + 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00, + U16_TO_U8S_LE(0x0050),// wPropertyDataLength + //bPropertyData: {3E7E0711-DF3B-4158-A32F-E5951B2AB9A1}. + '{', 0x00, '3', 0x00, 'E', 0x00, '7', 0x00, 'E', 0x00, '0', 0x00, '7', 0x00, '1', 0x00, '1', 0x00, '-', 0x00, + 'D', 0x00, 'F', 0x00, '3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, '1', 0x00, '5', 0x00, '8', 0x00, '-', 0x00, + 'A', 0x00, '3', 0x00, '2', 0x00, 'F', 0x00, '-', 0x00, 'E', 0x00, '5', 0x00, '9', 0x00, '5', 0x00, '1', 0x00, + 'B', 0x00, '2', 0x00, 'A', 0x00, 'B', 0x00, '9', 0x00, 'A', 0x00, '1', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size"); + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t *request) { + // nothing to with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) { + return true; + } + + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR) { + if (request->bRequest == VENDOR_REQUEST_MICROSOFT) { + if (request->wIndex == 7) { + return tud_control_xfer(rhport, request, (void *)(uintptr_t)desc_ms_os_20, MS_OS_20_DESC_LEN); + } else { + return false; + } + } + } + + // stall unknown request + return false; +} + +//--------------------------------------------------------------------+ // String Descriptors //--------------------------------------------------------------------+ @@ -126,25 +196,24 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "FLASH", // 4: DFU Partition 1 - "EEPROM", // 5: DFU Partition 2 +static const char *string_desc_arr[] = { + (const char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "FLASH", // 4: DFU Partition 1 + "EEPROM", // 5: DFU Partition 2 }; static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - (void) langid; +const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void)langid; size_t chr_count; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; @@ -158,24 +227,28 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char - chr_count = strlen(str); - size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + chr_count = strlen(str); + const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; } // first byte is length (including header), second byte is string type - _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); return _desc_str; } diff --git a/examples/device/dfu_runtime/Makefile b/examples/device/dfu_runtime/Makefile index 1b4d398cf..1a4b428dc 100644 --- a/examples/device/dfu_runtime/Makefile +++ b/examples/device/dfu_runtime/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/dfu_runtime/src/main.c b/examples/device/dfu_runtime/src/main.c index 37cb80093..5de651bcd 100644 --- a/examples/device/dfu_runtime/src/main.c +++ b/examples/device/dfu_runtime/src/main.c @@ -132,7 +132,9 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/dfu_runtime/src/usb_descriptors.c b/examples/device/dfu_runtime/src/usb_descriptors.c index 7ac53d255..8fa078da2 100644 --- a/examples/device/dfu_runtime/src/usb_descriptors.c +++ b/examples/device/dfu_runtime/src/usb_descriptors.c @@ -25,7 +25,6 @@ #include "bsp/board_api.h" #include "tusb.h" -#include "class/dfu/dfu_rt_device.h" /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. @@ -33,48 +32,45 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4)) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, +static const tusb_desc_device_t desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0201, - #if CFG_TUD_CDC - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - #else - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - #endif +#if CFG_TUD_CDC + // Use Interface Association Descriptor (IAD) for CDC + // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, +#else + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, +#endif - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0100, + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 + .bNumConfigurations = 0x01 }; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ +uint8_t const *tud_descriptor_device_cb(void) { return (uint8_t const *) &desc_device; } @@ -82,16 +78,14 @@ uint8_t const * tud_descriptor_device_cb(void) // Configuration Descriptor //--------------------------------------------------------------------+ -enum -{ +enum { ITF_NUM_DFU_RT, ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_RT_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_RT_DESC_LEN) -uint8_t const desc_configuration[] = -{ +uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -103,13 +97,109 @@ uint8_t const desc_configuration[] = // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { + (void) index;// for multiple configurations return desc_configuration; } //--------------------------------------------------------------------+ +// BOS Descriptor +//--------------------------------------------------------------------+ + +/* Microsoft OS 2.0 registry property descriptor + Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx + device should create DeviceInterfaceGUIDs. It can be done by driver and + in case of real PnP solution device should expose MS "Microsoft OS 2.0 + registry property descriptor". Such descriptor can insert any record + into Windows registry per device/configuration/interface. In our case it + will insert "DeviceInterfaceGUIDs" multistring property. + GUID is freshly generated and should be OK to use. + https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/ + (Section Microsoft OS compatibility descriptors) +*/ + +#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) +#define MS_OS_20_DESC_LEN 0xA2 +#define VENDOR_REQUEST_MICROSOFT 1 + +// BOS Descriptor is required for webUSB +const uint8_t desc_bos[] = { + // total length, number of device caps + TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 1), + + // Microsoft OS 2.0 descriptor + TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, 1)}; + +const uint8_t *tud_descriptor_bos_cb(void) { + return desc_bos; +} + +uint8_t const desc_ms_os_20[] = { + // Set header: length, type, windows version, total length + U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN), + + // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID + U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sub-compatible + + // MS OS 2.0 Registry property descriptor: length, type + U16_TO_U8S_LE(MS_OS_20_DESC_LEN - 0x0A - 0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), + U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A),// wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16 + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, + 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00, + U16_TO_U8S_LE(0x0050),// wPropertyDataLength + //bPropertyData: {F7CC2C68-3B14-4D72-B876-1A981AD2C9E5}. + '{', 0x00, 'F', 0x00, '7', 0x00, 'C', 0x00, 'C', 0x00, '2', 0x00, 'C', 0x00, '6', 0x00, '8', 0x00, '-', 0x00, + '3', 0x00, 'B', 0x00, '1', 0x00, '4', 0x00, '-', 0x00, '4', 0x00, 'D', 0x00, '7', 0x00, '2', 0x00, '-', 0x00, + 'B', 0x00, '8', 0x00, '7', 0x00, '6', 0x00, '-', 0x00, '1', 0x00, 'A', 0x00, '9', 0x00, '8', 0x00, '1', 0x00, + 'A', 0x00, 'D', 0x00, '2', 0x00, 'C', 0x00, '9', 0x00, 'E', 0x00, '5', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size"); + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { + // nothing to with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) { + return true; + } + + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR) { + if (request->bRequest == VENDOR_REQUEST_MICROSOFT) { + if (request->wIndex == 7) { + return tud_control_xfer(rhport, request, (void *)(uintptr_t)desc_ms_os_20, MS_OS_20_DESC_LEN); + } else { + return false; + } + } + } + + switch (request->bmRequestType_bit.type) { + case TUSB_REQ_TYPE_VENDOR: + switch (request->bRequest) { + case VENDOR_REQUEST_MICROSOFT: + if (request->wIndex == 7) { + return tud_control_xfer(rhport, request, (void *) (uintptr_t) desc_ms_os_20, MS_OS_20_DESC_LEN); + } else { + return false; + } + + default: + break; + } + break; + + default: + break; + } + + // stall unknown request + return false; +} + +//--------------------------------------------------------------------+ // String Descriptors //--------------------------------------------------------------------+ @@ -122,24 +212,23 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible - "TinyUSB DFU runtime", // 4: DFU runtime +static char const *string_desc_arr[] = { + (const char[]){0x09, 0x04},// 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "TinyUSB DFU runtime", // 4: DFU runtime }; static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - (void) langid; +const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void)langid; size_t chr_count; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; @@ -153,24 +242,28 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char - chr_count = strlen(str); - size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + chr_count = strlen(str); + const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; } // first byte is length (including header), second byte is string type - _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); return _desc_str; } diff --git a/examples/device/dynamic_configuration/Makefile b/examples/device/dynamic_configuration/Makefile index 1b4d398cf..1a4b428dc 100644 --- a/examples/device/dynamic_configuration/Makefile +++ b/examples/device/dynamic_configuration/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index 258cfcd02..dac74bb7a 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -109,23 +109,18 @@ void tud_resume_cb(void) //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -void cdc_task(void) -{ - if ( tud_cdc_connected() ) - { - // connected and there are data available - if ( tud_cdc_available() ) - { +void cdc_task(void) { + if (tud_cdc_connected()) { + // connected and there are data available read and echo back + if (tud_cdc_available()) { uint8_t buf[64]; - - // read and echo back uint32_t count = tud_cdc_read(buf, sizeof(buf)); - for(uint32_t i=0; i<count; i++) - { + for (uint32_t i = 0; i < count; i++) { tud_cdc_write_char(buf[i]); - - if ( buf[i] == '\r' ) tud_cdc_write_char('\n'); + if (buf[i] == '\r') { + tud_cdc_write_char('\n'); + } } tud_cdc_write_flush(); @@ -134,23 +129,18 @@ void cdc_task(void) } // Invoked when cdc when line state changed e.g connected/disconnected -void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) -{ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; // connected - if ( dtr && rts ) - { + if (dtr && rts) { // print initial message when connected tud_cdc_write_str("\r\nTinyUSB CDC MSC device example\r\n"); } } // Invoked when CDC interface received data from host -void tud_cdc_rx_cb(uint8_t itf) -{ - (void) itf; -} +void tud_cdc_rx_cb(uint8_t itf) { (void) itf; } //--------------------------------------------------------------------+ // MIDI Task @@ -167,8 +157,7 @@ static const uint8_t note_sequence[] = 56,61,64,68,74,78,81,86,90,93,98,102 }; -void midi_task(void) -{ +void midi_task(void) { static uint32_t start_ms = 0; uint8_t const cable_num = 0; // MIDI jack associated with USB endpoint @@ -181,7 +170,9 @@ void midi_task(void) while( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms - if (board_millis() - start_ms < 286) return; // not enough time + if (board_millis() - start_ms < 286) { + return; // not enough time + } start_ms += 286; // Previous positions in the note sequence. @@ -189,7 +180,9 @@ void midi_task(void) // If we currently are at position 0, set the // previous position to the last note in the sequence. - if (previous < 0) previous = sizeof(note_sequence) - 1; + if (previous < 0) { + previous = sizeof(note_sequence) - 1; + } // Send Note On for current position at full velocity (127) on channel 1. uint8_t note_on[3] = { 0x90 | channel, note_sequence[note_pos], 127 }; @@ -203,21 +196,24 @@ void midi_task(void) note_pos++; // If we are at the end of the sequence, start over. - if (note_pos >= sizeof(note_sequence)) note_pos = 0; + if (note_pos >= sizeof(note_sequence)) { + note_pos = 0; + } } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return;// not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state;// toggle } diff --git a/examples/device/dynamic_configuration/src/msc_disk.c b/examples/device/dynamic_configuration/src/msc_disk.c index ebc86e260..e95b2e197 100644 --- a/examples/device/dynamic_configuration/src/msc_disk.c +++ b/examples/device/dynamic_configuration/src/msc_disk.c @@ -43,6 +43,7 @@ enum DISK_BLOCK_SIZE = 512 }; +static #ifdef CFG_EXAMPLE_MSC_READONLY const #endif @@ -126,9 +127,9 @@ uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uin const char pid[] = "Mass Storage"; const char rev[] = "1.0"; - memcpy(inquiry_resp->vendor_id, vid, strlen(vid)); - memcpy(inquiry_resp->product_id, pid, strlen(pid)); - memcpy(inquiry_resp->product_rev, rev, strlen(rev)); + strncpy((char*) inquiry_resp->vendor_id, vid, 8); + strncpy((char*) inquiry_resp->product_id, pid, 16); + strncpy((char*) inquiry_resp->product_rev, rev, 4); return sizeof(scsi_inquiry_resp_t); // 36 bytes } @@ -176,12 +177,13 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. -int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) -{ +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if ( lba >= DISK_BLOCK_NUM ) { + return -1; + } uint8_t const* addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); @@ -191,12 +193,13 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) -{ +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if ( lba >= DISK_BLOCK_NUM ) { + return -1; + } #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[lba] + offset; @@ -211,42 +214,21 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) -{ +int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { // read10 & write10 has their own callback and MUST not be handled here + (void) buffer; + (void) bufsize; - void const* response = NULL; - int32_t resplen = 0; - - // most scsi handled is input - bool in_xfer = true; - - switch (scsi_cmd[0]) - { + switch (scsi_cmd[0]) { default: // Set Sense = Invalid Command Operation tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // negative means error -> tinyusb could stall and/or response with failed status - resplen = -1; - break; - } - - // return resplen must not larger than bufsize - if ( resplen > bufsize ) resplen = bufsize; - - if ( response && (resplen > 0) ) - { - if(in_xfer) - { - memcpy(buffer, response, (size_t) resplen); - }else - { - // SCSI output - } + return -1; } - return resplen; + return -1; } #endif diff --git a/examples/device/dynamic_configuration/src/tusb_config.h b/examples/device/dynamic_configuration/src/tusb_config.h index b9b3878cc..7309d97c9 100644 --- a/examples/device/dynamic_configuration/src/tusb_config.h +++ b/examples/device/dynamic_configuration/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -112,4 +112,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/dynamic_configuration/src/usb_descriptors.c b/examples/device/dynamic_configuration/src/usb_descriptors.c index 0a2049288..458b7c2a5 100644 --- a/examples/device/dynamic_configuration/src/usb_descriptors.c +++ b/examples/device/dynamic_configuration/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) // Configuration mode // 0 : enumerated as CDC/MIDI. Board button is not pressed when enumerating @@ -202,7 +202,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer @@ -232,14 +232,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/hid_boot_interface/Makefile b/examples/device/hid_boot_interface/Makefile index 52a24cdb0..9e1eab4a2 100644 --- a/examples/device/hid_boot_interface/Makefile +++ b/examples/device/hid_boot_interface/Makefile @@ -1,14 +1,14 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ src/main.c \ src/usb_descriptors.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/hid_boot_interface/src/main.c b/examples/device/hid_boot_interface/src/main.c index 45712cede..44a91db67 100644 --- a/examples/device/hid_boot_interface/src/main.c +++ b/examples/device/hid_boot_interface/src/main.c @@ -23,8 +23,8 @@ * */ -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include "bsp/board_api.h" @@ -40,10 +40,10 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; @@ -52,21 +52,16 @@ void led_blinking_task(void); void hid_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); @@ -81,29 +76,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void) remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -113,59 +104,54 @@ void tud_resume_cb(void) // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) // tud_hid_report_complete_cb() is used to send the next report after previous one is complete -void hid_task(void) -{ +void hid_task(void) { // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if (board_millis() - start_ms < interval_ms) { + return; // not enough time + } start_ms += interval_ms; uint32_t const btn = board_button_read(); - if ( tud_suspended() && btn ) - { + if (tud_suspended() && btn) { // Wake up host if we are in suspend mode // and REMOTE_WAKEUP feature is enabled by host tud_remote_wakeup(); - } - else - { + } else { // keyboard interface - if ( tud_hid_n_ready(ITF_NUM_KEYBOARD) ) - { + if (tud_hid_n_ready(ITF_NUM_KEYBOARD)) { // used to avoid send multiple consecutive zero report for keyboard static bool has_keyboard_key = false; uint8_t const report_id = 0; uint8_t const modifier = 0; - if ( btn ) - { - uint8_t keycode[6] = { 0 }; - keycode[0] = HID_KEY_ARROW_RIGHT; + if (btn) { + uint8_t keycode[6] = {0}; + keycode[0] = HID_KEY_ARROW_RIGHT; tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, keycode); has_keyboard_key = true; - }else - { + } else { // send empty key report if previously has key pressed - if (has_keyboard_key) tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, NULL); + if (has_keyboard_key) { + tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, NULL); + } has_keyboard_key = false; } } // mouse interface - if ( tud_hid_n_ready(ITF_NUM_MOUSE) ) - { - if ( btn ) - { + if (tud_hid_n_ready(ITF_NUM_MOUSE)) { + if (btn) { uint8_t const report_id = 0; uint8_t const button_mask = 0; - int8_t const vertical = 0; - int8_t const horizontal = 0; - int8_t const delta = 5; + int8_t const vertical = 0; + int8_t const horizontal = 0; + int8_t const delta = 5; tud_hid_n_mouse_report(ITF_NUM_MOUSE, report_id, button_mask, delta, delta, vertical, horizontal); } @@ -175,10 +161,9 @@ void hid_task(void) // Invoked when received SET_PROTOCOL request // protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) -{ - (void) instance; - (void) protocol; +void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) { + (void)instance; + (void)protocol; // nothing to do since we use the same compatible boot report for both Boot and Report mode. // TODO set a indicator for user @@ -187,11 +172,10 @@ void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) -{ - (void) instance; - (void) report; - (void) len; +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len) { + (void)instance; + (void)report; + (void)len; // nothing to do } @@ -199,42 +183,40 @@ void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_ // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) -{ +uint16_t tud_hid_get_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { // TODO not Implemented - (void) instance; - (void) report_id; - (void) report_type; - (void) buffer; - (void) reqlen; + (void)instance; + (void)report_id; + (void)report_type; + (void)buffer; + (void)reqlen; return 0; } // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) -{ - (void) report_id; +void tud_hid_set_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { + (void)report_id; // keyboard interface - if (instance == ITF_NUM_KEYBOARD) - { + if (instance == ITF_NUM_KEYBOARD) { // Set keyboard LED e.g Capslock, Numlock etc... - if (report_type == HID_REPORT_TYPE_OUTPUT) - { + if (report_type == HID_REPORT_TYPE_OUTPUT) { // bufsize should be (at least) 1 - if ( bufsize < 1 ) return; + if (bufsize < 1) { + return; + } uint8_t const kbd_leds = buffer[0]; - if (kbd_leds & KEYBOARD_LED_CAPSLOCK) - { + if (kbd_leds & KEYBOARD_LED_CAPSLOCK) { // Capslock On: disable blink, turn led on blink_interval_ms = 0; board_led_write(true); - }else - { + } else { // Caplocks Off: back to normal blink board_led_write(false); blink_interval_ms = BLINK_MOUNTED; @@ -246,16 +228,19 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_ //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - static uint32_t start_ms = 0; - static bool led_state = false; +void led_blinking_task(void) { + static uint32_t start_ms = 0; + static bool led_state = false; // blink is disabled - if (!blink_interval_ms) return; + if (!blink_interval_ms) { + return; + } // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/hid_boot_interface/src/tusb_config.h b/examples/device/hid_boot_interface/src/tusb_config.h index 52723e09f..5d6fd62e1 100644 --- a/examples/device/hid_boot_interface/src/tusb_config.h +++ b/examples/device/hid_boot_interface/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_boot_interface/src/usb_descriptors.c b/examples/device/hid_boot_interface/src/usb_descriptors.c index d68ef16d9..b5c31a94a 100644 --- a/examples/device/hid_boot_interface/src/usb_descriptors.c +++ b/examples/device/hid_boot_interface/src/usb_descriptors.c @@ -33,60 +33,49 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4)) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, +static tusb_desc_device_t const desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0100, + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 -}; + .bNumConfigurations = 0x01}; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; +uint8_t const *tud_descriptor_device_cb(void) { + return (uint8_t const *)&desc_device; } //--------------------------------------------------------------------+ // HID Report Descriptor //--------------------------------------------------------------------+ -uint8_t const desc_hid_keyboard_report[] = -{ - TUD_HID_REPORT_DESC_KEYBOARD() -}; +uint8_t const desc_hid_keyboard_report[] = {TUD_HID_REPORT_DESC_KEYBOARD()}; -uint8_t const desc_hid_mouse_report[] = -{ - TUD_HID_REPORT_DESC_MOUSE() -}; +uint8_t const desc_hid_mouse_report[] = {TUD_HID_REPORT_DESC_MOUSE()}; // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) -{ +uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) { return (instance == 0) ? desc_hid_keyboard_report : desc_hid_mouse_report; } @@ -94,36 +83,37 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) // Configuration Descriptor //--------------------------------------------------------------------+ -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2*TUD_HID_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_HID_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 1 Interrupt, 2 Bulk, 3 Iso, 4 Interrupt, 5 Bulk etc ... - #define EPNUM_KEYBOARD 0x81 - #define EPNUM_MOUSE 0x84 +// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number +// 1 Interrupt, 2 Bulk, 3 Iso, 4 Interrupt, 5 Bulk etc ... +#define EPNUM_KEYBOARD 0x81 +#define EPNUM_MOUSE 0x84 #else - #define EPNUM_KEYBOARD 0x81 - #define EPNUM_MOUSE 0x82 +#define EPNUM_KEYBOARD 0x81 +#define EPNUM_MOUSE 0x82 #endif -uint8_t const desc_configuration[] = -{ +uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_KEYBOARD, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(desc_hid_keyboard_report), EPNUM_KEYBOARD, CFG_TUD_HID_EP_BUFSIZE, 10), + TUD_HID_DESCRIPTOR( + ITF_NUM_KEYBOARD, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(desc_hid_keyboard_report), EPNUM_KEYBOARD, + CFG_TUD_HID_EP_BUFSIZE, 10), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_MOUSE, 0, HID_ITF_PROTOCOL_MOUSE, sizeof(desc_hid_mouse_report), EPNUM_MOUSE, CFG_TUD_HID_EP_BUFSIZE, 10) -}; + TUD_HID_DESCRIPTOR( + ITF_NUM_MOUSE, 0, HID_ITF_PROTOCOL_MOUSE, sizeof(desc_hid_mouse_report), EPNUM_MOUSE, CFG_TUD_HID_EP_BUFSIZE, + 10)}; // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; // for multiple configurations return desc_configuration; } @@ -140,12 +130,11 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible +static char const *string_desc_arr[] = { + (const char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible }; static uint16_t _desc_str[32 + 1]; @@ -153,41 +142,44 @@ static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - (void) langid; + (void)langid; size_t chr_count; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; break; - case STRID_SERIAL: - chr_count = board_usb_get_serial(_desc_str + 1, 32); - break; + case STRID_SERIAL: chr_count = board_usb_get_serial(_desc_str + 1, 32); break; default: // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; } // first byte is length (including header), second byte is string type - _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); return _desc_str; } diff --git a/examples/device/hid_composite/Makefile b/examples/device/hid_composite/Makefile index 1b4d398cf..1a4b428dc 100644 --- a/examples/device/hid_composite/Makefile +++ b/examples/device/hid_composite/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index fa02a1abe..9693d564d 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -23,8 +23,8 @@ * */ -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include "bsp/board_api.h" @@ -41,10 +41,10 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; @@ -53,24 +53,18 @@ void led_blinking_task(void); void hid_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); - hid_task(); } } @@ -80,29 +74,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void) remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -110,157 +100,128 @@ void tud_resume_cb(void) // USB HID //--------------------------------------------------------------------+ -static void send_hid_report(uint8_t report_id, uint32_t btn) -{ +static void send_hid_report(uint8_t report_id, uint32_t btn) { // skip if hid is not ready yet - if ( !tud_hid_ready() ) return; + if (!tud_hid_ready()) { + return; + } - switch(report_id) - { - case REPORT_ID_KEYBOARD: - { + switch (report_id) { + case REPORT_ID_KEYBOARD: { // use to avoid send multiple consecutive zero report for keyboard static bool has_keyboard_key = false; - if ( btn ) - { - uint8_t keycode[6] = { 0 }; - keycode[0] = HID_KEY_A; + if (btn != 0u) { + uint8_t keycode[6] = {0}; + keycode[0] = HID_KEY_A; tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); has_keyboard_key = true; - }else - { + } else { // send empty key report if previously has key pressed - if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); + if (has_keyboard_key) { + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); + } has_keyboard_key = false; } + break; } - break; - case REPORT_ID_MOUSE: - { + case REPORT_ID_MOUSE: { int8_t const delta = 5; // no button, right + down, no scroll, no pan tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); + break; } - break; - case REPORT_ID_CONSUMER_CONTROL: - { + case REPORT_ID_CONSUMER_CONTROL: { // use to avoid send multiple consecutive zero report static bool has_consumer_key = false; - if ( btn ) - { + if (btn != 0u) { // volume down uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); has_consumer_key = true; - }else - { + } else { // send empty key report (release key) if previously has key pressed uint16_t empty_key = 0; - if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); + if (has_consumer_key) { + tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); + } has_consumer_key = false; } + break; } - break; - case REPORT_ID_GAMEPAD: - { + case REPORT_ID_GAMEPAD: { // use to avoid send multiple consecutive zero report for keyboard static bool has_gamepad_key = false; - hid_gamepad_report_t report = - { - .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, - .hat = 0, .buttons = 0 - }; + hid_gamepad_report_t report = {.x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, .hat = 0, .buttons = 0}; - if ( btn ) - { - report.hat = GAMEPAD_HAT_UP; + if (btn != 0u) { + report.hat = GAMEPAD_HAT_UP; report.buttons = GAMEPAD_BUTTON_A; tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); has_gamepad_key = true; - }else - { - report.hat = GAMEPAD_HAT_CENTERED; + } else { + report.hat = GAMEPAD_HAT_CENTERED; report.buttons = 0; - if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + if (has_gamepad_key) { + tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + } has_gamepad_key = false; } + break; } - break; - default: break; - } -} - -/* use this to send stylus touch signal through USB. */ -static void send_stylus_touch(uint16_t x, uint16_t y, bool state) -{ - // skip if hid is not ready yet - if ( !tud_hid_ready() ) return; - - static bool has_stylus_pen = false; - hid_stylus_report_t report = - { - .attr = 0, - .x = 0, - .y = 0 - }; + case REPORT_ID_STYLUS_PEN: { + static bool touch_state = false; + hid_stylus_report_t report = {.attr = 0, .x = 0, .y = 0}; - report.x = x; - report.y = y; - - if (state) - { - report.attr = STYLUS_ATTR_TIP_SWITCH | STYLUS_ATTR_IN_RANGE; - tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + if (btn != 0u) { + report.attr = STYLUS_ATTR_TIP_SWITCH | STYLUS_ATTR_IN_RANGE; + report.x = 100; + report.y = 100; + tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + touch_state = true; + } else { + report.attr = 0; + if (touch_state) { + tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + } + touch_state = false; + } + break; + } - has_stylus_pen = true; - }else - { - report.attr = 0; - if (has_stylus_pen) tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); - has_stylus_pen = false; + default: break; // unknown report id } - } // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) // tud_hid_report_complete_cb() is used to send the next report after previous one is complete -void hid_task(void) -{ +void hid_task(void) { // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; - static uint32_t touch_ms = 0; - static bool touch_state = false; + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; - if (board_millis() - touch_ms < 100) { - touch_ms = board_millis(); - send_stylus_touch(0, 0, touch_state = !touch_state); - return; + if (board_millis() - start_ms < interval_ms) { + return; // not enough time } - - if ( board_millis() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; uint32_t const btn = board_button_read(); // Remote wakeup - if ( tud_suspended() && btn ) - { + if (tud_suspended() && btn != 0u) { // Wake up host if we are in suspend mode // and REMOTE_WAKEUP feature is enabled by host tud_remote_wakeup(); - }else - { + } else { // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() send_hid_report(REPORT_ID_KEYBOARD, btn); } @@ -269,15 +230,13 @@ void hid_task(void) // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) -{ - (void) instance; - (void) len; +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len) { + (void)instance; + (void)len; uint8_t next_report_id = report[0] + 1u; - if (next_report_id < REPORT_ID_COUNT) - { + if (next_report_id < REPORT_ID_COUNT) { send_hid_report(next_report_id, board_button_read()); } } @@ -285,41 +244,39 @@ void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_ // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) -{ +uint16_t tud_hid_get_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { // TODO not Implemented - (void) instance; - (void) report_id; - (void) report_type; - (void) buffer; - (void) reqlen; + (void)instance; + (void)report_id; + (void)report_type; + (void)buffer; + (void)reqlen; return 0; } // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) -{ - (void) instance; +void tud_hid_set_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { + (void)instance; - if (report_type == HID_REPORT_TYPE_OUTPUT) - { + if (report_type == HID_REPORT_TYPE_OUTPUT) { // Set keyboard LED e.g Capslock, Numlock etc... - if (report_id == REPORT_ID_KEYBOARD) - { + if (report_id == REPORT_ID_KEYBOARD) { // bufsize should be (at least) 1 - if ( bufsize < 1 ) return; + if (bufsize < 1) { + return; + } uint8_t const kbd_leds = buffer[0]; - if (kbd_leds & KEYBOARD_LED_CAPSLOCK) - { + if ((kbd_leds & KEYBOARD_LED_CAPSLOCK) != 0u) { // Capslock On: disable blink, turn led on blink_interval_ms = 0; board_led_write(true); - }else - { + } else { // Caplocks Off: back to normal blink board_led_write(false); blink_interval_ms = BLINK_MOUNTED; @@ -331,16 +288,19 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_ //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - static uint32_t start_ms = 0; - static bool led_state = false; +void led_blinking_task(void) { + static uint32_t start_ms = 0; + static bool led_state = false; // blink is disabled - if (!blink_interval_ms) return; + if (0u == blink_interval_ms) { + return; + } // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/hid_composite/src/tusb_config.h b/examples/device/hid_composite/src/tusb_config.h index 6bd32c427..895745ed2 100644 --- a/examples/device/hid_composite/src/tusb_config.h +++ b/examples/device/hid_composite/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index 15c6e1f73..46e4b63f9 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -43,7 +43,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -120,10 +120,10 @@ uint8_t const desc_configuration[] = // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, @@ -154,7 +154,7 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - // other speed config is basically configuration with type = OHER_SPEED_CONFIG + // other speed config is basically configuration with type = OTHER_SPEED_CONFIG memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN); desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; @@ -188,7 +188,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer diff --git a/examples/device/hid_composite_freertos/Makefile b/examples/device/hid_composite_freertos/Makefile index bd625b345..3c421af74 100644 --- a/examples/device/hid_composite_freertos/Makefile +++ b/examples/device/hid_composite_freertos/Makefile @@ -1,15 +1,15 @@ RTOS = freertos -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ src/main.c \ src/usb_descriptors.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 0eb13add3..391e3c42a 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -53,7 +53,7 @@ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define HID_STACK_SZIE configMINIMAL_STACK_SIZE +#define HID_STACK_SZIE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1)) //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index b28033a0c..ad067ac82 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_composite_freertos/src/usb_descriptors.c b/examples/device/hid_composite_freertos/src/usb_descriptors.c index 85820de55..a745c17b5 100644 --- a/examples/device/hid_composite_freertos/src/usb_descriptors.c +++ b/examples/device/hid_composite_freertos/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -43,7 +43,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -119,10 +119,10 @@ uint8_t const desc_configuration[] = // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, @@ -153,7 +153,7 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - // other speed config is basically configuration with type = OHER_SPEED_CONFIG + // other speed config is basically configuration with type = OTHER_SPEED_CONFIG memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN); desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; @@ -185,7 +185,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer diff --git a/examples/device/hid_generic_inout/Makefile b/examples/device/hid_generic_inout/Makefile index 1b4d398cf..1a4b428dc 100644 --- a/examples/device/hid_generic_inout/Makefile +++ b/examples/device/hid_generic_inout/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/hid_generic_inout/src/tusb_config.h b/examples/device/hid_generic_inout/src/tusb_config.h index 98143ac4d..58dc52afc 100644 --- a/examples/device/hid_generic_inout/src/tusb_config.h +++ b/examples/device/hid_generic_inout/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_generic_inout/src/usb_descriptors.c b/examples/device/hid_generic_inout/src/usb_descriptors.c index 64f6d17ae..f26333d50 100644 --- a/examples/device/hid_generic_inout/src/usb_descriptors.c +++ b/examples/device/hid_generic_inout/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -130,7 +130,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer diff --git a/examples/device/hid_multiple_interface/Makefile b/examples/device/hid_multiple_interface/Makefile index 1b4d398cf..1a4b428dc 100644 --- a/examples/device/hid_multiple_interface/Makefile +++ b/examples/device/hid_multiple_interface/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/hid_multiple_interface/src/tusb_config.h b/examples/device/hid_multiple_interface/src/tusb_config.h index 49dc962fe..e1805017d 100644 --- a/examples/device/hid_multiple_interface/src/tusb_config.h +++ b/examples/device/hid_multiple_interface/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/hid_multiple_interface/src/usb_descriptors.c b/examples/device/hid_multiple_interface/src/usb_descriptors.c index 86f567e8e..cd2d93c44 100644 --- a/examples/device/hid_multiple_interface/src/usb_descriptors.c +++ b/examples/device/hid_multiple_interface/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -146,7 +146,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer diff --git a/examples/device/midi_test/Makefile b/examples/device/midi_test/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/midi_test/Makefile +++ b/examples/device/midi_test/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/midi_test/src/tusb_config.h b/examples/device/midi_test/src/tusb_config.h index 314dde438..f4282b2d7 100644 --- a/examples/device/midi_test/src/tusb_config.h +++ b/examples/device/midi_test/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -105,4 +105,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/midi_test/src/usb_descriptors.c b/examples/device/midi_test/src/usb_descriptors.c index 384742ae8..e969f33a3 100644 --- a/examples/device/midi_test/src/usb_descriptors.c +++ b/examples/device/midi_test/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, @@ -98,7 +98,7 @@ enum { #define EPNUM_MIDI_IN 0x81 #endif -uint8_t const desc_fs_configuration[] = { +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -107,7 +107,7 @@ uint8_t const desc_fs_configuration[] = { }; #if TUD_OPT_HIGH_SPEED -uint8_t const desc_hs_configuration[] = { +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -143,7 +143,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = { +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product diff --git a/examples/device/midi_test_freertos/Makefile b/examples/device/midi_test_freertos/Makefile index 26cd83486..ebacfecdf 100644 --- a/examples/device/midi_test_freertos/Makefile +++ b/examples/device/midi_test_freertos/Makefile @@ -1,15 +1,15 @@ RTOS = freertos -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ src/main.c \ src/usb_descriptors.c \ -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/midi_test_freertos/src/main.c b/examples/device/midi_test_freertos/src/main.c index 9dd66c526..f5267214e 100644 --- a/examples/device/midi_test_freertos/src/main.c +++ b/examples/device/midi_test_freertos/src/main.c @@ -48,7 +48,7 @@ #endif #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE -#define MIDI_STACK_SIZE configMINIMAL_STACK_SIZE +#define MIDI_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1)) // static task #if configSUPPORT_STATIC_ALLOCATION diff --git a/examples/device/midi_test_freertos/src/tusb_config.h b/examples/device/midi_test_freertos/src/tusb_config.h index 0ffdc37fb..c158f5197 100644 --- a/examples/device/midi_test_freertos/src/tusb_config.h +++ b/examples/device/midi_test_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -105,4 +105,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/midi_test_freertos/src/usb_descriptors.c b/examples/device/midi_test_freertos/src/usb_descriptors.c index 384742ae8..e969f33a3 100644 --- a/examples/device/midi_test_freertos/src/usb_descriptors.c +++ b/examples/device/midi_test_freertos/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, @@ -98,7 +98,7 @@ enum { #define EPNUM_MIDI_IN 0x81 #endif -uint8_t const desc_fs_configuration[] = { +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -107,7 +107,7 @@ uint8_t const desc_fs_configuration[] = { }; #if TUD_OPT_HIGH_SPEED -uint8_t const desc_hs_configuration[] = { +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -143,7 +143,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = { +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product diff --git a/examples/device/msc_dual_lun/Makefile b/examples/device/msc_dual_lun/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/msc_dual_lun/Makefile +++ b/examples/device/msc_dual_lun/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 775fa047e..694da11db 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -217,9 +217,9 @@ uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uin const char pid[] = "Mass Storage"; const char rev[] = "1.0"; - memcpy(inquiry_resp->vendor_id, vid, strlen(vid)); - memcpy(inquiry_resp->product_id, pid, strlen(pid)); - memcpy(inquiry_resp->product_rev, rev, strlen(rev)); + strncpy((char*) inquiry_resp->vendor_id, vid, 8); + strncpy((char*) inquiry_resp->product_id, pid, 16); + strncpy((char*) inquiry_resp->product_rev, rev, 4); return sizeof(scsi_inquiry_resp_t); // 36 bytes } @@ -227,9 +227,7 @@ uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uin // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted bool tud_msc_test_unit_ready_cb(uint8_t lun) { - if ( lun == 1 && board_button_read() ) return false; - - return true; // RAM disk is always ready + return ( lun == 1 && board_button_read() ) ? false : true; } // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 9cbbbade9..4fb6816c6 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -104,4 +104,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c index efb9a966d..f73935ee0 100644 --- a/examples/device/msc_dual_lun/src/usb_descriptors.c +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -32,14 +32,14 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -103,7 +103,7 @@ enum #endif -uint8_t const desc_fs_configuration[] = +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -113,7 +113,7 @@ uint8_t const desc_fs_configuration[] = }; #if TUD_OPT_HIGH_SPEED -uint8_t const desc_hs_configuration[] = +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -151,7 +151,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer diff --git a/examples/device/mtp/CMakeLists.txt b/examples/device/mtp/CMakeLists.txt new file mode 100644 index 000000000..e91eb8fd9 --- /dev/null +++ b/examples/device/mtp/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.20) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT} C CXX ASM) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + +if (RTOS STREQUAL zephyr) + set(EXE_NAME app) +else() + set(EXE_NAME ${PROJECT}) + add_executable(${EXE_NAME}) +endif() + +# Example source +target_sources(${EXE_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mtp_fs_example.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + +# Example include +target_include_directories(${EXE_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example without RTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${EXE_NAME} ${RTOS}) diff --git a/examples/device/mtp/CMakePresets.json b/examples/device/mtp/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/mtp/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/mtp/Makefile b/examples/device/mtp/Makefile new file mode 100644 index 000000000..035e90308 --- /dev/null +++ b/examples/device/mtp/Makefile @@ -0,0 +1,11 @@ +include ../../../hw/bsp/family_support.mk + +INC += \ + src \ + + +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) + +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/mtp/prj.conf b/examples/device/mtp/prj.conf new file mode 100644 index 000000000..2f5139d9d --- /dev/null +++ b/examples/device/mtp/prj.conf @@ -0,0 +1,6 @@ +CONFIG_GPIO=y +CONFIG_FPU=y +CONFIG_NO_OPTIMIZATIONS=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_NRFX_POWER=y +CONFIG_NRFX_UARTE0=y diff --git a/examples/device/mtp/skip.txt b/examples/device/mtp/skip.txt new file mode 100644 index 000000000..37a4485d7 --- /dev/null +++ b/examples/device/mtp/skip.txt @@ -0,0 +1 @@ +board:cynthion_d11 diff --git a/examples/device/mtp/src/main.c b/examples/device/mtp/src/main.c new file mode 100644 index 000000000..57d1535b2 --- /dev/null +++ b/examples/device/mtp/src/main.c @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ennebi Elettronica (https://ennebielettronica.com) + * + * 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. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "bsp/board_api.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void); + +/*------------- MAIN -------------*/ +int main(void) { + board_init(); + + // init device stack on configured roothub port + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); + board_init_after_tusb(); + + while (1) { + tud_task(); // tinyusb device task + led_blinking_task(); + } +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) { + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) { + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) { + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) { + blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) { + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every interval ms + if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c new file mode 100644 index 000000000..7fd7db61b --- /dev/null +++ b/examples/device/mtp/src/mtp_fs_example.c @@ -0,0 +1,634 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ennebi Elettronica (https://ennebielettronica.com) + * + * 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. + * + */ + +#include "bsp/board_api.h" +#include "tusb.h" + +#include "tinyusb_logo_png.h" + +//--------------------------------------------------------------------+ +// Dataset +//--------------------------------------------------------------------+ + +//------------- device info -------------// +#define DEV_INFO_MANUFACTURER "TinyUSB" +#define DEV_INFO_MODEL "MTP Example" +#define DEV_INFO_VERSION "1.0" +#define DEV_PROP_FRIENDLY_NAME "TinyUSB MTP" + +//------------- storage info -------------// +#define STORAGE_DESCRIPTION { 'd', 'i', 's', 'k', 0 } +#define VOLUME_IDENTIFIER { 'v', 'o', 'l', 0 } + +enum { + STORAGE_DESC_LEN = TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTION), + VOLUME_ID_LEN = TU_ARRAY_SIZE((uint16_t[])VOLUME_IDENTIFIER) +}; + +typedef MTP_STORAGE_INFO_STRUCT(STORAGE_DESC_LEN, VOLUME_ID_LEN) storage_info_t; + +storage_info_t storage_info = { + #ifdef CFG_EXAMPLE_MTP_READONLY + .storage_type = MTP_STORAGE_TYPE_FIXED_ROM, + #else + .storage_type = MTP_STORAGE_TYPE_FIXED_RAM, + #endif + + .filesystem_type = MTP_FILESYSTEM_TYPE_GENERIC_HIERARCHICAL, + .access_capability = MTP_ACCESS_CAPABILITY_READ_WRITE, + .max_capacity_in_bytes = 0, // calculated at runtime + .free_space_in_bytes = 0, // calculated at runtime + .free_space_in_objects = 0, // calculated at runtime + .storage_description = { + .count = (TU_FIELD_SIZE(storage_info_t, storage_description)-1) / sizeof(uint16_t), + .utf16 = STORAGE_DESCRIPTION + }, + .volume_identifier = { + .count = (TU_FIELD_SIZE(storage_info_t, volume_identifier)-1) / sizeof(uint16_t), + .utf16 = VOLUME_IDENTIFIER + } +}; + +//--------------------------------------------------------------------+ +// MTP FILESYSTEM +//--------------------------------------------------------------------+ +// only allow to add 1 more object to make it simpler to manage memory +#define FS_MAX_FILE_COUNT 3UL +#define FS_MAX_FILENAME_LEN 16 + +#ifdef CFG_EXAMPLE_MTP_READONLY + #define FS_MAX_CAPACITY_BYTES 0 +#else + #define FS_MAX_CAPACITY_BYTES (4 * 1024UL) + + // object data buffer (excluding 2 predefined files) with simple allocation pointer + uint8_t fs_buf[FS_MAX_CAPACITY_BYTES]; +#endif + +#define FS_FIXED_DATETIME "20250808T173500.0" // "YYYYMMDDTHHMMSS.s" +#define README_TXT_CONTENT "TinyUSB MTP Filesystem example" + +typedef struct { + uint16_t name[FS_MAX_FILENAME_LEN]; + uint16_t object_format; + uint16_t protection_status; + uint32_t image_pix_width; + uint32_t image_pix_height; + uint32_t image_bit_depth; + uint32_t parent; + uint16_t association_type; + uint32_t size; + uint8_t* data; +} fs_file_t; + +// Files system, handle is index + 1 +static fs_file_t fs_objects[FS_MAX_FILE_COUNT] = { + { + .name = { 'r', 'e', 'a', 'd', 'm', 'e', '.', 't', 'x', 't', 0 }, // readme.txt + .object_format = MTP_OBJ_FORMAT_TEXT, + .protection_status = MTP_PROTECTION_STATUS_READ_ONLY, + .image_pix_width = 0, + .image_pix_height = 0, + .image_bit_depth = 0, + .parent = 0, + .association_type = MTP_ASSOCIATION_UNDEFINED, + .size = sizeof(README_TXT_CONTENT)-1, + .data = (uint8_t*) (uintptr_t) README_TXT_CONTENT, + }, + { + .name = { 't', 'i', 'n', 'y', 'u', 's', 'b', '.', 'p', 'n', 'g', 0 }, // "tinyusb.png" + .object_format = MTP_OBJ_FORMAT_PNG, + .protection_status = MTP_PROTECTION_STATUS_READ_ONLY, + .image_pix_width = 128, + .image_pix_height = 64, + .image_bit_depth = 32, + .parent = 0, + .association_type = MTP_ASSOCIATION_UNDEFINED, + .size = LOGO_LEN, + .data = (uint8_t*) (uintptr_t) logo_bin + } +}; + +enum { + SUPPORTED_STORAGE_ID = 0x00010001u // physical = 1, logical = 1 +}; + +static int32_t fs_get_device_info(tud_mtp_cb_data_t* cb_data); +static int32_t fs_open_close_session(tud_mtp_cb_data_t* cb_data); +static int32_t fs_get_storage_ids(tud_mtp_cb_data_t* cb_data); +static int32_t fs_get_storage_info(tud_mtp_cb_data_t* cb_data); +static int32_t fs_get_device_properties(tud_mtp_cb_data_t* cb_data); +static int32_t fs_get_object_handles(tud_mtp_cb_data_t* cb_data); +static int32_t fs_get_object_info(tud_mtp_cb_data_t* cb_data); +static int32_t fs_get_object(tud_mtp_cb_data_t* cb_data); +static int32_t fs_delete_object(tud_mtp_cb_data_t* cb_data); +static int32_t fs_send_object_info(tud_mtp_cb_data_t* cb_data); +static int32_t fs_send_object(tud_mtp_cb_data_t* cb_data); + +typedef int32_t (*fs_op_handler_t)(tud_mtp_cb_data_t* cb_data); +typedef struct { + uint32_t op_code; + fs_op_handler_t handler; +}fs_op_handler_dict_t; + +fs_op_handler_dict_t fs_op_handler_dict[] = { + { MTP_OP_GET_DEVICE_INFO, fs_get_device_info }, + { MTP_OP_OPEN_SESSION, fs_open_close_session }, + { MTP_OP_CLOSE_SESSION, fs_open_close_session }, + { MTP_OP_GET_STORAGE_IDS, fs_get_storage_ids }, + { MTP_OP_GET_STORAGE_INFO, fs_get_storage_info }, + { MTP_OP_GET_DEVICE_PROP_DESC, fs_get_device_properties }, + { MTP_OP_GET_DEVICE_PROP_VALUE, fs_get_device_properties }, + { MTP_OP_GET_OBJECT_HANDLES, fs_get_object_handles }, + { MTP_OP_GET_OBJECT_INFO, fs_get_object_info }, + { MTP_OP_GET_OBJECT, fs_get_object }, + { MTP_OP_DELETE_OBJECT, fs_delete_object }, + { MTP_OP_SEND_OBJECT_INFO, fs_send_object_info }, + { MTP_OP_SEND_OBJECT, fs_send_object }, +}; + +static bool is_session_opened = false; +static uint32_t send_obj_handle = 0; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +// Get pointer to object info from handle +static inline fs_file_t* fs_get_file(uint32_t handle) { + if (handle == 0 || handle > FS_MAX_FILE_COUNT) { + return NULL; + } + return &fs_objects[handle-1]; +} + +static inline bool fs_file_exist(fs_file_t* f) { + return f->name[0] != 0; +} + +// Get the number of allocated nodes in filesystem +static uint32_t fs_get_file_count(void) { + uint32_t count = 0; + for (size_t i = 0; i < FS_MAX_FILE_COUNT; i++) { + if (fs_file_exist(&fs_objects[i])) { + count++; + } + } + return count; +} + +static inline fs_file_t* fs_create_file(void) { + for (size_t i = 0; i < FS_MAX_FILE_COUNT; i++) { + fs_file_t* f = &fs_objects[i]; + if (!fs_file_exist(f)) { + send_obj_handle = i + 1; + return f; + } + } + return NULL; +} + +// simple malloc +static inline uint8_t* fs_malloc(size_t size) { +#ifdef CFG_EXAMPLE_MTP_READONLY + (void) size; + return NULL; +#else + if (size > FS_MAX_CAPACITY_BYTES) { + return NULL; + } + return fs_buf; +#endif +} + +//--------------------------------------------------------------------+ +// Control Request callback +//--------------------------------------------------------------------+ +bool tud_mtp_request_cancel_cb(tud_mtp_request_cb_data_t* cb_data) { + mtp_request_reset_cancel_data_t cancel_data; + memcpy(&cancel_data, cb_data->buf, sizeof(cancel_data)); + (void) cancel_data.code; + (void ) cancel_data.transaction_id; + return true; +} + +// Invoked when received Device Reset request +// return false to stall the request +bool tud_mtp_request_device_reset_cb(tud_mtp_request_cb_data_t* cb_data) { + (void) cb_data; + return true; +} + +// Invoked when received Get Extended Event request. Application fill callback data's buffer for response +// return negative to stall the request +int32_t tud_mtp_request_get_extended_event_cb(tud_mtp_request_cb_data_t* cb_data) { + (void) cb_data; + return false; // not implemented yet +} + +// Invoked when received Get DeviceStatus request. Application fill callback data's buffer for response +// return negative to stall the request +int32_t tud_mtp_request_get_device_status_cb(tud_mtp_request_cb_data_t* cb_data) { + uint16_t* buf16 = (uint16_t*)(uintptr_t) cb_data->buf; + buf16[0] = 4; // length + buf16[1] = MTP_RESP_OK; // status + return 4; +} + +//--------------------------------------------------------------------+ +// Bulk Only Protocol +//--------------------------------------------------------------------+ +int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + fs_op_handler_t handler = NULL; + for (size_t i = 0; i < TU_ARRAY_SIZE(fs_op_handler_dict); i++) { + if (fs_op_handler_dict[i].op_code == command->header.code) { + handler = fs_op_handler_dict[i].handler; + break; + } + } + + int32_t resp_code; + if (handler == NULL) { + resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED; + } else { + resp_code = handler(cb_data); + if (resp_code > MTP_RESP_UNDEFINED) { + // send response if needed + io_container->header->code = (uint16_t)resp_code; + tud_mtp_response_send(io_container); + } + } + + return resp_code; +} + +int32_t tud_mtp_data_xfer_cb(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + + fs_op_handler_t handler = NULL; + for (size_t i = 0; i < TU_ARRAY_SIZE(fs_op_handler_dict); i++) { + if (fs_op_handler_dict[i].op_code == command->header.code) { + handler = fs_op_handler_dict[i].handler; + break; + } + } + + int32_t resp_code; + if (handler == NULL) { + resp_code = MTP_RESP_OPERATION_NOT_SUPPORTED; + } else { + resp_code = handler(cb_data); + if (resp_code > MTP_RESP_UNDEFINED) { + // send response if needed + io_container->header->code = (uint16_t)resp_code; + tud_mtp_response_send(io_container); + } + } + + return 0; +} + +int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* resp = &cb_data->io_container; + switch (command->header.code) { + case MTP_OP_SEND_OBJECT_INFO: { + fs_file_t* f = fs_get_file(send_obj_handle); + if (f == NULL) { + resp->header->code = MTP_RESP_GENERAL_ERROR; + break; + } + // parameter is: storage id, parent handle, new handle + (void) mtp_container_add_uint32(resp, SUPPORTED_STORAGE_ID); + (void) mtp_container_add_uint32(resp, f->parent); + (void) mtp_container_add_uint32(resp, send_obj_handle); + resp->header->code = MTP_RESP_OK; + break; + } + + default: + resp->header->code = (cb_data->xfer_result == XFER_RESULT_SUCCESS) ? MTP_RESP_OK : MTP_RESP_GENERAL_ERROR; + break; + } + + tud_mtp_response_send(resp); + return 0; +} + +int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) { + (void) cb_data; + return 0; // nothing to do +} + +//--------------------------------------------------------------------+ +// File System Handlers +//--------------------------------------------------------------------+ +static int32_t fs_get_device_info(tud_mtp_cb_data_t* cb_data) { + // Device info is already prepared up to playback formats. Application only need to add string fields + int32_t resp_code = 0; + mtp_container_info_t* io_container = &cb_data->io_container; + (void) mtp_container_add_cstring(io_container, DEV_INFO_MANUFACTURER); + (void) mtp_container_add_cstring(io_container, DEV_INFO_MODEL); + (void) mtp_container_add_cstring(io_container, DEV_INFO_VERSION); + + enum { MAX_SERIAL_NCHARS = 32 }; + uint16_t serial_utf16[MAX_SERIAL_NCHARS+1]; + size_t nchars = board_usb_get_serial(serial_utf16, MAX_SERIAL_NCHARS); + serial_utf16[tu_min32(nchars, MAX_SERIAL_NCHARS)] = 0; // ensure null termination + (void) mtp_container_add_string(io_container, serial_utf16); + + if (!tud_mtp_data_send(io_container)) { + resp_code = MTP_RESP_DEVICE_BUSY; + } + return resp_code; +} + +static int32_t fs_open_close_session(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + if (command->header.code == MTP_OP_OPEN_SESSION) { + if (is_session_opened) { + return MTP_RESP_SESSION_ALREADY_OPEN; + } + is_session_opened = true; + } else { // close session + if (!is_session_opened) { + return MTP_RESP_SESSION_NOT_OPEN; + } + is_session_opened = false; + } + return MTP_RESP_OK; +} + +static int32_t fs_get_storage_ids(tud_mtp_cb_data_t* cb_data) { + mtp_container_info_t* io_container = &cb_data->io_container; + uint32_t storage_ids [] = { SUPPORTED_STORAGE_ID }; + (void) mtp_container_add_auint32(io_container, 1, storage_ids); + tud_mtp_data_send(io_container); + return 0; +} + +static int32_t fs_get_storage_info(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + const uint32_t storage_id = command->params[0]; + TU_VERIFY(SUPPORTED_STORAGE_ID == storage_id, -1); + // update storage info with current free space + storage_info.max_capacity_in_bytes = sizeof(README_TXT_CONTENT) + LOGO_LEN + FS_MAX_CAPACITY_BYTES; + storage_info.free_space_in_objects = FS_MAX_FILE_COUNT - fs_get_file_count(); + storage_info.free_space_in_bytes = storage_info.free_space_in_objects ? FS_MAX_CAPACITY_BYTES : 0; + (void) mtp_container_add_raw(io_container, &storage_info, sizeof(storage_info)); + tud_mtp_data_send(io_container); + return 0; +} + +static int32_t fs_get_device_properties(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + const uint16_t dev_prop_code = (uint16_t) command->params[0]; + + if (command->header.code == MTP_OP_GET_DEVICE_PROP_DESC) { + // get describing dataset + mtp_device_prop_desc_header_t device_prop_header; + device_prop_header.device_property_code = dev_prop_code; + switch (dev_prop_code) { + case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: + device_prop_header.datatype = MTP_DATA_TYPE_STR; + device_prop_header.get_set = MTP_MODE_GET; + (void) mtp_container_add_raw(io_container, &device_prop_header, sizeof(device_prop_header)); + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // factory + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // current + (void) mtp_container_add_uint8(io_container, 0); // no form + tud_mtp_data_send(io_container); + break; + + default: + return MTP_RESP_PARAMETER_NOT_SUPPORTED; + } + } else { + // get value + switch (dev_prop_code) { + case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); + tud_mtp_data_send(io_container); + break; + + default: + return MTP_RESP_PARAMETER_NOT_SUPPORTED; + } + } + return 0; +} + +static int32_t fs_get_object_handles(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + + const uint32_t storage_id = command->params[0]; + const uint32_t obj_format = command->params[1]; // optional + const uint32_t parent_handle = command->params[2]; // folder handle, 0xFFFFFFFF is root + (void)obj_format; + + if (storage_id != 0xFFFFFFFFu && storage_id != SUPPORTED_STORAGE_ID) { + return MTP_RESP_INVALID_STORAGE_ID; + } + + uint32_t handles[FS_MAX_FILE_COUNT] = { 0 }; + uint32_t count = 0u; + for (uint8_t i = 0u; i < FS_MAX_FILE_COUNT; i++) { + fs_file_t* f = &fs_objects[i]; + if (fs_file_exist(f) && + (parent_handle == f->parent || (parent_handle == 0xFFFFFFFFu && f->parent == 0u))) { + handles[count++] = (uint32_t) i + 1u; // handle is index + 1 + } + } + (void) mtp_container_add_auint32(io_container, count, handles); + tud_mtp_data_send(io_container); + + return 0; +} + +static int32_t fs_get_object_info(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + const uint32_t obj_handle = command->params[0]; + fs_file_t* f = fs_get_file(obj_handle); + if (f == NULL) { + return MTP_RESP_INVALID_OBJECT_HANDLE; + } + mtp_object_info_header_t obj_info_header = { + .storage_id = SUPPORTED_STORAGE_ID, + .object_format = f->object_format, + .protection_status = f->protection_status, + .object_compressed_size = f->size, + .thumb_format = MTP_OBJ_FORMAT_UNDEFINED, + .thumb_compressed_size = 0, + .thumb_pix_width = 0, + .thumb_pix_height = 0, + .image_pix_width = f->image_pix_width, + .image_pix_height = f->image_pix_height, + .image_bit_depth = f->image_bit_depth, + .parent_object = f->parent, + .association_type = f->association_type, + .association_desc = 0, + .sequence_number = 0 + }; + (void) mtp_container_add_raw(io_container, &obj_info_header, sizeof(obj_info_header)); + (void) mtp_container_add_string(io_container, f->name); + (void) mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); + (void) mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); + (void) mtp_container_add_cstring(io_container, ""); // keywords, not used + tud_mtp_data_send(io_container); + + return 0; +} + +static int32_t fs_get_object(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + const uint32_t obj_handle = command->params[0]; + const fs_file_t* f = fs_get_file(obj_handle); + if (f == NULL) { + return MTP_RESP_INVALID_OBJECT_HANDLE; + } + + if (cb_data->phase == MTP_PHASE_COMMAND) { + // If file contents is larger than CFG_TUD_MTP_EP_BUFSIZE, data may only partially is added here + // the rest will be sent in tud_mtp_data_more_cb + (void) mtp_container_add_raw(io_container, f->data, f->size); + tud_mtp_data_send(io_container); + } else if (cb_data->phase == MTP_PHASE_DATA) { + // continue sending remaining data: file contents offset is xferred byte minus header size + const uint32_t offset = cb_data->total_xferred_bytes - sizeof(mtp_container_header_t); + const uint32_t xact_len = tu_min32(f->size - offset, io_container->payload_bytes); + if (xact_len > 0) { + memcpy(io_container->payload, f->data + offset, xact_len); + tud_mtp_data_send(io_container); + } + } else { + // nothing to do + } + + return 0; +} + +static int32_t fs_send_object_info(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + mtp_container_info_t* io_container = &cb_data->io_container; + const uint32_t storage_id = command->params[0]; + const uint32_t parent_handle = command->params[1]; // folder handle, 0xFFFFFFFF is root + (void) parent_handle; + + if (!is_session_opened) { + return MTP_RESP_SESSION_NOT_OPEN; + } + if (storage_id != 0xFFFFFFFFu && storage_id != SUPPORTED_STORAGE_ID) { + return MTP_RESP_INVALID_STORAGE_ID; + } + + if (cb_data->phase == MTP_PHASE_COMMAND) { + (void) tud_mtp_data_receive(io_container); + } else if (cb_data->phase == MTP_PHASE_DATA) { + mtp_object_info_header_t* obj_info = (mtp_object_info_header_t*) io_container->payload; + if (obj_info->storage_id != 0 && obj_info->storage_id != SUPPORTED_STORAGE_ID) { + return MTP_RESP_INVALID_STORAGE_ID; + } + + if (obj_info->parent_object != 0) { // not root + fs_file_t* parent = fs_get_file(obj_info->parent_object); + if (parent == NULL || 0u == parent->association_type) { + return MTP_RESP_INVALID_PARENT_OBJECT; + } + } + + uint8_t* f_buf = fs_malloc(obj_info->object_compressed_size); + if (f_buf == NULL) { + return MTP_RESP_STORE_FULL; + } + fs_file_t* f = fs_create_file(); + if (f == NULL) { + return MTP_RESP_STORE_FULL; + } + + f->object_format = obj_info->object_format; + f->protection_status = obj_info->protection_status; + f->image_pix_width = obj_info->image_pix_width; + f->image_pix_height = obj_info->image_pix_height; + f->image_bit_depth = obj_info->image_bit_depth; + f->parent = obj_info->parent_object; + f->association_type = obj_info->association_type; + f->size = obj_info->object_compressed_size; + f->data = f_buf; + uint8_t* buf = io_container->payload + sizeof(mtp_object_info_header_t); + (void) mtp_container_get_string(buf, f->name); + // ignore date created/modified/keywords + } else { + // nothing to do + } + + return 0; +} + +static int32_t fs_send_object(tud_mtp_cb_data_t* cb_data) { + mtp_container_info_t* io_container = &cb_data->io_container; + fs_file_t* f = fs_get_file(send_obj_handle); + if (f == NULL) { + return MTP_RESP_INVALID_OBJECT_HANDLE; + } + + if (cb_data->phase == MTP_PHASE_COMMAND) { + io_container->header->len += f->size; + tud_mtp_data_receive(io_container); + } else { + // file contents offset is total xferred minus header size minus last received chunk + const uint32_t offset = cb_data->total_xferred_bytes - sizeof(mtp_container_header_t) - io_container->payload_bytes; + memcpy(f->data + offset, io_container->payload, io_container->payload_bytes); + if (cb_data->total_xferred_bytes - sizeof(mtp_container_header_t) < f->size) { + tud_mtp_data_receive(io_container); + } + } + + return 0; +} + +static int32_t fs_delete_object(tud_mtp_cb_data_t* cb_data) { + const mtp_container_command_t* command = cb_data->command_container; + const uint32_t obj_handle = command->params[0]; + const uint32_t obj_format = command->params[1]; // optional + (void) obj_format; + + if (!is_session_opened) { + return MTP_RESP_SESSION_NOT_OPEN; + } + fs_file_t* f = fs_get_file(obj_handle); + if (f == NULL) { + return MTP_RESP_INVALID_OBJECT_HANDLE; + } + + // delete object by clear the name + f->name[0] = 0; + return MTP_RESP_OK; +} diff --git a/examples/device/mtp/src/tinyusb_logo_png.h b/examples/device/mtp/src/tinyusb_logo_png.h new file mode 100644 index 000000000..f8a9bde4e --- /dev/null +++ b/examples/device/mtp/src/tinyusb_logo_png.h @@ -0,0 +1,175 @@ +// convert using tools/file2carray.py +enum { LOGO_LEN = 2733 }; +static const uint8_t logo_bin[] __attribute__((aligned(16))) = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0xd2, 0xd6, 0x7f, + 0x7f, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, + 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x0a, 0x62, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0xed, 0x9c, 0x7d, + 0x54, 0x54, 0x65, 0x1a, 0xc0, 0x7f, 0xc3, 0x00, 0x29, 0x1f, 0x31, 0x88, 0x61, 0x90, 0xd6, 0xa1, + 0xb3, 0xba, 0x1a, 0x18, 0x7e, 0xf2, 0xad, 0x40, 0x82, 0xb8, 0x9b, 0x2b, 0x43, 0x1e, 0xd2, 0x00, + 0x53, 0xc0, 0xea, 0xec, 0xc9, 0x70, 0x18, 0x3d, 0x5b, 0xb1, 0x9e, 0x4a, 0x6d, 0x13, 0x2d, 0xcb, + 0x76, 0xcd, 0x00, 0xf3, 0x8b, 0x10, 0x8a, 0x8e, 0xd6, 0xee, 0xda, 0x8a, 0x96, 0x30, 0x66, 0xa2, + 0xa0, 0x91, 0x64, 0xae, 0x16, 0x98, 0x45, 0x9d, 0x2c, 0x93, 0x8f, 0x05, 0x11, 0x92, 0x81, 0xbb, + 0x7f, 0xa8, 0x93, 0x33, 0x23, 0xcc, 0xdc, 0x61, 0x60, 0x46, 0xb8, 0xbf, 0xbf, 0x78, 0xdf, 0xfb, + 0x3c, 0xcf, 0xfb, 0xc0, 0x7d, 0xee, 0x73, 0xdf, 0xf7, 0xb9, 0xef, 0x8b, 0x8c, 0x6b, 0x08, 0x82, + 0x90, 0x08, 0x2c, 0x03, 0x02, 0x81, 0x21, 0x48, 0x0c, 0x44, 0xda, 0x81, 0x6a, 0xe0, 0x55, 0x99, + 0x4c, 0x56, 0x0c, 0x20, 0x03, 0x10, 0x04, 0x61, 0x35, 0xb0, 0xc2, 0x86, 0x8e, 0x49, 0xf4, 0x3f, + 0x6b, 0x64, 0x32, 0x59, 0x96, 0x4c, 0x10, 0x84, 0x19, 0xc0, 0x47, 0x5c, 0x0b, 0x06, 0x89, 0x41, + 0x45, 0xac, 0x03, 0xa0, 0x42, 0xba, 0xf9, 0x83, 0x15, 0x95, 0x4c, 0x10, 0x84, 0x8b, 0x80, 0x97, + 0xad, 0x3d, 0x91, 0xb0, 0x09, 0x4d, 0x32, 0x41, 0x10, 0x3a, 0x01, 0x07, 0x5b, 0x7b, 0x22, 0x61, + 0x1b, 0x1c, 0x90, 0xd2, 0xff, 0xa0, 0x46, 0x7a, 0xf2, 0x07, 0x39, 0x52, 0x00, 0x0c, 0x72, 0x1c, + 0x2d, 0x55, 0x3c, 0x52, 0x5e, 0x4e, 0x53, 0x63, 0x93, 0x28, 0x9d, 0x49, 0x93, 0x27, 0x31, 0xe2, + 0xce, 0x3b, 0x4d, 0xca, 0x5d, 0xba, 0x74, 0x89, 0xea, 0x13, 0xd5, 0x26, 0xe5, 0x46, 0x8c, 0xf0, + 0xe6, 0x77, 0xa3, 0x47, 0x8b, 0xf2, 0x41, 0x42, 0x1f, 0x99, 0x20, 0x08, 0x5d, 0x58, 0x30, 0x0f, + 0x48, 0x7c, 0x68, 0x2e, 0x9f, 0x57, 0x55, 0x89, 0xd2, 0xd9, 0x94, 0x9b, 0xc3, 0xcc, 0xb8, 0x38, + 0x93, 0x72, 0x27, 0xbf, 0x38, 0x49, 0xc2, 0x9c, 0x39, 0x78, 0x78, 0x78, 0x74, 0x2b, 0xd3, 0xd6, + 0xd6, 0x46, 0xbc, 0x52, 0xc9, 0x9a, 0x75, 0x6b, 0x45, 0xf9, 0x20, 0xa1, 0x8f, 0xc5, 0x19, 0xa0, + 0x3f, 0xa8, 0xfc, 0xec, 0x38, 0x72, 0xc7, 0x9b, 0xbb, 0xb8, 0x22, 0x2b, 0x8b, 0x4e, 0x6d, 0x67, + 0x3f, 0x7b, 0x34, 0xf0, 0x90, 0xe6, 0x00, 0x83, 0x1c, 0xbb, 0x0e, 0x80, 0xb6, 0xb6, 0x36, 0x5e, + 0x5c, 0xb5, 0x8a, 0x0f, 0x76, 0xbf, 0x0f, 0x40, 0xdd, 0x77, 0xdf, 0xf1, 0xe2, 0xaa, 0x55, 0x1c, + 0xfe, 0xf4, 0xb0, 0x8d, 0x3d, 0x1b, 0x38, 0xd8, 0x75, 0x00, 0x68, 0xb5, 0x5a, 0x34, 0xa5, 0x65, + 0x9c, 0x3a, 0x75, 0x0a, 0x80, 0xa6, 0xa6, 0xff, 0xa1, 0x29, 0x2d, 0xa3, 0xae, 0xee, 0x3b, 0x1b, + 0x7b, 0x36, 0x70, 0xb0, 0xeb, 0x39, 0x80, 0xbb, 0xbb, 0x3b, 0x1f, 0x6b, 0xca, 0x74, 0xed, 0xfb, + 0x03, 0xef, 0xd7, 0xb5, 0x57, 0x64, 0x65, 0xd9, 0xca, 0xad, 0x01, 0x85, 0x5d, 0x07, 0x80, 0xbd, + 0x70, 0xb9, 0xf5, 0x32, 0x3f, 0x5f, 0xf8, 0x19, 0xb9, 0x83, 0x03, 0x6e, 0xee, 0xee, 0x28, 0x14, + 0x0a, 0x1c, 0x1c, 0xec, 0x3a, 0x79, 0x9a, 0x8d, 0xd9, 0xcb, 0xc0, 0x8e, 0x8e, 0x0e, 0x56, 0x3e, + 0xff, 0xbc, 0xae, 0xfd, 0xf1, 0xfe, 0x8f, 0xb8, 0x78, 0xf1, 0xa2, 0xa8, 0xc1, 0x22, 0xa6, 0x4d, + 0x63, 0xe4, 0xa8, 0x91, 0x7a, 0x7d, 0xa1, 0x61, 0x61, 0x3c, 0x38, 0x7b, 0xb6, 0xae, 0xfd, 0xf7, + 0x0d, 0x1b, 0x38, 0x73, 0xfa, 0x0c, 0xfb, 0xf7, 0xed, 0xe3, 0xe1, 0xf9, 0xf3, 0xba, 0xfd, 0x43, + 0x1f, 0xab, 0x3c, 0x86, 0xd0, 0xd5, 0x45, 0x50, 0x48, 0x30, 0x69, 0x8b, 0x17, 0x73, 0xef, 0xbd, + 0xf7, 0xea, 0xae, 0x7d, 0xb4, 0x7f, 0x3f, 0x07, 0x35, 0x1a, 0x51, 0xbe, 0xad, 0x5c, 0xbd, 0x1a, + 0xb9, 0x5c, 0x0e, 0x5c, 0x9d, 0x6b, 0x94, 0xec, 0x2d, 0xe1, 0xa0, 0x46, 0x43, 0xf5, 0x89, 0x13, + 0xb4, 0xb7, 0xb7, 0xeb, 0xc9, 0xba, 0xb9, 0xb9, 0xe1, 0x1f, 0x10, 0x40, 0x4c, 0x6c, 0x0c, 0xf1, + 0x09, 0x09, 0x0c, 0x1b, 0x36, 0x4c, 0x77, 0xed, 0xc7, 0x1f, 0x7f, 0x64, 0xd3, 0xc6, 0x8d, 0xa2, + 0xc6, 0x06, 0x70, 0x90, 0x39, 0xf0, 0xec, 0x5f, 0xb3, 0x18, 0xea, 0xe2, 0x22, 0x4a, 0xef, 0xdd, + 0xa2, 0x77, 0x38, 0x79, 0xf2, 0x0b, 0xbd, 0xbe, 0xe4, 0x94, 0x14, 0xc6, 0xdd, 0x77, 0x9f, 0x59, + 0xfa, 0x66, 0x07, 0x40, 0x5b, 0x5b, 0x1b, 0xe3, 0xc7, 0x99, 0x67, 0x54, 0x0c, 0x8b, 0xd2, 0x52, + 0x59, 0xf1, 0xdc, 0x73, 0xba, 0x76, 0x5c, 0x4c, 0x2c, 0x67, 0x6b, 0x6b, 0x45, 0xd9, 0x28, 0x28, + 0x2a, 0x24, 0x24, 0x34, 0x54, 0xd7, 0x5e, 0xff, 0xf2, 0x2b, 0xbc, 0xf9, 0xc6, 0x1b, 0xa2, 0x6c, + 0x9c, 0xa9, 0xad, 0xa1, 0xa1, 0xa1, 0x81, 0x7f, 0x6c, 0x78, 0x9d, 0xe2, 0xe2, 0x77, 0xcd, 0x5e, + 0x62, 0x0e, 0x19, 0x32, 0x84, 0xa5, 0x99, 0x99, 0xa4, 0xa5, 0xa7, 0xe9, 0x96, 0xac, 0x73, 0xe3, + 0x95, 0x54, 0x57, 0x9b, 0x2e, 0x64, 0x19, 0xf2, 0xf4, 0xb3, 0xcf, 0xf2, 0xd8, 0x13, 0x8f, 0x9b, + 0x2d, 0xdf, 0xdc, 0xdc, 0x4c, 0x44, 0x68, 0x28, 0x97, 0x5b, 0x2f, 0xeb, 0xfa, 0x14, 0x0a, 0x05, + 0x87, 0xca, 0x0f, 0x9b, 0x1d, 0x48, 0x03, 0x23, 0x8f, 0x59, 0x81, 0xea, 0x13, 0x27, 0x98, 0x3d, + 0xeb, 0x0f, 0x14, 0x15, 0x16, 0x8a, 0xaa, 0x2f, 0xb4, 0xb7, 0xb7, 0xb3, 0x76, 0xcd, 0x1a, 0x32, + 0x96, 0x3c, 0x45, 0xa7, 0x56, 0x0b, 0xc0, 0x53, 0xaa, 0xa5, 0x16, 0xf9, 0x90, 0x97, 0x9b, 0xa3, + 0x77, 0x33, 0x4d, 0x51, 0xb4, 0xb3, 0xd0, 0x48, 0x3e, 0xe5, 0xd1, 0x05, 0xa2, 0xb2, 0x88, 0x14, + 0x00, 0xd7, 0x78, 0xe2, 0xb1, 0xc7, 0x69, 0x68, 0x68, 0xb0, 0x58, 0x7f, 0x5f, 0x49, 0x09, 0x6b, + 0xb3, 0xaf, 0x56, 0x25, 0xa3, 0xa2, 0xa3, 0x09, 0x9c, 0x30, 0x41, 0xb4, 0x8d, 0xc6, 0x86, 0x46, + 0x76, 0x16, 0x14, 0x98, 0x25, 0xab, 0xd5, 0x6a, 0x29, 0xc8, 0xcf, 0xd7, 0xeb, 0x73, 0x72, 0x72, + 0x22, 0x29, 0x25, 0x45, 0xd4, 0x98, 0x66, 0x4f, 0x02, 0x9d, 0x9d, 0x9d, 0xd9, 0x71, 0x83, 0x73, + 0xab, 0x57, 0xae, 0xa4, 0xb6, 0xa6, 0x46, 0xd4, 0x60, 0x19, 0x2a, 0x15, 0x93, 0xa7, 0x4c, 0xd1, + 0xeb, 0xf3, 0xf1, 0xf5, 0x11, 0x65, 0xa3, 0xaf, 0x68, 0x6a, 0x6c, 0xec, 0xb5, 0x8d, 0x1d, 0xdb, + 0xb7, 0x91, 0xf8, 0x70, 0x22, 0xa3, 0xc7, 0x8c, 0x61, 0x69, 0xa6, 0x8a, 0xb4, 0x85, 0x8b, 0x44, + 0xdb, 0xc8, 0xcb, 0xcd, 0x21, 0x39, 0x25, 0x05, 0x17, 0xd7, 0x9e, 0x9f, 0xe2, 0x0f, 0xf7, 0xec, + 0xe1, 0xfc, 0xf9, 0xf3, 0x7a, 0x7d, 0x73, 0xe2, 0xe3, 0xf1, 0xf6, 0xf6, 0x16, 0x35, 0x9e, 0xd9, + 0x01, 0x20, 0x97, 0xcb, 0x09, 0x8f, 0x08, 0xd7, 0xb5, 0xdd, 0xdd, 0xdd, 0x45, 0x0d, 0x04, 0x30, + 0x76, 0xdc, 0x58, 0x3d, 0x1b, 0xf6, 0xc4, 0x5d, 0x77, 0xdd, 0x45, 0x70, 0x48, 0x08, 0x23, 0x47, + 0x8d, 0xa4, 0xab, 0xab, 0x8b, 0xe3, 0xc7, 0x8e, 0x73, 0xf4, 0xc8, 0x11, 0x51, 0x36, 0x3a, 0xb5, + 0x9d, 0x14, 0x15, 0x16, 0xf2, 0xdc, 0x0b, 0x2f, 0x30, 0x3d, 0x32, 0x92, 0x29, 0x53, 0xa7, 0x70, + 0xfc, 0xd8, 0x71, 0x51, 0x36, 0xae, 0x67, 0x01, 0x53, 0x73, 0x81, 0xfc, 0x6d, 0xdb, 0x8d, 0xfa, + 0x16, 0xa5, 0xa5, 0x8a, 0x1a, 0x0b, 0xa4, 0x57, 0x80, 0x8e, 0x98, 0x99, 0xb1, 0xac, 0x5b, 0xff, + 0x0a, 0x19, 0x2a, 0x15, 0x2a, 0xb5, 0x9a, 0x82, 0xa2, 0x42, 0xfe, 0xfc, 0xe4, 0x93, 0xa2, 0xed, + 0x94, 0x95, 0xfe, 0x56, 0xb7, 0x58, 0x92, 0x91, 0x61, 0x91, 0x2f, 0xa6, 0xe6, 0x02, 0x95, 0x15, + 0x15, 0x46, 0x93, 0xcc, 0xb0, 0xf0, 0x70, 0xb3, 0x67, 0xfe, 0x37, 0x22, 0x05, 0x40, 0x0f, 0x2c, + 0x4a, 0x4b, 0xd5, 0x2d, 0x0d, 0xcd, 0xe5, 0xfb, 0xba, 0x3a, 0x9a, 0x9a, 0xae, 0x7e, 0x26, 0x8f, + 0x98, 0x36, 0x8d, 0xa9, 0x41, 0x53, 0x45, 0x8f, 0x6b, 0x6a, 0x2e, 0xb0, 0xe5, 0xad, 0xb7, 0x8c, + 0xfa, 0x52, 0xd3, 0xd3, 0x44, 0x8f, 0x03, 0x52, 0x00, 0xf4, 0x88, 0x97, 0x97, 0x17, 0x0a, 0x85, + 0x42, 0xb4, 0x5e, 0x7d, 0x7d, 0xbd, 0xee, 0xe7, 0x25, 0x19, 0xd6, 0x5d, 0x11, 0x7c, 0x7b, 0xee, + 0x5b, 0xca, 0x0e, 0x94, 0xea, 0xf5, 0xf9, 0xf9, 0xf9, 0x11, 0x19, 0x15, 0x65, 0xd1, 0x38, 0x76, + 0x1b, 0x00, 0x81, 0x81, 0x81, 0x6c, 0xdc, 0xb4, 0x89, 0xdc, 0xcd, 0x9b, 0x89, 0x57, 0x2a, 0x01, + 0x58, 0x98, 0xba, 0x88, 0x3d, 0x25, 0x7b, 0xd9, 0xf5, 0xcf, 0x0f, 0x48, 0x4d, 0x4b, 0x43, 0x26, + 0xeb, 0xfb, 0xed, 0x8c, 0xb7, 0xdf, 0x7e, 0xbb, 0x68, 0x9d, 0xc6, 0x86, 0xdf, 0x26, 0x94, 0xe1, + 0x11, 0xe1, 0x4c, 0x0d, 0x0a, 0xb2, 0xc8, 0xc6, 0xcd, 0xb2, 0xc0, 0xb6, 0xad, 0x5b, 0xe9, 0xea, + 0xea, 0xd2, 0xeb, 0x4b, 0x7b, 0x6c, 0xb1, 0xc5, 0x95, 0x49, 0xbb, 0x2c, 0x05, 0xfb, 0xfa, 0xfa, + 0x52, 0x50, 0x54, 0xa8, 0x5b, 0xcf, 0xce, 0x88, 0x8d, 0x61, 0x7a, 0x64, 0x24, 0xf1, 0x09, 0x4a, + 0x9d, 0x4c, 0x60, 0x60, 0x20, 0x1d, 0x37, 0x59, 0x0a, 0x59, 0x1b, 0x4b, 0x82, 0xac, 0xab, 0x4b, + 0xbf, 0x8e, 0x90, 0xa1, 0x5a, 0xca, 0x82, 0xa4, 0x64, 0xd1, 0x76, 0x0c, 0x57, 0x04, 0x4d, 0x4d, + 0x4d, 0xec, 0xde, 0xb5, 0x4b, 0x4f, 0x46, 0xa1, 0x50, 0xa0, 0x54, 0x2a, 0x6f, 0xa6, 0x6e, 0x16, + 0x76, 0x99, 0x01, 0xe6, 0x28, 0x95, 0x0c, 0x75, 0x71, 0x61, 0x5d, 0x76, 0x36, 0xe1, 0x21, 0xa1, + 0xe4, 0x6f, 0xdf, 0x41, 0x7c, 0x82, 0x92, 0xa3, 0x47, 0x8e, 0x70, 0xbf, 0xbf, 0x3f, 0x33, 0x1f, + 0x98, 0x41, 0x4b, 0x4b, 0x0b, 0xf3, 0x93, 0x1e, 0xb1, 0xb5, 0xab, 0x66, 0x11, 0x1a, 0x16, 0x46, + 0x50, 0x70, 0xb0, 0x68, 0x3d, 0xc3, 0x2c, 0x50, 0x58, 0x50, 0x40, 0xdb, 0x65, 0xfd, 0xd7, 0x42, + 0xf2, 0x82, 0x14, 0xd1, 0xe5, 0xe3, 0x1b, 0xb1, 0xcb, 0x00, 0x18, 0x35, 0x6a, 0x14, 0x70, 0x75, + 0x69, 0xf6, 0xe8, 0xc2, 0x85, 0xb8, 0xb9, 0xbb, 0x01, 0x57, 0x9f, 0xc6, 0x27, 0x97, 0x3c, 0xc5, + 0xdc, 0xc4, 0x44, 0x5a, 0x2f, 0xb5, 0x72, 0xcf, 0xdd, 0x77, 0xdb, 0xd2, 0x4d, 0x51, 0xa8, 0x97, + 0x2f, 0xb7, 0x48, 0xef, 0xfa, 0x5c, 0x40, 0xab, 0xd5, 0x52, 0xb8, 0x73, 0xa7, 0xde, 0x35, 0x27, + 0x27, 0x27, 0x92, 0x17, 0x2c, 0xe8, 0x95, 0x5f, 0x76, 0xf9, 0x0a, 0x70, 0x76, 0x76, 0x06, 0x30, + 0xfa, 0xe5, 0x82, 0x43, 0x42, 0x08, 0x0e, 0x09, 0xd1, 0xb5, 0xaf, 0x97, 0x5e, 0x6f, 0x05, 0xa6, + 0x4c, 0x9d, 0x42, 0x70, 0x48, 0x08, 0x15, 0x47, 0x8f, 0x8a, 0xd2, 0xbb, 0x9e, 0x05, 0xbc, 0x86, + 0x7b, 0xf1, 0xd3, 0xf9, 0x9f, 0xf4, 0xae, 0x59, 0x52, 0xf8, 0x31, 0xc4, 0x2e, 0x03, 0xa0, 0x20, + 0x3f, 0x9f, 0xd2, 0xd2, 0x03, 0x26, 0xe5, 0x04, 0x41, 0xe8, 0x07, 0x6f, 0xac, 0x87, 0x4a, 0x9d, + 0xc9, 0x23, 0x0f, 0xcf, 0x13, 0xad, 0xf7, 0x56, 0x5e, 0x1e, 0xc3, 0xef, 0x18, 0x6e, 0xd4, 0x6f, + 0x49, 0xe1, 0xc7, 0x10, 0xbb, 0x0c, 0x80, 0xea, 0xea, 0xea, 0x9b, 0x7e, 0x4d, 0xf3, 0xf0, 0xf0, + 0x20, 0x2a, 0x3a, 0x9a, 0xdb, 0x86, 0xdc, 0x46, 0xd5, 0x67, 0x55, 0xa2, 0x4b, 0xd1, 0xb6, 0x66, + 0x6a, 0x50, 0x10, 0xa1, 0x61, 0x61, 0x1c, 0x29, 0x2f, 0x17, 0xa5, 0x57, 0x5f, 0x5f, 0xaf, 0xb7, + 0xb4, 0x04, 0xcb, 0x0b, 0x3f, 0x86, 0xd8, 0xe5, 0x1c, 0xe0, 0x99, 0xac, 0x2c, 0x6a, 0xbf, 0x3d, + 0x47, 0x4c, 0x6c, 0xac, 0xae, 0x2f, 0x6e, 0xd6, 0x2c, 0x0e, 0x68, 0xca, 0x58, 0xbf, 0xe1, 0x35, + 0x5e, 0xca, 0xce, 0xe6, 0xc3, 0x92, 0xbd, 0x24, 0xce, 0x13, 0xff, 0x34, 0xd9, 0x9a, 0xcc, 0x65, + 0x6a, 0xab, 0xd8, 0xb1, 0xb4, 0xf0, 0x63, 0x88, 0x5d, 0x06, 0xc0, 0xdd, 0xf7, 0x5c, 0x9d, 0xdc, + 0xd5, 0xd6, 0xd4, 0x20, 0x93, 0xc9, 0xc8, 0x50, 0xa9, 0xd8, 0xf8, 0xe6, 0x26, 0x14, 0x9e, 0x9e, + 0x1c, 0xd4, 0x68, 0x78, 0x79, 0xed, 0x5a, 0xae, 0x5c, 0xb9, 0xc2, 0x5f, 0x9e, 0x7e, 0xda, 0xc6, + 0x9e, 0x8a, 0x67, 0xd2, 0xe4, 0xc9, 0xbd, 0xfe, 0x1e, 0xd2, 0x9b, 0xc2, 0x8f, 0x21, 0x76, 0xf9, + 0x0a, 0xa8, 0xad, 0xa9, 0x61, 0x66, 0x5c, 0x1c, 0x1b, 0x73, 0xde, 0xa4, 0x53, 0xab, 0xc5, 0x3f, + 0x20, 0x00, 0xad, 0x56, 0x4b, 0xf6, 0x4b, 0x2f, 0xb1, 0x7d, 0xeb, 0x36, 0x00, 0x66, 0xc4, 0xc4, + 0x30, 0x61, 0xe2, 0x44, 0x9c, 0x9c, 0x9c, 0x6c, 0xec, 0xad, 0x78, 0x54, 0x6a, 0x75, 0xaf, 0x76, + 0x36, 0xa7, 0x2e, 0x4e, 0xb7, 0xda, 0x96, 0x34, 0xbb, 0xcc, 0x00, 0x9b, 0x73, 0xf3, 0xa8, 0xac, + 0xa8, 0x60, 0xec, 0xd8, 0xb1, 0xf8, 0x07, 0x04, 0xf0, 0x7d, 0x5d, 0x1d, 0x49, 0xf3, 0xe6, 0xeb, + 0x6e, 0xbe, 0xe7, 0x30, 0x4f, 0xc6, 0x8d, 0x1b, 0x47, 0xcd, 0xd7, 0x35, 0x74, 0x74, 0x74, 0xd8, + 0xd8, 0x5b, 0xf1, 0x4c, 0x9c, 0x34, 0x89, 0x88, 0x69, 0xd3, 0x2c, 0xd2, 0x55, 0x28, 0x14, 0x24, + 0x24, 0x24, 0x58, 0xcd, 0x17, 0x8b, 0x33, 0x80, 0x25, 0x25, 0x52, 0x73, 0x69, 0x69, 0x69, 0x21, + 0x69, 0xde, 0x7c, 0x7c, 0x7c, 0x7c, 0x70, 0x75, 0x73, 0xe3, 0xdc, 0x37, 0xdf, 0xd0, 0xd9, 0xf9, + 0x5b, 0x75, 0xad, 0xa5, 0xb9, 0x85, 0x88, 0xd0, 0x30, 0xae, 0xdc, 0x82, 0x37, 0xff, 0x3a, 0x2a, + 0x75, 0x26, 0x9f, 0x1e, 0x3a, 0x24, 0x5a, 0xaf, 0xb7, 0x85, 0x1f, 0x43, 0x2c, 0x0e, 0x80, 0x61, + 0x5e, 0xc3, 0x4c, 0x0b, 0x19, 0xf0, 0xeb, 0xaf, 0xbf, 0x9a, 0x25, 0xf7, 0xc7, 0xd9, 0x0f, 0xe2, + 0xef, 0x1f, 0xd0, 0xed, 0xf5, 0x96, 0xe6, 0x66, 0xaa, 0xaa, 0xaa, 0xa8, 0xac, 0xa8, 0x10, 0xed, + 0x83, 0xbd, 0x30, 0x61, 0xe2, 0x44, 0xa6, 0x47, 0x46, 0xf2, 0xc9, 0xc1, 0x83, 0x66, 0xeb, 0x38, + 0x3a, 0x3a, 0x92, 0x94, 0x2c, 0xbe, 0xa4, 0xdc, 0xa3, 0x4d, 0x4b, 0x15, 0xc7, 0x8c, 0xf9, 0xbd, + 0x68, 0x1d, 0xc3, 0x42, 0x46, 0x77, 0x44, 0x47, 0x3f, 0x40, 0xc2, 0xdc, 0x87, 0x4c, 0xca, 0xe5, + 0xe5, 0xe4, 0xb2, 0x2e, 0x3b, 0x5b, 0xb4, 0x1f, 0xf6, 0x82, 0x7a, 0xf9, 0x32, 0x0e, 0x7d, 0xf2, + 0x89, 0xd9, 0xf5, 0x8c, 0x39, 0xf1, 0xf1, 0x66, 0x9d, 0xae, 0x16, 0x83, 0xc5, 0x01, 0x10, 0x33, + 0x33, 0x96, 0xb5, 0x6b, 0xd6, 0x88, 0xd2, 0x29, 0x7e, 0xe7, 0x1d, 0x62, 0x66, 0xc6, 0xe2, 0xe7, + 0xe7, 0xd7, 0xa3, 0x5c, 0x5e, 0x6e, 0x2e, 0x1f, 0xbc, 0xbf, 0xbb, 0xdb, 0xeb, 0x1e, 0x0a, 0x05, + 0xea, 0x65, 0xcb, 0x49, 0x5f, 0x9c, 0xce, 0xeb, 0xaf, 0xbd, 0x26, 0xca, 0x07, 0x7b, 0x22, 0x60, + 0xfc, 0x78, 0x22, 0xa3, 0xa2, 0xd0, 0x94, 0x95, 0x99, 0x16, 0xc6, 0x7a, 0x4b, 0xbf, 0x1b, 0xb1, + 0x38, 0x00, 0xfc, 0xfc, 0xfc, 0x88, 0x9b, 0x35, 0x8b, 0x7d, 0x25, 0x25, 0x66, 0xeb, 0x9c, 0x3b, + 0x77, 0x8e, 0xb8, 0x19, 0x31, 0x78, 0x8f, 0xf0, 0xc6, 0xd5, 0xc5, 0x95, 0xfa, 0x86, 0x06, 0x94, + 0x09, 0x4a, 0xbd, 0x6d, 0xe1, 0x00, 0x0d, 0xf5, 0xf5, 0x46, 0x7b, 0xf1, 0x6f, 0x64, 0xc8, 0x85, + 0x5f, 0x68, 0x6e, 0x6e, 0xc6, 0x41, 0x2e, 0xc7, 0xb1, 0x9b, 0xd3, 0xc3, 0xb7, 0x0a, 0x2a, 0x75, + 0x26, 0x07, 0x35, 0x1a, 0x93, 0x59, 0xc0, 0x5a, 0x85, 0x1f, 0x43, 0x7a, 0xf5, 0xd7, 0x7b, 0x7e, + 0xe5, 0x0b, 0x9c, 0xfa, 0xf2, 0x4b, 0x7e, 0xf8, 0xe1, 0x07, 0xb3, 0x75, 0xba, 0xba, 0xba, 0x4c, + 0xbe, 0x0a, 0x9e, 0xc9, 0xca, 0x32, 0xeb, 0x15, 0xb0, 0xf7, 0xc3, 0xff, 0xd0, 0xda, 0xda, 0x6a, + 0xf6, 0xd8, 0xf6, 0x48, 0xc0, 0xf8, 0xf1, 0x44, 0x45, 0x47, 0x53, 0x56, 0x5a, 0xda, 0xa3, 0x5c, + 0x5f, 0x3c, 0xfd, 0xd0, 0xcb, 0x00, 0xf0, 0x1e, 0x31, 0x82, 0xe2, 0xdd, 0xbb, 0x58, 0x9e, 0xa9, + 0xa6, 0xfc, 0xb0, 0xf5, 0x4e, 0xec, 0xd6, 0xd4, 0x7c, 0xdd, 0xe3, 0x3a, 0xf9, 0xe2, 0xc5, 0x5f, + 0xf8, 0xec, 0xd8, 0x71, 0xde, 0x2b, 0x2e, 0xb6, 0xda, 0x98, 0xb6, 0x44, 0xa5, 0xce, 0x44, 0x53, + 0x56, 0xd6, 0x6d, 0x16, 0xb0, 0x66, 0xe1, 0xc7, 0x90, 0x5e, 0xe7, 0x4f, 0x6f, 0x6f, 0x6f, 0xf2, + 0x77, 0x16, 0x70, 0xac, 0xb2, 0x92, 0x3d, 0xff, 0xfa, 0x37, 0xe5, 0x87, 0x0f, 0x53, 0xf7, 0x7d, + 0x5d, 0x8f, 0x87, 0x2b, 0xe4, 0x72, 0x39, 0xc3, 0xef, 0xb8, 0x03, 0x1f, 0x1f, 0x1f, 0x46, 0x8f, + 0x1e, 0x63, 0x74, 0x3d, 0x2f, 0x27, 0x97, 0xbc, 0x9c, 0xdc, 0xde, 0xba, 0x76, 0xcb, 0xe0, 0x1f, + 0x10, 0x40, 0xf4, 0x8c, 0x07, 0x28, 0xfd, 0xf8, 0xe6, 0x1f, 0xc0, 0xac, 0x59, 0xf8, 0x31, 0xc4, + 0xe2, 0x7f, 0x11, 0xd3, 0x13, 0x9d, 0x5a, 0x2d, 0x3f, 0x5f, 0xb8, 0x40, 0x73, 0x73, 0x33, 0xda, + 0x6b, 0x6b, 0xf5, 0xa1, 0x2e, 0x2e, 0x38, 0x3b, 0x39, 0x31, 0xd4, 0xc5, 0x05, 0x4f, 0x4f, 0x4f, + 0xd1, 0x9b, 0x2d, 0x07, 0x3a, 0xff, 0x3d, 0x75, 0x8a, 0xf8, 0xd9, 0x7f, 0x32, 0xca, 0x02, 0x62, + 0x8f, 0x7a, 0x89, 0xa5, 0x4f, 0x66, 0x50, 0x72, 0x47, 0x47, 0x7c, 0x7d, 0x7d, 0xf1, 0xf5, 0xf5, + 0xed, 0x0b, 0xf3, 0x03, 0x92, 0xfb, 0xfc, 0xfd, 0x09, 0x09, 0x0d, 0x35, 0xfa, 0x52, 0xf8, 0x48, + 0x72, 0x72, 0x9f, 0xdd, 0x7c, 0xb0, 0xd3, 0x52, 0xf0, 0x60, 0xa4, 0xad, 0xad, 0x8d, 0xd3, 0xa7, + 0x4f, 0xeb, 0xf5, 0x39, 0x3a, 0x3a, 0x92, 0x2c, 0xf2, 0xa8, 0x97, 0x58, 0xa4, 0x00, 0xb0, 0x13, + 0x76, 0xbd, 0xf7, 0x9e, 0xd1, 0xf1, 0xb4, 0x39, 0xf1, 0xf1, 0xdc, 0xe9, 0x63, 0xdd, 0xc2, 0x8f, + 0x21, 0x52, 0x00, 0xd8, 0x01, 0x82, 0x20, 0xf0, 0xf6, 0x0e, 0xe3, 0xdd, 0xcd, 0x7d, 0xb5, 0xf4, + 0xbb, 0x11, 0x29, 0x00, 0xec, 0x80, 0xb2, 0x03, 0xa5, 0x9c, 0x3d, 0x7b, 0x56, 0xaf, 0x2f, 0x34, + 0x2c, 0xac, 0x4f, 0x0a, 0x3f, 0x86, 0x48, 0x01, 0x60, 0x07, 0x6c, 0xdd, 0xb2, 0xc5, 0xa8, 0x2f, + 0x35, 0x3d, 0xbd, 0x5f, 0xc6, 0x96, 0x02, 0xc0, 0xc6, 0x7c, 0x75, 0xe6, 0x2b, 0xa3, 0x9d, 0xc2, + 0x7e, 0x7e, 0x7e, 0x44, 0x45, 0x47, 0xf5, 0xcb, 0xf8, 0x52, 0x00, 0xd8, 0x98, 0x2d, 0x9b, 0x37, + 0x1b, 0xad, 0xfd, 0xfb, 0xb2, 0xf0, 0x63, 0x48, 0x9f, 0x14, 0x82, 0x24, 0xcc, 0xa3, 0xbe, 0xbe, + 0x9e, 0xe9, 0x61, 0xe1, 0x7a, 0xfb, 0x24, 0xfa, 0xba, 0xf0, 0x63, 0x88, 0x94, 0x01, 0x6c, 0xc8, + 0xdb, 0x3b, 0x76, 0x18, 0x6d, 0x92, 0x49, 0x4a, 0xb1, 0xee, 0x8e, 0x1f, 0x53, 0x48, 0x19, 0xc0, + 0x86, 0xb4, 0xb6, 0xb6, 0xa2, 0x35, 0x38, 0xdd, 0xe4, 0xea, 0xea, 0xda, 0xaf, 0x9f, 0xb8, 0xa5, + 0x00, 0x18, 0xe4, 0x38, 0x00, 0xb7, 0xd6, 0xf9, 0x2a, 0x09, 0xab, 0xe2, 0x00, 0xf4, 0xfe, 0xdf, + 0x63, 0x49, 0xdc, 0xaa, 0x34, 0x3a, 0x00, 0xe2, 0x0e, 0xaa, 0x49, 0x0c, 0x24, 0xca, 0x65, 0x82, + 0x20, 0x44, 0x03, 0x07, 0x90, 0xe6, 0x01, 0x83, 0x0d, 0x01, 0x88, 0x75, 0x90, 0xc9, 0x64, 0x65, + 0xc0, 0x8b, 0xb6, 0xf6, 0x46, 0xa2, 0xdf, 0xf9, 0x9b, 0x4c, 0x26, 0x3b, 0xa0, 0x7b, 0xea, 0x05, + 0x41, 0x98, 0x0b, 0xa8, 0x81, 0x89, 0xc0, 0x50, 0x9b, 0xb9, 0x25, 0xd1, 0x97, 0xb4, 0x03, 0x9f, + 0x03, 0xeb, 0x65, 0x32, 0xd9, 0x2e, 0x80, 0xff, 0x03, 0xff, 0x08, 0x81, 0xdd, 0xa8, 0xcb, 0xf5, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +}; diff --git a/examples/device/mtp/src/tusb_config.h b/examples/device/mtp/src/tusb_config.h new file mode 100644 index 000000000..95cc048ee --- /dev/null +++ b/examples/device/mtp/src/tusb_config.h @@ -0,0 +1,139 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ennebi Elettronica (https://ennebielettronica.com) + * + * 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. + * + */ + +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +// 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 + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable 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 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_MTP 1 +#define CFG_TUD_MTP_EP_BUFSIZE 512 +#define CFG_TUD_MTP_EP_CONTROL_BUFSIZE 16 // should be enough to hold data in MTP control request + +//------------- MTP device info -------------// +#define CFG_TUD_MTP_DEVICEINFO_EXTENSIONS "microsoft.com: 1.0; " +#define CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS \ + MTP_OP_GET_DEVICE_INFO, \ + MTP_OP_OPEN_SESSION, \ + MTP_OP_CLOSE_SESSION, \ + MTP_OP_GET_STORAGE_IDS, \ + MTP_OP_GET_STORAGE_INFO, \ + MTP_OP_GET_OBJECT_HANDLES, \ + MTP_OP_GET_OBJECT_INFO, \ + MTP_OP_GET_OBJECT, \ + MTP_OP_DELETE_OBJECT, \ + MTP_OP_SEND_OBJECT_INFO, \ + MTP_OP_SEND_OBJECT, \ + MTP_OP_RESET_DEVICE, \ + MTP_OP_GET_DEVICE_PROP_DESC, \ + MTP_OP_GET_DEVICE_PROP_VALUE, \ + MTP_OP_SET_DEVICE_PROP_VALUE + +#define CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS \ + MTP_EVENT_OBJECT_ADDED + +#define CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES \ + MTP_DEV_PROP_DEVICE_FRIENDLY_NAME + +#define CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS \ + MTP_OBJ_FORMAT_UNDEFINED, \ + MTP_OBJ_FORMAT_ASSOCIATION, \ + MTP_OBJ_FORMAT_TEXT, \ + MTP_OBJ_FORMAT_PNG + +#define CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS \ + MTP_OBJ_FORMAT_UNDEFINED, \ + MTP_OBJ_FORMAT_ASSOCIATION, \ + MTP_OBJ_FORMAT_TEXT, \ + MTP_OBJ_FORMAT_PNG + +#ifdef __cplusplus + } +#endif + +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/mtp/src/usb_descriptors.c b/examples/device/mtp/src/usb_descriptors.c new file mode 100644 index 000000000..f0aa3de6b --- /dev/null +++ b/examples/device/mtp/src/usb_descriptors.c @@ -0,0 +1,255 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + * + */ + +#include "bsp/board_api.h" +#include "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] MTP | VENDOR | MIDI | HID | MSC | CDC [LSB] + */ +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) | PID_MAP(MTP, 5)) + +#define USB_VID 0xCafe +#define USB_BCD 0x0200 + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +static tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + .bDeviceClass = TUSB_CLASS_UNSPECIFIED, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const *tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +enum +{ + ITF_NUM_MTP = 0, + ITF_NUM_TOTAL +}; + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ... + #define EPNUM_MTP_EVT 0x81 + #define EPNUM_MTP_OUT 0x02 + #define EPNUM_MTP_IN 0x82 + +#elif CFG_TUSB_MCU == OPT_MCU_CXD56 + // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number + // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN) + #define EPNUM_MTP_EVT 0x83 + #define EPNUM_MTP_OUT 0x02 + #define EPNUM_MTP_IN 0x81 + +#elif defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY) + // MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h + // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_MTP_EVT 0x81 + #define EPNUM_MTP_OUT 0x03 + #define EPNUM_MTP_IN 0x82 + +#else + #define EPNUM_MTP_EVT 0x81 + #define EPNUM_MTP_OUT 0x02 + #define EPNUM_MTP_IN 0x82 +#endif + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MTP_DESC_LEN) + +// full speed configuration +const uint8_t desc_fs_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + // Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size + TUD_MTP_DESCRIPTOR(ITF_NUM_MTP, 4, EPNUM_MTP_EVT, 64, 1, EPNUM_MTP_OUT, EPNUM_MTP_IN, 64), +}; + +#if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + +// high speed configuration +static uint8_t const desc_hs_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + // Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size + TUD_MTP_DESCRIPTOR(ITF_NUM_MTP, 4, EPNUM_MTP_EVT, 64, 1, EPNUM_MTP_OUT, EPNUM_MTP_IN, 512), +}; + +// other speed configuration +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +static tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const *tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const *) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG + memcpy(desc_other_speed_config, + (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, + CONFIG_TOTAL_LEN); + desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; + return desc_other_speed_config; +} + +#endif // highspeed + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +const uint8_t*tud_descriptor_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// String Descriptor Index +enum { + STRID_LANGID = 0, + STRID_MANUFACTURER, + STRID_PRODUCT, + STRID_SERIAL, + STRID_MTP, +}; + +// array of pointer to string descriptors +static char const *string_desc_arr[] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "TinyUsb", // 1: Manufacturer + "TinyUsb Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible + "TinyUSB MTP", // 4: MTP Interface +}; + +static uint16_t _desc_str[32 + 1]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void) langid; + size_t chr_count; + + switch ( index ) { + case STRID_LANGID: + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + break; + + case STRID_SERIAL: + chr_count = board_usb_get_serial(_desc_str + 1, 32); + break; + + default: + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) { + return NULL; + } + + const char *str = string_desc_arr[index]; + // Cap at max char + chr_count = strlen(str); + const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if ( chr_count > max_count ) { + chr_count = max_count; + } + + // Convert ASCII string into UTF-16 + for ( size_t i = 0; i < chr_count; i++ ) { + _desc_str[1 + i] = str[i]; + } + break; + } + + // first byte is length (including header), second byte is string type + _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + + return _desc_str; +} diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index 4ad110dec..9d8e8ec77 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -1,4 +1,4 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk # suppress warning caused by lwip CFLAGS_GCC += \ @@ -8,7 +8,6 @@ CFLAGS_GCC += \ INC += \ src \ - $(TOP)/hw \ $(TOP)/lib/lwip/src/include \ $(TOP)/lib/lwip/src/include/ipv4 \ $(TOP)/lib/lwip/src/include/lwip/apps \ @@ -16,7 +15,7 @@ INC += \ # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) # lwip sources SRC_C += \ @@ -66,4 +65,4 @@ SRC_C += \ lib/networking/dnserver.c \ lib/networking/rndis_reports.c -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 6121f1f9d..ecb9eb7ec 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -20,3 +20,5 @@ board:curiosity_nano board:frdm_kl25z # lpc55 has weird error 'ncm_interface' causes a section type conflict with 'ntb_parameters' family:lpc55 +family:nuc126 +family:nuc100_120 diff --git a/examples/device/net_lwip_webserver/src/arch/cc.h b/examples/device/net_lwip_webserver/src/arch/cc.h index 9f30b91cb..c3fc12dda 100644 --- a/examples/device/net_lwip_webserver/src/arch/cc.h +++ b/examples/device/net_lwip_webserver/src/arch/cc.h @@ -29,8 +29,8 @@ * Author: Adam Dunkels <[email protected]> * */ -#ifndef __CC_H__ -#define __CC_H__ +#ifndef CC_H__ +#define CC_H__ //#include "cpu.h" @@ -72,4 +72,4 @@ typedef int sys_prot_t; #define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) -#endif /* __CC_H__ */ +#endif /* CC_H__ */ diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h index 04949cef9..11686ce2a 100644 --- a/examples/device/net_lwip_webserver/src/lwipopts.h +++ b/examples/device/net_lwip_webserver/src/lwipopts.h @@ -29,8 +29,8 @@ * Author: Simon Goldschmidt * */ -#ifndef __LWIPOPTS_H__ -#define __LWIPOPTS_H__ +#ifndef LWIPOPTS_H__ +#define LWIPOPTS_H__ /* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ #define NO_SYS 1 diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index dd9f213ae..867cf2812 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -58,6 +58,7 @@ try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 #include "lwip/ethip6.h" #include "lwip/init.h" #include "lwip/timeouts.h" +#include "lwip/sys.h" #ifdef INCLUDE_IPERF #include "lwip/apps/lwiperf.h" @@ -172,7 +173,7 @@ static void init_lwip(void) { } /* handle any DNS requests from dns-server */ -bool dns_query_proc(const char *name, ip4_addr_t *addr) { +static bool dns_query_proc(const char *name, ip4_addr_t *addr) { if (0 == strcmp(name, "tiny.usb")) { *addr = ipaddr; return true; diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index c774f59ff..3285ea52c 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -88,7 +88,7 @@ extern "C" { #ifndef USE_ECM #if TU_CHECK_MCU(OPT_MCU_LPC15XX, OPT_MCU_LPC40XX, OPT_MCU_LPC51UXX, OPT_MCU_LPC54) #define USE_ECM 1 -#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML21, OPT_MCU_SAML22) +#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML2X) #define USE_ECM 1 #elif TU_CHECK_MCU(OPT_MCU_STM32F0, OPT_MCU_STM32F1) #define USE_ECM 1 @@ -141,4 +141,4 @@ extern "C" { } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index cd800f521..c976cb62b 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -24,6 +24,7 @@ */ #include "bsp/board_api.h" +#include "class/net/net_device.h" #include "tusb.h" /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. @@ -32,35 +33,34 @@ * Auto ProductID layout's Bitmap: * [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(ECM_RNDIS, 5) | _PID_MAP(NCM, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID \ + (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) | \ + PID_MAP(ECM_RNDIS, 5) | PID_MAP(NCM, 5)) // String Descriptor Index -enum -{ +enum { STRID_LANGID = 0, STRID_MANUFACTURER, STRID_PRODUCT, STRID_SERIAL, STRID_INTERFACE, - STRID_MAC + STRID_MAC, + STRID_COUNT }; -enum -{ +enum { ITF_NUM_CDC = 0, ITF_NUM_CDC_DATA, ITF_NUM_TOTAL }; -enum -{ +enum { #if CFG_TUD_ECM_RNDIS CONFIG_ID_RNDIS = 0, CONFIG_ID_ECM = 1, #else - CONFIG_ID_NCM = 0, + CONFIG_ID_NCM = 0, #endif CONFIG_ID_COUNT }; @@ -68,103 +68,103 @@ enum //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, +static const tusb_desc_device_t desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, #if CFG_TUD_NCM - .bcdUSB = 0x0201, + .bcdUSB = 0x0201, #else - .bcdUSB = 0x0200, + .bcdUSB = 0x0200, #endif - // Use Interface Association Descriptor (IAD) device class - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, + // Use Interface Association Descriptor (IAD) device class + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0101, + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0101, - .iManufacturer = STRID_MANUFACTURER, - .iProduct = STRID_PRODUCT, - .iSerialNumber = STRID_SERIAL, + .iManufacturer = STRID_MANUFACTURER, + .iProduct = STRID_PRODUCT, + .iSerialNumber = STRID_SERIAL, - .bNumConfigurations = CONFIG_ID_COUNT // multiple configurations + .bNumConfigurations = CONFIG_ID_COUNT // multiple configurations }; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; +const uint8_t *tud_descriptor_device_cb(void) { + return (const uint8_t *)&desc_device; } //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) -#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) -#define NCM_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_NCM_DESC_LEN) +#define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) +#define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) +#define NCM_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_NCM_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX - // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_NET_NOTIF 0x81 - #define EPNUM_NET_OUT 0x02 - #define EPNUM_NET_IN 0x82 +// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number +// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... +#define EPNUM_NET_NOTIF 0x81 +#define EPNUM_NET_OUT 0x02 +#define EPNUM_NET_IN 0x82 #elif CFG_TUSB_MCU == OPT_MCU_CXD56 - // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number - // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN) - #define EPNUM_NET_NOTIF 0x83 - #define EPNUM_NET_OUT 0x02 - #define EPNUM_NET_IN 0x81 +// CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number +// 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN) +#define EPNUM_NET_NOTIF 0x83 +#define EPNUM_NET_OUT 0x02 +#define EPNUM_NET_IN 0x81 #elif defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY) - // MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h - // e.g EP1 OUT & EP1 IN cannot exist together - #define EPNUM_NET_NOTIF 0x81 - #define EPNUM_NET_OUT 0x02 - #define EPNUM_NET_IN 0x83 +// MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h +// e.g EP1 OUT & EP1 IN cannot exist together +#define EPNUM_NET_NOTIF 0x81 +#define EPNUM_NET_OUT 0x02 +#define EPNUM_NET_IN 0x83 #else - #define EPNUM_NET_NOTIF 0x81 - #define EPNUM_NET_OUT 0x02 - #define EPNUM_NET_IN 0x82 +#define EPNUM_NET_NOTIF 0x81 +#define EPNUM_NET_OUT 0x02 +#define EPNUM_NET_IN 0x82 #endif #if CFG_TUD_ECM_RNDIS -static uint8_t const rndis_configuration[] = -{ +static uint8_t const rndis_configuration[] = { // Config number (index+1), interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS+1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS + 1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_NET_NOTIF, 8, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE), + TUD_RNDIS_DESCRIPTOR( + ITF_NUM_CDC, STRID_INTERFACE, EPNUM_NET_NOTIF, 8, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE), }; -static uint8_t const ecm_configuration[] = -{ +static const uint8_t ecm_configuration[] = { // Config number (index+1), interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM+1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM + 1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), + TUD_CDC_ECM_DESCRIPTOR( + ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, + CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), }; #else -static uint8_t const ncm_configuration[] = -{ +static uint8_t const ncm_configuration[] = { // Config number (index+1), interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(CONFIG_ID_NCM+1, ITF_NUM_TOTAL, 0, NCM_CONFIG_TOTAL_LEN, 0, 100), + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_NCM + 1, ITF_NUM_TOTAL, 0, NCM_CONFIG_TOTAL_LEN, 0, 100), // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), + TUD_CDC_NCM_DESCRIPTOR( + ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, + CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), }; #endif @@ -173,21 +173,19 @@ static uint8_t const ncm_configuration[] = // - Windows only works with RNDIS // - MacOS only works with CDC-ECM // - Linux will work on both -static uint8_t const * const configuration_arr[2] = -{ +static const uint8_t *const configuration_arr[CONFIG_ID_COUNT] = { #if CFG_TUD_ECM_RNDIS [CONFIG_ID_RNDIS] = rndis_configuration, - [CONFIG_ID_ECM ] = ecm_configuration + [CONFIG_ID_ECM] = ecm_configuration #else - [CONFIG_ID_NCM ] = ncm_configuration + [CONFIG_ID_NCM] = ncm_configuration #endif }; // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ +const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { return (index < CONFIG_ID_COUNT) ? configuration_arr[index] : NULL; } @@ -213,61 +211,62 @@ https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/ (Section Microsoft OS compatibility descriptors) */ -#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) +#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) -#define MS_OS_20_DESC_LEN 0xB2 +#define MS_OS_20_DESC_LEN 0xB2 // BOS Descriptor is required for webUSB -uint8_t const desc_bos[] = -{ +const uint8_t desc_bos[] = { // total length, number of device caps TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 1), // Microsoft OS 2.0 descriptor - TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, 1) -}; + TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, 1)}; -uint8_t const * tud_descriptor_bos_cb(void) -{ +const uint8_t *tud_descriptor_bos_cb(void) { return desc_bos; } -uint8_t const desc_ms_os_20[] = -{ +const uint8_t desc_ms_os_20[] = { // Set header: length, type, windows version, total length - U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN), + U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), + U16_TO_U8S_LE(MS_OS_20_DESC_LEN), // Configuration subset header: length, type, configuration index, reserved, configuration total length - U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A), + U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, + U16_TO_U8S_LE(MS_OS_20_DESC_LEN - 0x0A), // Function Subset header: length, type, first interface, reserved, subset length - U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), ITF_NUM_CDC, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08), + U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), ITF_NUM_CDC, 0, + U16_TO_U8S_LE(MS_OS_20_DESC_LEN - 0x0A - 0x08), // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID - U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'N', 'C', 'M', 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible + U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'N', 'C', 'M', 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible // MS OS 2.0 Registry property descriptor: length, type - U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08-0x08-0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), - U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16 - 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, - 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00, + U16_TO_U8S_LE(MS_OS_20_DESC_LEN - 0x0A - 0x08 - 0x08 - 0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), + U16_TO_U8S_LE(0x0007), + U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16 + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', + 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00, U16_TO_U8S_LE(0x0050), // wPropertyDataLength - //bPropertyData: {12345678-0D08-43FD-8B3E-127CA8AFFF9D} - '{', 0x00, '1', 0x00, '2', 0x00, '3', 0x00, '4', 0x00, '5', 0x00, '6', 0x00, '7', 0x00, '8', 0x00, '-', 0x00, - '0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00, - '8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00, - '8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 -}; + //bPropertyData: {12345678-0D08-43FD-8B3E-127CA8AFFF9D} + '{', 0x00, '1', 0x00, '2', 0x00, '3', 0x00, '4', 0x00, '5', 0x00, '6', 0x00, '7', 0x00, '8', 0x00, '-', 0x00, '0', + 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00, '8', 0x00, + 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00, '8', 0x00, 'A', + 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00}; TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size"); // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) { +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t *request) { // nothing to with DATA & ACK stage - if (stage != CONTROL_STAGE_SETUP) return true; + if (stage != CONTROL_STAGE_SETUP) { + return true; + } switch (request->bmRequestType_bit.type) { case TUSB_REQ_TYPE_VENDOR: @@ -278,16 +277,18 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ uint16_t total_len; memcpy(&total_len, desc_ms_os_20 + 8, 2); - return tud_control_xfer(rhport, request, (void*)(uintptr_t)desc_ms_os_20, total_len); + return tud_control_xfer(rhport, request, (void *)(uintptr_t)desc_ms_os_20, total_len); } else { return false; } - default: break; + default: + break; // nothing to do } break; - default: break; + default: + break; // nothing to do } // stall unknown request @@ -300,26 +301,24 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ //--------------------------------------------------------------------+ // array of pointer to string descriptors -static char const* string_desc_arr [] = -{ - [STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) - [STRID_MANUFACTURER] = "TinyUSB", // Manufacturer - [STRID_PRODUCT] = "TinyUSB Device", // Product - [STRID_SERIAL] = NULL, // Serials will use unique ID if possible - [STRID_INTERFACE] = "TinyUSB Network Interface" // Interface Description - - // STRID_MAC index is handled separately +static const char *string_desc_arr[STRID_COUNT] = { + [STRID_LANGID] = (const char[]){0x09, 0x04}, // supported language is English (0x0409) + [STRID_MANUFACTURER] = "TinyUSB", // Manufacturer + [STRID_PRODUCT] = "TinyUSB Device", // Product + [STRID_SERIAL] = NULL, // Serials will use unique ID if possible + [STRID_INTERFACE] = "TinyUSB Network Interface", // Interface Description + [STRID_MAC] = NULL // STRID_MAC index is handled separately }; static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - (void) langid; +const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + (void)langid; unsigned int chr_count = 0; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; @@ -331,34 +330,40 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) { case STRID_MAC: // Convert MAC address into UTF-16 - for (unsigned i=0; i<sizeof(tud_network_mac_address); i++) { - _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf]; - _desc_str[1+chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf]; + for (unsigned i = 0; i < sizeof(tud_network_mac_address); i++) { + _desc_str[1 + chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 4) & 0xf]; + _desc_str[1 + chr_count++] = "0123456789ABCDEF"[(tud_network_mac_address[i] >> 0) & 0xf]; } break; - default: + default: { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (index >= sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); - size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + + const size_t max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; + } } // first byte is length (including header), second byte is string type - _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2)); + _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); return _desc_str; } diff --git a/examples/device/uac2_headset/Makefile b/examples/device/uac2_headset/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/uac2_headset/Makefile +++ b/examples/device/uac2_headset/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 102a6eef1..96fa66f1e 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -73,7 +73,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 +uint8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1];// +1 for master channel 0 // Buffer for microphone data @@ -141,18 +141,195 @@ void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } +//--------------------------------------------------------------------+ +// Audio Callback Functions +//--------------------------------------------------------------------+ + +//--------------------------------------------------------------------+ +// UAC1 Helper Functions +//--------------------------------------------------------------------+ + +static bool audio10_set_req_ep(tusb_control_request_t const *p_request, uint8_t *pBuff) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + + switch (ctrlSel) { + case AUDIO10_EP_CTRL_SAMPLING_FREQ: + if (p_request->bRequest == AUDIO10_CS_REQ_SET_CUR) { + // Request uses 3 bytes + TU_VERIFY(p_request->wLength == 3); + + current_sample_rate = tu_unaligned_read32(pBuff) & 0x00FFFFFF; + + TU_LOG2("EP set current freq: %" PRIu32 "\r\n", current_sample_rate); + + return true; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + + return false; +} + +static bool audio10_get_req_ep(uint8_t rhport, tusb_control_request_t const *p_request) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + + switch (ctrlSel) { + case AUDIO10_EP_CTRL_SAMPLING_FREQ: + if (p_request->bRequest == AUDIO10_CS_REQ_GET_CUR) { + TU_LOG2("EP get current freq\r\n"); + + uint8_t freq[3]; + freq[0] = (uint8_t) (current_sample_rate & 0xFF); + freq[1] = (uint8_t) ((current_sample_rate >> 8) & 0xFF); + freq[2] = (uint8_t) ((current_sample_rate >> 16) & 0xFF); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, freq, sizeof(freq)); + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + + return false; +} + +static bool audio10_set_req_entity(tusb_control_request_t const *p_request, uint8_t *pBuff) { + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // If request is for our speaker feature unit + if (entityID == UAC1_ENTITY_SPK_FEATURE_UNIT) { + switch (ctrlSel) { + case AUDIO10_FU_CTRL_MUTE: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_SET_CUR: + // Only 1st form is supported + TU_VERIFY(p_request->wLength == 1); + + mute[channelNum] = pBuff[0]; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; + + default: + return false; // not supported + } + + case AUDIO10_FU_CTRL_VOLUME: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_SET_CUR: + // Only 1st form is supported + TU_VERIFY(p_request->wLength == 2); + + volume[channelNum] = (int16_t)tu_unaligned_read16(pBuff) / 256; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; + + default: + return false; // not supported + } + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + return false; +} + +static bool audio10_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) { + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // If request is for our speaker feature unit + if (entityID == UAC1_ENTITY_SPK_FEATURE_UNIT) { + switch (ctrlSel) { + case AUDIO10_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO10_FU_CTRL_VOLUME: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_GET_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + { + int16_t vol = (int16_t) volume[channelNum]; + vol = vol * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &vol, sizeof(vol)); + } + + case AUDIO10_CS_REQ_GET_MIN: + TU_LOG2(" Get Volume min of channel: %u\r\n", channelNum); + { + int16_t min = -90; // -90 dB + min = min * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &min, sizeof(min)); + } + + case AUDIO10_CS_REQ_GET_MAX: + TU_LOG2(" Get Volume max of channel: %u\r\n", channelNum); + { + int16_t max = 30; // +30 dB + max = max * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &max, sizeof(max)); + } + + case AUDIO10_CS_REQ_GET_RES: + TU_LOG2(" Get Volume res of channel: %u\r\n", channelNum); + { + int16_t res = 1; // 1 dB + res = res * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &res, sizeof(res)); + } + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + return false; +} + +//--------------------------------------------------------------------+ +// UAC2 Helper Functions +//--------------------------------------------------------------------+ + +#if TUD_OPT_HIGH_SPEED + // Helper for clock get requests -static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) { +static bool audio20_clock_get_request(uint8_t rhport, audio20_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { - if (request->bRequest == AUDIO_CS_REQ_CUR) { + if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) { + if (request->bRequest == AUDIO20_CS_REQ_CUR) { TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); - audio_control_cur_4_t curf = {(int32_t) tu_htole32(current_sample_rate)}; + audio20_control_cur_4_t curf = {(int32_t) tu_htole32(current_sample_rate)}; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &curf, sizeof(curf)); - } else if (request->bRequest == AUDIO_CS_REQ_RANGE) { - audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = + } else if (request->bRequest == AUDIO20_CS_REQ_RANGE) { + audio20_control_range_4_n_t(N_SAMPLE_RATES) rangef = { .wNumSubRanges = tu_htole16(N_SAMPLE_RATES)}; TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES); @@ -165,9 +342,9 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &rangef, sizeof(rangef)); } - } else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && - request->bRequest == AUDIO_CS_REQ_CUR) { - audio_control_cur_1_t cur_valid = {.bCur = 1}; + } else if (request->bControlSelector == AUDIO20_CS_CTRL_CLK_VALID && + request->bRequest == AUDIO20_CS_REQ_CUR) { + audio20_control_cur_1_t cur_valid = {.bCur = 1}; TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_valid, sizeof(cur_valid)); } @@ -177,16 +354,16 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t } // Helper for clock set requests -static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { +static bool audio20_clock_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) { (void) rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); + if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) { + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_4_t)); - current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *) buf)->bCur; + current_sample_rate = (uint32_t) ((audio20_control_cur_4_t const *) buf)->bCur; TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); @@ -199,23 +376,23 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t } // Helper for feature unit get requests -static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) { +static bool audio20_feature_unit_get_request(uint8_t rhport, audio20_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) { - audio_control_cur_1_t mute1 = {.bCur = mute[request->bChannelNumber]}; + if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE && request->bRequest == AUDIO20_CS_REQ_CUR) { + audio20_control_cur_1_t mute1 = {.bCur = mute[request->bChannelNumber]}; TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &mute1, sizeof(mute1)); - } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { - if (request->bRequest == AUDIO_CS_REQ_RANGE) { - audio_control_range_2_n_t(1) range_vol = { + } else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) { + if (request->bRequest == AUDIO20_CS_REQ_RANGE) { + audio20_control_range_2_n_t(1) range_vol = { .wNumSubRanges = tu_htole16(1), .subrange[0] = {.bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256)}}; TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &range_vol, sizeof(range_vol)); - } else if (request->bRequest == AUDIO_CS_REQ_CUR) { - audio_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[request->bChannelNumber])}; + } else if (request->bRequest == AUDIO20_CS_REQ_CUR) { + audio20_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[request->bChannelNumber])}; TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_vol, sizeof(cur_vol)); } @@ -227,24 +404,24 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req } // Helper for feature unit set requests -static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { +static bool audio20_feature_unit_set_request(uint8_t rhport, audio20_control_request_t const *request, uint8_t const *buf) { (void) rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); - TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t)); + if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE) { + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_1_t)); - mute[request->bChannelNumber] = ((audio_control_cur_1_t const *) buf)->bCur; + mute[request->bChannelNumber] = ((audio20_control_cur_1_t const *) buf)->bCur; TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; - } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_2_t)); + } else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) { + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_2_t)); - volume[request->bChannelNumber] = ((audio_control_cur_2_t const *) buf)->bCur; + volume[request->bChannelNumber] = ((audio20_control_cur_2_t const *) buf)->bCur; TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); @@ -256,18 +433,13 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req } } -//--------------------------------------------------------------------+ -// Application Callback API Implementations -//--------------------------------------------------------------------+ - -// Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - audio_control_request_t const *request = (audio_control_request_t const *) p_request; +static bool audio20_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) { + audio20_control_request_t const *request = (audio20_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_CLOCK) - return tud_audio_clock_get_request(rhport, request); + return audio20_clock_get_request(rhport, request); if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) - return tud_audio_feature_unit_get_request(rhport, request); + return audio20_feature_unit_get_request(rhport, request); else { TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); @@ -275,20 +447,78 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false; } -// Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { - audio_control_request_t const *request = (audio_control_request_t const *) p_request; +static bool audio20_set_req_entity(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { + audio20_control_request_t const *request = (audio20_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) - return tud_audio_feature_unit_set_request(rhport, request, buf); + return audio20_feature_unit_set_request(rhport, request, buf); if (request->bEntityID == UAC2_ENTITY_CLOCK) - return tud_audio_clock_set_request(rhport, request, buf); + return audio20_clock_set_request(rhport, request, buf); TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); return false; } +#endif // TUD_OPT_HIGH_SPEED + +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { + (void) rhport; + (void) pBuff; + + if (tud_audio_version() == 1) { + return audio10_set_req_ep(p_request, pBuff); + } else if (tud_audio_version() == 2) { + // We do not support any requests here + } + + return false;// Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_get_req_ep(rhport, p_request); + } else if (tud_audio_version() == 2) { + // We do not support any requests here + } + + return false;// Yet not implemented +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_get_req_entity(rhport, p_request); +#if TUD_OPT_HIGH_SPEED + } else if (tud_audio_version() == 2) { + return audio20_get_req_entity(rhport, p_request); +#endif + } + + return false; +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_set_req_entity(p_request, buf); +#if TUD_OPT_HIGH_SPEED + } else if (tud_audio_version() == 2) { + return audio20_set_req_entity(rhport, p_request, buf); +#endif + } + + return false; +} + bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; @@ -380,6 +610,10 @@ void audio_control_task(void) { uint32_t btn = board_button_read(); + // Even UAC1 spec have status interrupt support like UAC2, most host do not support it + // So you have to either use UAC2 or use old day HID volume control + TU_VERIFY((tud_audio_version() == 1),); + if (!btn_prev && btn) { // Adjust volume between 0dB (100%) and -30dB (10%) for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++) { @@ -387,14 +621,14 @@ void audio_control_task(void) { } // 6.1 Interrupt Data Message - const audio_interrupt_data_t data = { + const audio_interrupt_data_t data = {.v2 = { .bInfo = 0, // Class-specific interrupt, originated from an interface - .bAttribute = AUDIO_CS_REQ_CUR, // Caused by current settings + .bAttribute = AUDIO20_CS_REQ_CUR, // Caused by current settings .wValue_cn_or_mcn = 0, // CH0: master volume - .wValue_cs = AUDIO_FU_CTRL_VOLUME, // Volume change + .wValue_cs = AUDIO20_FU_CTRL_VOLUME, // Volume change .wIndex_ep_or_int = 0, // From the interface itself .wIndex_entity_id = UAC2_ENTITY_SPK_FEATURE_UNIT,// From feature unit - }; + }}; tud_audio_int_write(&data); } diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index e9165163b..a43a4bd25 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -24,8 +24,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -108,8 +108,6 @@ extern "C" { // Allow volume controlled by on-baord button #define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 1 -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_HEADSET_STEREO_DESC_LEN - // How many formats are used, need to adjust USB descriptor if changed #define CFG_TUD_AUDIO_FUNC_1_N_FORMATS 2 @@ -126,43 +124,48 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX 2 #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX 16 -#if defined(__RX__) -// 8bit in 8bit slots -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 1 -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 8 -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 1 -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 8 -#else -// 24bit in 32bit slots +// 24bit in 32bit slots (UAC2 only) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX 4 #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX 24 #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX 4 #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX 24 -#endif // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +// UAC1 (Full-Speed) Endpoint size calculation +#define CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(false, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) + +// UAC2 (High-Speed) Endpoint size calculation +#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) +#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device +// Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, TU_MAX(CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN)) + +// Tx flow control needs buffer size >= 4* EP size to work correctly +// Example write FIFO every 1ms (8 HS frames), so buffer size should be 8 times larger for HS device +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(4 * CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, TU_MAX(32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_IN, 32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_IN)) // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +// UAC1 (Full-Speed) Endpoint size calculation +#define CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(false, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) + +// UAC2 (High-Speed) Endpoint size calculation +#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +#define CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device +// Maximum EP OUT size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT, TU_MAX(CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_OUT)) -// Size of control request buffer -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 +// Rx flow control needs buffer size >= 4* EP size to work correctly +// Example read FIFO every 1ms (8 HS frames), so buffer size should be 8 times larger for HS device +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(4 * CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT, TU_MAX(32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_1_EP_SZ_OUT, 32 * CFG_TUD_AUDIO20_FUNC_1_FORMAT_2_EP_SZ_OUT)) #ifdef __cplusplus } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/uac2_headset/src/usb_descriptors.c b/examples/device/uac2_headset/src/usb_descriptors.c index bc9160d5e..e4fbbf8a5 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.c +++ b/examples/device/uac2_headset/src/usb_descriptors.c @@ -34,14 +34,14 @@ * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -87,9 +87,9 @@ uint8_t const * tud_descriptor_device_cb(void) #elif CFG_TUSB_MCU == OPT_MCU_CXD56 // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN) - // #define EPNUM_AUDIO_IN 0x01 - // #define EPNUM_AUDIO_OUT 0x02 - // #define EPNUM_AUDIO_INT 0x03 + #define EPNUM_AUDIO_IN 0x01 + #define EPNUM_AUDIO_OUT 0x02 + #define EPNUM_AUDIO_INT 0x03 #elif CFG_TUSB_MCU == OPT_MCU_NRF5X // ISO endpoints for NRF5x are fixed to 0x08 (0x88) @@ -110,22 +110,93 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_AUDIO_INT 0x02 #endif -uint8_t const desc_configuration[] = +#define CONFIG_UAC1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO10_HEADSET_STEREO_DESC_LEN(2)) + +uint8_t const desc_uac1_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC1_TOTAL_LEN, 0x00, 100), + + // Interface number, string index, bytes per sample RX/TX, bits used per sample RX/TX, EP Out & EP In address, EP sizes, sample rate + TUD_AUDIO10_HEADSET_STEREO_DESCRIPTOR(ITF_NUM_AUDIO_CONTROL, 4, \ + CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX, \ + CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX, \ + EPNUM_AUDIO_OUT, CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_OUT, \ + EPNUM_AUDIO_IN | 0x80, CFG_TUD_AUDIO10_FUNC_1_FORMAT_1_EP_SZ_IN, \ + 44100, 48000) +}; + +TU_VERIFY_STATIC(sizeof(desc_uac1_configuration) == CONFIG_UAC1_TOTAL_LEN, "Incorrect size"); + +#if TUD_OPT_HIGH_SPEED + +#define CONFIG_UAC2_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO20_HEADSET_STEREO_DESC_LEN) + +uint8_t const desc_uac2_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC2_TOTAL_LEN, 0x00, 100), - // Interface number, string index, EP Out & EP In address, EP size - TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80, EPNUM_AUDIO_INT | 0x80) + // String index, EP Out & EP In address, EP Interrupt address + TUD_AUDIO20_HEADSET_STEREO_DESCRIPTOR(5, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80, EPNUM_AUDIO_INT | 0x80) }; +TU_VERIFY_STATIC(sizeof(desc_uac2_configuration) == CONFIG_UAC2_TOTAL_LEN, "Incorrect size"); + + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = +{ + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = 0x0200, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const *tud_descriptor_device_qualifier_cb(void) +{ + return (uint8_t const *) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_uac1_configuration : desc_uac2_configuration; +} +#endif + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void)index; // for multiple configurations - return desc_configuration; +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + if(tud_speed_get() == TUSB_SPEED_FULL) { + return desc_uac1_configuration; + } else { + return desc_uac2_configuration; + } +#else + return desc_uac1_configuration; +#endif } //--------------------------------------------------------------------+ @@ -141,14 +212,14 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer - "TinyUSB headset", // 2: Product + "TinyUSB Headset", // 2: Product NULL, // 3: Serials will use unique ID if possible - "TinyUSB Speakers", // 4: Audio Interface - "TinyUSB Microphone", // 5: Audio Interface + "TinyUSB UAC1 Headset", // 4: Function + "TinyUSB UAC2 Headset", // 5: Function }; static uint16_t _desc_str[32 + 1]; diff --git a/examples/device/uac2_headset/src/usb_descriptors.h b/examples/device/uac2_headset/src/usb_descriptors.h index da0da83e8..47154626e 100644 --- a/examples/device/uac2_headset/src/usb_descriptors.h +++ b/examples/device/uac2_headset/src/usb_descriptors.h @@ -23,10 +23,20 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ -// #include "tusb.h" +enum +{ + ITF_NUM_AUDIO_CONTROL = 0, + ITF_NUM_AUDIO_STREAMING_SPK, + ITF_NUM_AUDIO_STREAMING_MIC, + ITF_NUM_TOTAL +}; + +//--------------------------------------------------------------------+ +// UAC2 DESCRIPTOR TEMPLATES +//--------------------------------------------------------------------+ // Unit numbers are arbitrary selected #define UAC2_ENTITY_CLOCK 0x04 @@ -38,121 +48,192 @@ #define UAC2_ENTITY_MIC_INPUT_TERMINAL 0x11 #define UAC2_ENTITY_MIC_OUTPUT_TERMINAL 0x13 -enum -{ - ITF_NUM_AUDIO_CONTROL = 0, - ITF_NUM_AUDIO_STREAMING_SPK, - ITF_NUM_AUDIO_STREAMING_MIC, - ITF_NUM_TOTAL -}; - -#define TUD_AUDIO_HEADSET_STEREO_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_STD_AC_INT_EP_LEN\ +#define TUD_AUDIO20_HEADSET_STEREO_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\ + + TUD_AUDIO20_DESC_STD_AC_LEN\ + + TUD_AUDIO20_DESC_CS_AC_LEN\ + + TUD_AUDIO20_DESC_CLK_SRC_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(2)\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_STD_AC_INT_EP_LEN\ /* Interface 1, Alternate 0 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ /* Interface 1, Alternate 1 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ /* Interface 1, Alternate 2 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ /* Interface 2, Alternate 0 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ /* Interface 2, Alternate 1 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ /* Interface 2, Alternate 2 */\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin, _epint) \ +#define TUD_AUDIO20_HEADSET_STEREO_DESCRIPTOR(_stridx, _epout, _epin, _epint) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitf*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_IAD(/*_firstitf*/ ITF_NUM_AUDIO_CONTROL, /*_nitfs*/ ITF_NUM_TOTAL, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ + TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ ITF_NUM_AUDIO_CONTROL, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_HEADSET, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(2)+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN, /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ + TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ UAC2_ENTITY_CLOCK, /*_attr*/ 3, /*_ctrl*/ 7, /*_assocTerm*/ 0x00, /*_stridx*/ 0x00), \ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrlch0master*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch2*/ (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_stridx*/ 0x00, /*_ctrlch0master*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch2*/ (AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS)),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_SPK_FEATURE_UNIT, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_srcid*/ UAC2_ENTITY_MIC_INPUT_TERMINAL, /*_clkid*/ UAC2_ENTITY_CLOCK, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */\ - TUD_AUDIO_DESC_STD_AC_INT_EP(/*_ep*/ _epint, /*_interval*/ 0x01), \ + TUD_AUDIO20_DESC_STD_AC_INT_EP(/*_ep*/ _epint, /*_interval*/ 0x01), \ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x05),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Interface 1, Alternate 2 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x05),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_SPK), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_SPK_INPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_RX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 2, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x04),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 2, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Interface 2, Alternate 2 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ 0x04),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)(ITF_NUM_AUDIO_STREAMING_MIC), /*_altset*/ 0x02, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ UAC2_ENTITY_MIC_OUTPUT_TERMINAL, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_RESOLUTION_TX),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ TUD_AUDIO_EP_SIZE(TUD_OPT_HIGH_SPEED, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX), /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + +//--------------------------------------------------------------------+ +// UAC1 DESCRIPTOR TEMPLATES +//--------------------------------------------------------------------+ + +// UAC1 entity IDs for speaker and microphone +// Speaker path +#define UAC1_ENTITY_SPK_INPUT_TERMINAL 0x01 +#define UAC1_ENTITY_SPK_FEATURE_UNIT 0x02 +#define UAC1_ENTITY_SPK_OUTPUT_TERMINAL 0x03 +// Microphone path +#define UAC1_ENTITY_MIC_INPUT_TERMINAL 0x11 +#define UAC1_ENTITY_MIC_OUTPUT_TERMINAL 0x13 + +#define TUD_AUDIO10_HEADSET_STEREO_DESC_LEN(_nfreqs) (\ + +TUD_AUDIO10_DESC_STD_AC_LEN\ + + TUD_AUDIO10_DESC_CS_AC_LEN(2)\ + + TUD_AUDIO10_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(2)\ + + TUD_AUDIO10_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO10_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO10_DESC_OUTPUT_TERM_LEN\ + /* Interface 1, Alternate 0 (speaker) */\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + /* Interface 1, Alternate 1 (speaker) */\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + + TUD_AUDIO10_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(_nfreqs)\ + + TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN\ + /* Interface 2, Alternate 0 (microphone) */\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + /* Interface 2, Alternate 1 (microphone) */\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + + TUD_AUDIO10_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(_nfreqs)\ + + TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN) + + +#define TUD_AUDIO10_HEADSET_STEREO_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample_RX, _nBitsUsedPerSample_RX, _nBytesPerSample_TX, _nBitsUsedPerSample_TX, _epout, _epoutsize, _epin, _epinsize, ...) \ + /* Standard AC Interface Descriptor(4.3.1) */\ + TUD_AUDIO10_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.3.2) */\ + TUD_AUDIO10_DESC_CS_AC(/*_bcdADC*/ 0x0100, /*_totallen*/ (TUD_AUDIO10_DESC_INPUT_TERM_LEN+TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(2)+TUD_AUDIO10_DESC_OUTPUT_TERM_LEN+TUD_AUDIO10_DESC_INPUT_TERM_LEN+TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(1)+TUD_AUDIO10_DESC_OUTPUT_TERM_LEN), /*_itf*/ ((_itfnum)+1), ((_itfnum)+2)),\ + /* Speaker Input Terminal Descriptor(4.3.2.1) */\ + TUD_AUDIO10_DESC_INPUT_TERM(/*_termid*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC1_ENTITY_MIC_OUTPUT_TERMINAL, /*_nchannels*/ 0x02, /*_channelcfg*/ AUDIO10_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_stridx*/ 0x00),\ + /* Speaker Feature Unit Descriptor(4.3.2.5) */\ + TUD_AUDIO10_DESC_FEATURE_UNIT(/*_unitid*/ UAC1_ENTITY_SPK_FEATURE_UNIT, /*_srcid*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_stridx*/ 0x00, /*_ctrlmaster*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME), /*_ctrlch1*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME), /*_ctrlch2*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME)),\ + /* Speaker Output Terminal Descriptor(4.3.2.2) */\ + TUD_AUDIO10_DESC_OUTPUT_TERM(/*_termid*/ UAC1_ENTITY_SPK_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_OUT_HEADPHONES, /*_assocTerm*/ 0x00, /*_srcid*/ UAC1_ENTITY_SPK_FEATURE_UNIT, /*_stridx*/ 0x00),\ + /* Microphone Input Terminal Descriptor(4.3.2.1) */\ + TUD_AUDIO10_DESC_INPUT_TERM(/*_termid*/ UAC1_ENTITY_MIC_INPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x00, /*_nchannels*/ 0x01, /*_channelcfg*/ AUDIO10_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_stridx*/ 0x00),\ + /* Microphone Output Terminal Descriptor(4.3.2.2) */\ + TUD_AUDIO10_DESC_OUTPUT_TERM(/*_termid*/ UAC1_ENTITY_MIC_OUTPUT_TERMINAL, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_srcid*/ UAC1_ENTITY_MIC_INPUT_TERMINAL, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.5.1) - Speaker Interface 1, Alternate 0 */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Standard AS Interface Descriptor(4.5.1) - Speaker Interface 1, Alternate 1 */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ + /* Class-Specific AS Interface Descriptor(4.5.2) */\ + TUD_AUDIO10_DESC_CS_AS_INT(/*_termid*/ UAC1_ENTITY_SPK_INPUT_TERMINAL, /*_delay*/ 0x01, /*_formattype*/ AUDIO10_DATA_FORMAT_TYPE_I_PCM),\ + /* Type I Format Type Descriptor(2.2.5) */\ + TUD_AUDIO10_DESC_TYPE_I_FORMAT(/*_nrchannels*/ 0x02, /*_subframesize*/ _nBytesPerSample_RX, /*_bitresolution*/ _nBitsUsedPerSample_RX, /*_freqs*/ __VA_ARGS__),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.6.1.1) */\ + TUD_AUDIO10_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ADAPTIVE), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01, /*_syncep*/ 0x00),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.6.1.2) */\ + TUD_AUDIO10_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO10_CS_AS_ISO_DATA_EP_ATT_SAMPLING_FRQ, /*_lockdelayunits*/ AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ + /* Standard AS Interface Descriptor(4.5.1) - Microphone Interface 2, Alternate 0 */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+2), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Standard AS Interface Descriptor(4.5.1) - Microphone Interface 2, Alternate 1 */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+2), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ _stridx),\ + /* Class-Specific AS Interface Descriptor(4.5.2) */\ + TUD_AUDIO10_DESC_CS_AS_INT(/*_termid*/ UAC1_ENTITY_MIC_OUTPUT_TERMINAL, /*_delay*/ 0x01, /*_formattype*/ AUDIO10_DATA_FORMAT_TYPE_I_PCM),\ + /* Type I Format Type Descriptor(2.2.5) */\ + TUD_AUDIO10_DESC_TYPE_I_FORMAT(/*_nrchannels*/ 0x01, /*_subframesize*/ _nBytesPerSample_TX, /*_bitresolution*/ _nBitsUsedPerSample_TX, /*_freqs*/ __VA_ARGS__),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.6.1.1) */\ + TUD_AUDIO10_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS), /*_maxEPsize*/ _epinsize, /*_interval*/ 0x01, /*_syncep*/ 0x00),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.6.1.2) */\ + TUD_AUDIO10_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO10_CS_AS_ISO_DATA_EP_ATT_SAMPLING_FRQ, /*_lockdelayunits*/ AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001) #endif diff --git a/examples/device/uac2_speaker_fb/CMakeLists.txt b/examples/device/uac2_speaker_fb/CMakeLists.txt index 0ed3db646..ced98a909 100644 --- a/examples/device/uac2_speaker_fb/CMakeLists.txt +++ b/examples/device/uac2_speaker_fb/CMakeLists.txt @@ -21,7 +21,6 @@ add_executable(${PROJECT}) target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/quirk_os_guessing.c ) # Example include diff --git a/examples/device/uac2_speaker_fb/Makefile b/examples/device/uac2_speaker_fb/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/uac2_speaker_fb/Makefile +++ b/examples/device/uac2_speaker_fb/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/uac2_speaker_fb/src/common_types.h b/examples/device/uac2_speaker_fb/src/common_types.h index 174e26671..b79ae2fd0 100644 --- a/examples/device/uac2_speaker_fb/src/common_types.h +++ b/examples/device/uac2_speaker_fb/src/common_types.h @@ -41,7 +41,7 @@ typedef struct { uint32_t sample_rate; uint8_t alt_settings; - int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; + uint8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; uint16_t fifo_size; uint16_t fifo_count; diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index ed9e7716d..7b4e2d64c 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c @@ -31,25 +31,10 @@ #include "tusb.h" #include "usb_descriptors.h" -#ifdef CFG_QUIRK_OS_GUESSING - #include "quirk_os_guessing.h" -#endif - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ -// List of supported sample rates -#if defined(__RX__) -const uint32_t sample_rates[] = {44100, 48000}; -#else -const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; -#endif - -uint32_t current_sample_rate = 44100; - -#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates) - /* Blink pattern * - 25 ms : streaming data * - 250 ms : device not mounted @@ -82,8 +67,9 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 +uint8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1];// +1 for master channel 0 +uint32_t current_sample_rate = 44100; // Buffer for speaker data uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 2]; @@ -153,18 +139,193 @@ void tud_resume_cb(void) { // Application Callback API Implementations //--------------------------------------------------------------------+ -// Helper for clock get requests -static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) { +//--------------------------------------------------------------------+ +// UAC1 Helper Functions +//--------------------------------------------------------------------+ + +static bool audio10_set_req_ep(tusb_control_request_t const *p_request, uint8_t *pBuff) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + + switch (ctrlSel) { + case AUDIO10_EP_CTRL_SAMPLING_FREQ: + if (p_request->bRequest == AUDIO10_CS_REQ_SET_CUR) { + // Request uses 3 bytes + TU_VERIFY(p_request->wLength == 3); + + current_sample_rate = tu_unaligned_read32(pBuff) & 0x00FFFFFF; + + TU_LOG2("EP set current freq: %" PRIu32 "\r\n", current_sample_rate); + + return true; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + + return false; +} + +static bool audio10_get_req_ep(uint8_t rhport, tusb_control_request_t const *p_request) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + + switch (ctrlSel) { + case AUDIO10_EP_CTRL_SAMPLING_FREQ: + if (p_request->bRequest == AUDIO10_CS_REQ_GET_CUR) { + TU_LOG2("EP get current freq\r\n"); + + uint8_t freq[3]; + freq[0] = (uint8_t) (current_sample_rate & 0xFF); + freq[1] = (uint8_t) ((current_sample_rate >> 8) & 0xFF); + freq[2] = (uint8_t) ((current_sample_rate >> 16) & 0xFF); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, freq, sizeof(freq)); + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + + return false; +} + +static bool audio10_set_req_entity(tusb_control_request_t const *p_request, uint8_t *pBuff) { + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // If request is for our feature unit + if (entityID == UAC1_ENTITY_FEATURE_UNIT) { + switch (ctrlSel) { + case AUDIO10_FU_CTRL_MUTE: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_SET_CUR: + // Only 1st form is supported + TU_VERIFY(p_request->wLength == 1); + + mute[channelNum] = pBuff[0]; + + TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; + + default: + return false; // not supported + } + + case AUDIO10_FU_CTRL_VOLUME: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_SET_CUR: + // Only 1st form is supported + TU_VERIFY(p_request->wLength == 2); + + volume[channelNum] = (int16_t)tu_unaligned_read16(pBuff) / 256; + + TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; + + default: + return false; // not supported + } + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + return false; +} + +static bool audio10_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) { + uint8_t channelNum = TU_U16_LOW(p_request->wValue); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + + // If request is for our feature unit + if (entityID == UAC1_ENTITY_FEATURE_UNIT) { + switch (ctrlSel) { + case AUDIO10_FU_CTRL_MUTE: + // Audio control mute cur parameter block consists of only one byte - we thus can send it right away + // There does not exist a range parameter block for mute + TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); + + case AUDIO10_FU_CTRL_VOLUME: + switch (p_request->bRequest) { + case AUDIO10_CS_REQ_GET_CUR: + TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + { + int16_t vol = (int16_t) volume[channelNum]; + vol = vol * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &vol, sizeof(vol)); + } + + case AUDIO10_CS_REQ_GET_MIN: + TU_LOG2(" Get Volume min of channel: %u\r\n", channelNum); + { + int16_t min = -90; // -90 dB + min = min * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &min, sizeof(min)); + } + + case AUDIO10_CS_REQ_GET_MAX: + TU_LOG2(" Get Volume max of channel: %u\r\n", channelNum); + { + int16_t max = 30; // +30 dB + max = max * 256; // convert to 1/256 dB units + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &max, sizeof(max)); + } + + case AUDIO10_CS_REQ_GET_RES: + TU_LOG2(" Get Volume res of channel: %u\r\n", channelNum); + { + int16_t res = 128; // 0.5 dB + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &res, sizeof(res)); + } + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + break; + + // Unknown/Unsupported control + default: + TU_BREAKPOINT(); + return false; + } + } + + return false; +} + +//--------------------------------------------------------------------+ +// UAC2 Helper Functions +//--------------------------------------------------------------------+ + +#if TUD_OPT_HIGH_SPEED +// List of supported sample rates for UAC2 +const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; + +#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates) + +static bool audio20_clock_get_request(uint8_t rhport, audio20_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { - if (request->bRequest == AUDIO_CS_REQ_CUR) { - TU_LOG1("Clock get current freq %lu\r\n", current_sample_rate); + if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) { + if (request->bRequest == AUDIO20_CS_REQ_CUR) { + TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); - audio_control_cur_4_t curf = {(int32_t) tu_htole32(current_sample_rate)}; + audio20_control_cur_4_t curf = {(int32_t) tu_htole32(current_sample_rate)}; return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &curf, sizeof(curf)); - } else if (request->bRequest == AUDIO_CS_REQ_RANGE) { - audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = + } else if (request->bRequest == AUDIO20_CS_REQ_RANGE) { + audio20_control_range_4_n_t(N_SAMPLE_RATES) rangef = { .wNumSubRanges = tu_htole16(N_SAMPLE_RATES)}; TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES); @@ -177,9 +338,9 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &rangef, sizeof(rangef)); } - } else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && - request->bRequest == AUDIO_CS_REQ_CUR) { - audio_control_cur_1_t cur_valid = {.bCur = 1}; + } else if (request->bControlSelector == AUDIO20_CS_CTRL_CLK_VALID && + request->bRequest == AUDIO20_CS_REQ_CUR) { + audio20_control_cur_1_t cur_valid = {.bCur = 1}; TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_valid, sizeof(cur_valid)); } @@ -188,19 +349,16 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t return false; } -// Helper for clock set requests -static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { - (void) rhport; - +static bool audio20_clock_set_request(audio20_control_request_t const *request, uint8_t const *buf) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); + if (request->bControlSelector == AUDIO20_CS_CTRL_SAM_FREQ) { + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_4_t)); - current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *) buf)->bCur; + current_sample_rate = (uint32_t) ((audio20_control_cur_4_t const *) buf)->bCur; - TU_LOG1("Clock set current freq: %ld\r\n", current_sample_rate); + TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); return true; } else { @@ -210,24 +368,23 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t } } -// Helper for feature unit get requests -static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) { +static bool audio20_feature_unit_get_request(uint8_t rhport, audio20_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_FEATURE_UNIT); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) { - audio_control_cur_1_t mute1 = {.bCur = mute[request->bChannelNumber]}; + if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE && request->bRequest == AUDIO20_CS_REQ_CUR) { + audio20_control_cur_1_t mute1 = {.bCur = mute[request->bChannelNumber]}; TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &mute1, sizeof(mute1)); - } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { - if (request->bRequest == AUDIO_CS_REQ_RANGE) { - audio_control_range_2_n_t(1) range_vol = { + } else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) { + if (request->bRequest == AUDIO20_CS_REQ_RANGE) { + audio20_control_range_2_n_t(1) range_vol = { .wNumSubRanges = tu_htole16(1), .subrange[0] = {.bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256)}}; TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &range_vol, sizeof(range_vol)); - } else if (request->bRequest == AUDIO_CS_REQ_CUR) { - audio_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[request->bChannelNumber])}; + } else if (request->bRequest == AUDIO20_CS_REQ_CUR) { + audio20_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[request->bChannelNumber])}; TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_vol, sizeof(cur_vol)); } @@ -238,25 +395,22 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req return false; } -// Helper for feature unit set requests -static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { - (void) rhport; - +static bool audio20_feature_unit_set_request(audio20_control_request_t const *request, uint8_t const *buf) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_FEATURE_UNIT); - TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); + TU_VERIFY(request->bRequest == AUDIO20_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t)); + if (request->bControlSelector == AUDIO20_FU_CTRL_MUTE) { + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_1_t)); - mute[request->bChannelNumber] = ((audio_control_cur_1_t const *) buf)->bCur; + mute[request->bChannelNumber] = ((audio20_control_cur_1_t const *) buf)->bCur; TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; - } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { - TU_VERIFY(request->wLength == sizeof(audio_control_cur_2_t)); + } else if (request->bControlSelector == AUDIO20_FU_CTRL_VOLUME) { + TU_VERIFY(request->wLength == sizeof(audio20_control_cur_2_t)); - volume[request->bChannelNumber] = ((audio_control_cur_2_t const *) buf)->bCur; + volume[request->bChannelNumber] = ((audio20_control_cur_2_t const *) buf)->bCur; TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); @@ -268,14 +422,13 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req } } -// Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - audio_control_request_t const *request = (audio_control_request_t const *) p_request; +static bool audio20_get_req_entity(uint8_t rhport, tusb_control_request_t const *p_request) { + audio20_control_request_t const *request = (audio20_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_CLOCK) - return tud_audio_clock_get_request(rhport, request); + return audio20_clock_get_request(rhport, request); if (request->bEntityID == UAC2_ENTITY_FEATURE_UNIT) - return tud_audio_feature_unit_get_request(rhport, request); + return audio20_feature_unit_get_request(rhport, request); else { TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); @@ -283,31 +436,24 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false; } -// Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { - audio_control_request_t const *request = (audio_control_request_t const *) p_request; +static bool audio20_set_req_entity(tusb_control_request_t const *p_request, uint8_t *buf) { + audio20_control_request_t const *request = (audio20_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_FEATURE_UNIT) - return tud_audio_feature_unit_set_request(rhport, request, buf); + return audio20_feature_unit_set_request(request, buf); if (request->bEntityID == UAC2_ENTITY_CLOCK) - return tud_audio_clock_set_request(rhport, request, buf); + return audio20_clock_set_request(request, buf); TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); return false; } -bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { - (void) rhport; - - uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); - uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); - - if (ITF_NUM_AUDIO_STREAMING == itf && alt == 0) - blink_interval_ms = BLINK_MOUNTED; +#endif // TUD_OPT_HIGH_SPEED - return true; -} +//--------------------------------------------------------------------+ +// Main Callback Functions +//--------------------------------------------------------------------+ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; @@ -325,12 +471,92 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_reques return true; } +// Invoked when audio class specific set request received for an EP +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { + (void) rhport; + (void) pBuff; + + if (tud_audio_version() == 1) { + return audio10_set_req_ep(p_request, pBuff); + } else if (tud_audio_version() == 2) { + // We do not support any requests here + } + + return false;// Yet not implemented +} + +// Invoked when audio class specific get request received for an EP +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_get_req_ep(rhport, p_request); + } else if (tud_audio_version() == 2) { + // We do not support any requests here + } + + return false;// Yet not implemented +} + +// Invoked when audio class specific set request received for an entity +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_set_req_entity(p_request, buf); +#if TUD_OPT_HIGH_SPEED + } else if (tud_audio_version() == 2) { + return audio20_set_req_entity(p_request, buf); +#endif + } + + return false; +} + +// Invoked when audio class specific get request received for an entity +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + + if (tud_audio_version() == 1) { + return audio10_get_req_entity(rhport, p_request); +#if TUD_OPT_HIGH_SPEED + } else if (tud_audio_version() == 2) { + return audio20_get_req_entity(rhport, p_request); +#endif + } + + return false; +} + +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; + + uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); + uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); + + if (ITF_NUM_AUDIO_STREAMING == itf && alt == 0) + blink_interval_ms = BLINK_MOUNTED; + + return true; +} + void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t *feedback_param) { (void) func_id; (void) alt_itf; // Set feedback method to fifo counting feedback_param->method = AUDIO_FEEDBACK_METHOD_FIFO_COUNT; feedback_param->sample_freq = current_sample_rate; + + // About FIFO threshold: + // + // By default the threshold is set to half FIFO size, which works well in most cases, + // you can reduce the threshold to have less latency. + // + // For example, here we could set the threshold to 2 ms of audio data, as audio_task() read audio data every 1 ms, + // having 2 ms threshold allows some margin and a quick response: + // + // feedback_param->fifo_count.fifo_threshold = + // current_sample_rate * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX / 1000 * 2; } #if CFG_AUDIO_DEBUG @@ -349,16 +575,6 @@ bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t fu } #endif -#if CFG_QUIRK_OS_GUESSING -bool tud_audio_feedback_format_correction_cb(uint8_t func_id) { - (void) func_id; - if (tud_speed_get() == TUSB_SPEED_FULL && quirk_os_guessing_get() == QUIRK_OS_GUESSING_OSX) { - return true; - } else { - return false; - } -} -#endif //--------------------------------------------------------------------+ // AUDIO Task //--------------------------------------------------------------------+ diff --git a/examples/device/uac2_speaker_fb/src/quirk_os_guessing.c b/examples/device/uac2_speaker_fb/src/quirk_os_guessing.c deleted file mode 100644 index 92b9ab6ee..000000000 --- a/examples/device/uac2_speaker_fb/src/quirk_os_guessing.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 HiFiPhile - * - * 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. - * - */ - -#include "quirk_os_guessing.h" - -static tusb_desc_type_t desc_req_buf[2]; -static int desc_req_idx = 0; - -// Place at the start of tud_descriptor_device_cb() -void quirk_os_guessing_desc_device_cb(void) { - desc_req_idx = 0; -} - -// Place at the start of tud_descriptor_configuration_cb() -void quirk_os_guessing_desc_configuration_cb(void) { - // Skip redundant request - if (desc_req_idx == 0 || (desc_req_idx == 1 && desc_req_buf[0] != TUSB_DESC_CONFIGURATION)) { - desc_req_buf[desc_req_idx++] = TUSB_DESC_CONFIGURATION; - } -} - -// Place at the start of tud_descriptor_bos_cb() -void quirk_os_guessing_desc_bos_cb(void) { - // Skip redundant request - if (desc_req_idx == 0 || (desc_req_idx == 1 && desc_req_buf[0] != TUSB_DESC_BOS)) { - desc_req_buf[desc_req_idx++] = TUSB_DESC_BOS; - } -} - -// Place at the start of tud_descriptor_string_cb() -void quirk_os_guessing_desc_string_cb(void) { - // Skip redundant request - if (desc_req_idx == 0 || (desc_req_idx == 1 && desc_req_buf[0] != TUSB_DESC_STRING)) { - desc_req_buf[desc_req_idx++] = TUSB_DESC_STRING; - } -} - -// Each OS request descriptors differently: -// Windows 10 - 11 -// Device Desc -// Config Desc -// BOS Desc -// String Desc -// Linux 3.16 - 6.8 -// Device Desc -// BOS Desc -// Config Desc -// String Desc -// OS X Ventura - Sonoma -// Device Desc -// String Desc -// Config Desc || BOS Desc -// BOS Desc || Config Desc -quirk_os_guessing_t quirk_os_guessing_get(void) { - if (desc_req_idx < 2) { - return QUIRK_OS_GUESSING_UNKNOWN; - } - - if (desc_req_buf[0] == TUSB_DESC_BOS && desc_req_buf[1] == TUSB_DESC_CONFIGURATION) { - return QUIRK_OS_GUESSING_LINUX; - } else if (desc_req_buf[0] == TUSB_DESC_CONFIGURATION && desc_req_buf[1] == TUSB_DESC_BOS) { - return QUIRK_OS_GUESSING_WINDOWS; - } else if (desc_req_buf[0] == TUSB_DESC_STRING && (desc_req_buf[1] == TUSB_DESC_BOS || desc_req_buf[1] == TUSB_DESC_CONFIGURATION)) { - return QUIRK_OS_GUESSING_OSX; - } - - return QUIRK_OS_GUESSING_UNKNOWN; -} diff --git a/examples/device/uac2_speaker_fb/src/quirk_os_guessing.h b/examples/device/uac2_speaker_fb/src/quirk_os_guessing.h deleted file mode 100644 index 1120355c9..000000000 --- a/examples/device/uac2_speaker_fb/src/quirk_os_guessing.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 HiFiPhile - * - * 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. - * - */ - -#ifndef _QUIRK_OS_GUESSING_H_ -#define _QUIRK_OS_GUESSING_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include "tusb.h" - -//================================== !!! WARNING !!! ==================================== -// This quirk operate out of USB specification in order to workaround specific issues. -// It may not work on your platform. -//======================================================================================= -// -// Prerequisites: -// - Set USB version to at least 2.01 in Device Descriptor -// - Has a valid BOS Descriptor, refer to webusb_serial example -// -// Attention: -// Windows detection result comes out after Configuration Descriptor request, -// meaning it will be too late to do descriptor adjustment. It's advised to make -// Windows as default configuration and adjust to other OS accordingly. - -typedef enum { - QUIRK_OS_GUESSING_UNKNOWN, - QUIRK_OS_GUESSING_LINUX, - QUIRK_OS_GUESSING_OSX, - QUIRK_OS_GUESSING_WINDOWS, -} quirk_os_guessing_t; - -// Get Host OS type -quirk_os_guessing_t quirk_os_guessing_get(void); - -// Place at the start of tud_descriptor_device_cb() -void quirk_os_guessing_desc_device_cb(void); - -// Place at the start of tud_descriptor_configuration_cb() -void quirk_os_guessing_desc_configuration_cb(void); - -// Place at the start of tud_descriptor_bos_cb() -void quirk_os_guessing_desc_bos_cb(void); - -// Place at the start of tud_descriptor_string_cb() -void quirk_os_guessing_desc_string_cb(void); - -#ifdef __cplusplus - } -#endif - -#endif /* _QUIRK_OS_GUESSING_H_ */ diff --git a/examples/device/uac2_speaker_fb/src/tusb_config.h b/examples/device/uac2_speaker_fb/src/tusb_config.h index 18ab2ff96..46f5703c8 100644 --- a/examples/device/uac2_speaker_fb/src/tusb_config.h +++ b/examples/device/uac2_speaker_fb/src/tusb_config.h @@ -24,8 +24,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -87,14 +87,6 @@ extern "C" { #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) #endif -/* (Needed for Full-Speed only) - * Enable host OS guessing to workaround UAC2 compatibility issues between Windows and OS X - * The default configuration only support Windows and Linux, enable this option for OS X - * support. Otherwise if you don't need Windows support you can make OS X's configuration as - * default. - */ -#define CFG_QUIRK_OS_GUESSING 1 - //-------------------------------------------------------------------- // DEVICE CONFIGURATION //-------------------------------------------------------------------- @@ -128,38 +120,33 @@ extern "C" { // AUDIO CLASS DRIVER CONFIGURATION //-------------------------------------------------------------------- -#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_SPEAKER_STEREO_FB_DESC_LEN - -// Can be enabled with Full-Speed device on OSX, which forces feedback EP size to 3, in this case CFG_QUIRK_OS_GUESSING can be disabled -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 +#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 -// Audio format type I specifications -#if defined(__RX__) -#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 -#else -#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 96000 -#endif +// 16bit data in 16bit slots +#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX 2 +#define CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX 16 -#define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX 2 +// UAC1 Full-Speed endpoint size +#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE_FS 48000 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_FS TUD_AUDIO_EP_SIZE(false, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE_FS, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) +// UAC2 High-Speed endpoint size +#define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE_HS 96000 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_HS TUD_AUDIO_EP_SIZE(true, CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE_HS, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -// 16bit in 16bit slots -#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX 2 -#define CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX 16 +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_FS, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_HS) -// EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) -#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 +// AUDIO_FEEDBACK_METHOD_FIFO_COUNT needs buffer size >= 4* EP size to work correctly +// Example read FIFO every 1ms (8 HS frames), so buffer size should be 8 times larger for HS device +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(4 * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_FS, 32 * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_HS) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device +// Enable OUT EP +#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 // Enable feedback EP -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 1 - -// Size of control request buffer -#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 1 #ifdef __cplusplus } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/uac2_speaker_fb/src/usb_descriptors.c b/examples/device/uac2_speaker_fb/src/usb_descriptors.c index ee1b92225..c5a161a1e 100644 --- a/examples/device/uac2_speaker_fb/src/usb_descriptors.c +++ b/examples/device/uac2_speaker_fb/src/usb_descriptors.c @@ -28,28 +28,24 @@ #include "usb_descriptors.h" #include "common_types.h" -#ifdef CFG_QUIRK_OS_GUESSING -#include "quirk_os_guessing.h" -#endif - /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. * * Auto ProductID layout's Bitmap: * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VENDOR, 5) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0201, + .bcdUSB = 0x0200, // Use Interface Association Descriptor (IAD) for Audio // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) @@ -71,12 +67,8 @@ tusb_desc_device_t const desc_device = // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ -#if CFG_QUIRK_OS_GUESSING - quirk_os_guessing_desc_device_cb(); -#endif - return (uint8_t const *)&desc_device; +uint8_t const * tud_descriptor_device_cb(void) { + return (uint8_t const *) &desc_device; } #if CFG_AUDIO_DEBUG @@ -84,8 +76,7 @@ uint8_t const * tud_descriptor_device_cb(void) // HID Report Descriptor //--------------------------------------------------------------------+ -uint8_t const desc_hid_report[] = -{ +uint8_t const desc_hid_report[] = { HID_USAGE_PAGE_N ( HID_USAGE_PAGE_VENDOR, 2 ),\ HID_USAGE ( 0x01 ),\ HID_COLLECTION ( HID_COLLECTION_APPLICATION ),\ @@ -101,8 +92,7 @@ uint8_t const desc_hid_report[] = // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) -{ +uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) { (void) itf; return desc_hid_report; } @@ -112,109 +102,126 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) // Configuration Descriptor //--------------------------------------------------------------------+ -#if CFG_AUDIO_DEBUG - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO_SPEAKER_STEREO_FB_DESC_LEN + TUD_HID_DESC_LEN) -#else - #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO_SPEAKER_STEREO_FB_DESC_LEN) -#endif - #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... + #define EPNUM_AUDIO 0x03 #define EPNUM_AUDIO_FB 0x03 - #define EPNUM_AUDIO_OUT 0x03 #define EPNUM_DEBUG 0x04 -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - // ISO endpoints for NRF5x are fixed to 0x08 (0x88) +#elif TU_CHECK_MCU(OPT_MCU_NRF5X) + // nRF5x ISO can only be endpoint 8 + #define EPNUM_AUDIO 0x08 #define EPNUM_AUDIO_FB 0x08 - #define EPNUM_AUDIO_OUT 0x08 #define EPNUM_DEBUG 0x01 #elif defined(TUD_ENDPOINT_ONE_DIRECTION_ONLY) // MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h // e.g EP1 OUT & EP1 IN cannot exist together + #define EPNUM_AUDIO 0x02 #define EPNUM_AUDIO_FB 0x01 - #define EPNUM_AUDIO_OUT 0x02 #define EPNUM_DEBUG 0x03 #else + #define EPNUM_AUDIO 0x01 #define EPNUM_AUDIO_FB 0x01 - #define EPNUM_AUDIO_OUT 0x01 #define EPNUM_DEBUG 0x02 #endif -uint8_t const desc_configuration_default[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), +#if CFG_AUDIO_DEBUG + #define CONFIG_UAC1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO10_SPEAKER_STEREO_FB_DESC_LEN(2) + TUD_HID_DESC_LEN) +#else + #define CONFIG_UAC1_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO10_SPEAKER_STEREO_FB_DESC_LEN(2)) +#endif + +uint8_t const desc_uac1_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC1_TOTAL_LEN, 0x00, 100), - // Interface number, string index, byte per sample, bit per sample, EP Out, EP size, EP feedback, feedback EP size, - TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR(0, 4, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX, EPNUM_AUDIO_OUT, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX, EPNUM_AUDIO_FB | 0x80, 4), + // Interface number, string index, byte per sample, bit per sample, EP Out, EP size, EP feedback, sample rates (44.1kHz, 48kHz) + TUD_AUDIO10_SPEAKER_STEREO_FB_DESCRIPTOR(ITF_NUM_AUDIO_CONTROL, 5, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX, EPNUM_AUDIO, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_FS, EPNUM_AUDIO_FB | 0x80, 44100, 48000), #if CFG_AUDIO_DEBUG - // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_DEBUG, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_DEBUG | 0x80, CFG_TUD_HID_EP_BUFSIZE, 7) + // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval + TUD_HID_DESCRIPTOR(ITF_NUM_DEBUG, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_DEBUG | 0x80, CFG_TUD_HID_EP_BUFSIZE, 7) #endif }; -#if CFG_QUIRK_OS_GUESSING -// OS X needs 3 bytes feedback endpoint on FS -uint8_t const desc_configuration_osx_fs[] = -{ - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), +TU_VERIFY_STATIC(sizeof(desc_uac1_configuration) == CONFIG_UAC1_TOTAL_LEN, "Incorrect size"); - // Interface number, string index, byte per sample, bit per sample, EP Out, EP size, EP feedback, feedback EP size, - TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR(0, 4, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX, EPNUM_AUDIO_OUT, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX, EPNUM_AUDIO_FB | 0x80, 3), +#if TUD_OPT_HIGH_SPEED #if CFG_AUDIO_DEBUG - // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_DEBUG, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_DEBUG | 0x80, CFG_TUD_HID_EP_BUFSIZE, 7) -#endif -}; + #define CONFIG_UAC2_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO20_SPEAKER_STEREO_FB_DESC_LEN + TUD_HID_DESC_LEN) +#else + #define CONFIG_UAC2_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_AUDIO20_SPEAKER_STEREO_FB_DESC_LEN) #endif -// Invoked when received GET CONFIGURATION DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - (void)index; // for multiple configurations +uint8_t const desc_uac2_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_UAC2_TOTAL_LEN, 0x00, 100), -#if CFG_QUIRK_OS_GUESSING - quirk_os_guessing_desc_configuration_cb(); - if(tud_speed_get() == TUSB_SPEED_FULL && quirk_os_guessing_get() == QUIRK_OS_GUESSING_OSX) { - return desc_configuration_osx_fs; - } -#endif - return desc_configuration_default; -} + // Interface number, string index, byte per sample, bit per sample, EP Out, EP size, EP feedback, feedback EP size, + TUD_AUDIO20_SPEAKER_STEREO_FB_DESCRIPTOR(ITF_NUM_AUDIO_CONTROL, 4, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX, EPNUM_AUDIO, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_HS, EPNUM_AUDIO_FB | 0x80, 4), -//--------------------------------------------------------------------+ -// BOS Descriptor, required for OS guessing quirk -//--------------------------------------------------------------------+ +#if CFG_AUDIO_DEBUG + // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval + TUD_HID_DESCRIPTOR(ITF_NUM_DEBUG, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_DEBUG | 0x80, CFG_TUD_HID_EP_BUFSIZE, 7) +#endif +}; -#define TUD_BOS_USB20_EXT_DESC_LEN 7 +TU_VERIFY_STATIC(sizeof(desc_uac2_configuration) == CONFIG_UAC2_TOTAL_LEN, "Incorrect size"); -#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_USB20_EXT_DESC_LEN) +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = 0x0200, -// BOS Descriptor is required for webUSB -uint8_t const desc_bos[] = -{ - // total length, number of device caps - TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 1), + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, - // USB 2.0 Extension Descriptor - 0x07, TUSB_DESC_DEVICE_CAPABILITY, DEVICE_CAPABILITY_USB20_EXTENSION, 0x00, 0x00, 0x00,0x00 + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 }; -uint8_t const * tud_descriptor_bos_cb(void) -{ -#if CFG_QUIRK_OS_GUESSING - quirk_os_guessing_desc_bos_cb(); +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const *tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const *) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index;// for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_uac1_configuration : desc_uac2_configuration; +} + +#endif // highspeed + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + if(tud_speed_get() == TUSB_SPEED_FULL) { + return desc_uac1_configuration; + } else { + return desc_uac2_configuration; + } +#else + return desc_uac1_configuration; #endif - return desc_bos; } //--------------------------------------------------------------------+ @@ -230,13 +237,14 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Speaker", // 2: Product NULL, // 3: Serials will use unique ID if possible "UAC2 Speaker", // 4: Audio Interface + "UAC1 Speaker", // 5: UAC1 Audio Interface }; static uint16_t _desc_str[32 + 1]; @@ -247,10 +255,6 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; size_t chr_count; -#if CFG_QUIRK_OS_GUESSING - quirk_os_guessing_desc_string_cb(); -#endif - switch ( index ) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); diff --git a/examples/device/uac2_speaker_fb/src/usb_descriptors.h b/examples/device/uac2_speaker_fb/src/usb_descriptors.h index 9511bf797..79f25bbfa 100644 --- a/examples/device/uac2_speaker_fb/src/usb_descriptors.h +++ b/examples/device/uac2_speaker_fb/src/usb_descriptors.h @@ -23,60 +23,148 @@ * */ -#ifndef _USB_DESCRIPTORS_H_ -#define _USB_DESCRIPTORS_H_ +#ifndef USB_DESCRIPTORS_H_ +#define USB_DESCRIPTORS_H_ -// Defined in TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR +//--------------------------------------------------------------------+ +// UAC2 DESCRIPTOR TEMPLATES +//--------------------------------------------------------------------+ + +// Defined in TUD_AUDIO20_SPEAKER_STEREO_FB_DESCRIPTOR #define UAC2_ENTITY_CLOCK 0x04 #define UAC2_ENTITY_INPUT_TERMINAL 0x01 #define UAC2_ENTITY_FEATURE_UNIT 0x02 #define UAC2_ENTITY_OUTPUT_TERMINAL 0x03 -#define TUD_AUDIO_SPEAKER_STEREO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) +#define TUD_AUDIO20_SPEAKER_STEREO_FB_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\ + + TUD_AUDIO20_DESC_STD_AC_LEN\ + + TUD_AUDIO20_DESC_CS_AC_LEN\ + + TUD_AUDIO20_DESC_CLK_SRC_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(2)\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP_LEN) -#define TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, _epfbsize) \ +#define TUD_AUDIO20_SPEAKER_STEREO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, _epfbsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(2), /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK, /*_ctrl*/ (AUDIO_CTRL_RW << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO20_CLOCK_SOURCE_ATT_INT_PRO_CLK, /*_ctrl*/ (AUDIO20_CTRL_RW << AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x02, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS,/*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_stridx*/ 0x00, /*_ctrlch0master*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x02, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x02, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_epsize*/ _epfbsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 4 : 1)\ + TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_epsize*/ _epfbsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 4 : 1) + +//--------------------------------------------------------------------+ +// UAC1 DESCRIPTOR TEMPLATES +//--------------------------------------------------------------------+ + +// Defined in TUD_AUDIO10_SPEAKER_STEREO_FB_DESCRIPTOR +#define UAC1_ENTITY_INPUT_TERMINAL 0x01 +#define UAC1_ENTITY_FEATURE_UNIT 0x02 +#define UAC1_ENTITY_OUTPUT_TERMINAL 0x03 + +#define TUD_AUDIO10_SPEAKER_STEREO_FB_DESC_LEN(_nfreqs) (\ + + TUD_AUDIO10_DESC_STD_AC_LEN\ + + TUD_AUDIO10_DESC_CS_AC_LEN(1)\ + + TUD_AUDIO10_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO10_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(2)\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + + TUD_AUDIO10_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(_nfreqs)\ + + TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO10_DESC_STD_AS_ISO_SYNC_EP_LEN) + +#define TUD_AUDIO10_SPEAKER_STEREO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, ...) \ + /* Standard AC Interface Descriptor(4.3.1) */\ + TUD_AUDIO10_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.3.2) */\ + TUD_AUDIO10_DESC_CS_AC(/*_bcdADC*/ 0x0100, /*_totallen*/ (TUD_AUDIO10_DESC_INPUT_TERM_LEN+TUD_AUDIO10_DESC_OUTPUT_TERM_LEN+TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(2)), /*_itf*/ ((_itfnum)+1)),\ + /* Input Terminal Descriptor(4.3.2.1) */\ + TUD_AUDIO10_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_nchannels*/ 0x02, /*_channelcfg*/ AUDIO10_CHANNEL_CONFIG_LEFT_FRONT | AUDIO10_CHANNEL_CONFIG_RIGHT_FRONT, /*_idxchannelnames*/ 0x00, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.3.2.2) */\ + TUD_AUDIO10_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x00, /*_srcid*/ 0x02, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.3.2.5) */\ + TUD_AUDIO10_DESC_FEATURE_UNIT(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_stridx*/ 0x00, /*_ctrlmaster*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME), /*_ctrlch1*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME), /*_ctrlch2*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME)),\ + /* Standard AS Interface Descriptor(4.5.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.5.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.5.2) */\ + TUD_AUDIO10_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_delay*/ 0x00, /*_formattype*/ AUDIO10_DATA_FORMAT_TYPE_I_PCM),\ + /* Type I Format Type Descriptor(2.2.5) */\ + TUD_AUDIO10_DESC_TYPE_I_FORMAT(/*_nrchannels*/ 0x02, /*_subframesize*/ _nBytesPerSample, /*_bitresolution*/ _nBitsUsedPerSample, /*_freqs*/ __VA_ARGS__),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.6.1.1) */\ + TUD_AUDIO10_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01, /*_sync_ep*/ _epfb),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.6.1.2) */\ + TUD_AUDIO10_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO10_CS_AS_ISO_DATA_EP_ATT_SAMPLING_FRQ, /*_lockdelayunits*/ AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + /* Standard AS Isochronous Synch Endpoint Descriptor (4.6.2.1) */\ + TUD_AUDIO10_DESC_STD_AS_ISO_SYNC_EP(/*_ep*/ _epfb, /*_bRefresh*/ 0) + +//---------------------------------------------------------------------------+ +// UAC1 Isochronous Synch Endpoint bRefresh Workaround +// +// bRefresh value is set to 0, while UAC1 spec requires it to be between +// 1 (2 ms) and 9 (512 ms) +// +// This value has been tested to work with Windows, macOS and Linux. +// +// Rationale: +// Some USB device controllers (e.g. Synopsys DWC2) require a known transfer +// interval to manually schedule isochronous IN transfers. For data isochronous +// endpoints, the bInterval field in the endpoint descriptor is used. However, +// for synch endpoint it's unclear which field the host uses to determine the +// transfer interval. Windows and macOS use bRefresh, while Linux uses bInterval. +// +// Since bInterval is fixed to 1, if bRefresh is set to 2 then Windows and macOS +// will schedule the feedback transfer every 4 ms, but Linux will schedule it +// every 1 ms. DWC2 controller cannot handle this discrepancy without knwowing +// the actual interval, therefore we set bRefresh to 0 to let the transfer +// execute every 1 ms, which is the same as bInterval. +// +// Rant: +// WTF USB-IF? Why have two fields that mean the same thing? Why not just use +// bInterval for both data and synch endpoints? Why is bRefresh even necessary? +// +// Note: +// For the moment DWC2 driver doesn't have proper support for bInterval > 1 +// for isochronous IN endpoints. The implementation would be complex and CPU +// intensive (cfr. +// https://github.com/torvalds/linux/blob/master/drivers/usb/dwc2/gadget.c) +// It MAY work in some cases if you are lucky, but it's not guaranteed. +//---------------------------------------------------------------------------+ #endif diff --git a/examples/device/usbtmc/Makefile b/examples/device/usbtmc/Makefile index 1b4d398cf..1a4b428dc 100644 --- a/examples/device/usbtmc/Makefile +++ b/examples/device/usbtmc/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c index f78cce91f..5cbbb85ef 100644 --- a/examples/device/usbtmc/src/main.c +++ b/examples/device/usbtmc/src/main.c @@ -29,6 +29,7 @@ #include "bsp/board_api.h" #include "tusb.h" +#include "main.h" #include "usbtmc_app.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES diff --git a/examples/device/usbtmc/src/usb_descriptors.c b/examples/device/usbtmc/src/usb_descriptors.c index 85acd990a..16bd176f8 100644 --- a/examples/device/usbtmc/src/usb_descriptors.c +++ b/examples/device/usbtmc/src/usb_descriptors.c @@ -34,9 +34,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xcafe #define USB_BCD 0x0200 @@ -44,7 +44,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -112,7 +112,7 @@ enum #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_USBTMC_DESC_LEN) -uint8_t const desc_fs_configuration[] = +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -122,7 +122,7 @@ uint8_t const desc_fs_configuration[] = #if TUD_OPT_HIGH_SPEED -uint8_t const desc_hs_configuration[] = +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -131,10 +131,10 @@ uint8_t const desc_hs_configuration[] = }; // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, @@ -158,6 +158,23 @@ uint8_t const* tud_descriptor_device_qualifier_cb(void) return (uint8_t const*) &desc_device_qualifier; } +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG + memcpy(desc_other_speed_config, + (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, + CONFIG_TOTAL_LEN); + + desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; + + return desc_other_speed_config; +} + #endif // Invoked when received GET CONFIGURATION DESCRIPTOR @@ -187,7 +204,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index e738f1008..4c3724ac4 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -28,6 +28,7 @@ #include "tusb.h" #include "bsp/board_api.h" #include "main.h" +#include "usbtmc_app.h" #if (CFG_TUD_USBTMC_ENABLE_488) static usbtmc_response_capabilities_488_t const diff --git a/examples/device/video_capture/Makefile b/examples/device/video_capture/Makefile index d698a848d..6c248ab7b 100644 --- a/examples/device/video_capture/Makefile +++ b/examples/device/video_capture/Makefile @@ -1,4 +1,4 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk ifeq ($(DISABLE_MJPEG),1) CFLAGS += -DCFG_EXAMPLE_VIDEO_DISABLE_MJPEG @@ -9,10 +9,10 @@ endif INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt index 50302c544..cb0c7d2e6 100644 --- a/examples/device/video_capture/skip.txt +++ b/examples/device/video_capture/skip.txt @@ -1,6 +1,5 @@ mcu:CH32V103 mcu:CH32V20X -mcu:MCXA15 mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index 29656e944..ffa2a7afa 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -53,9 +53,23 @@ void usb_device_task(void *param); void video_task(void* param); #if CFG_TUSB_OS == OPT_OS_FREERTOS -void freertos_init_task(void); +void freertos_init(void); #endif +#if !defined(CFG_EXAMPLE_VIDEO_READONLY) || defined(CFG_EXAMPLE_VIDEO_BUFFERLESS) +/* EBU color bars: https://stackoverflow.com/questions/6939422 */ +static uint8_t const bar_color[8][4] = { + /* Y, U, Y, V */ + { 235, 128, 235, 128}, /* 100% White */ + { 219, 16, 219, 138}, /* Yellow */ + { 188, 154, 188, 16}, /* Cyan */ + { 173, 42, 173, 26}, /* Green */ + { 78, 214, 78, 230}, /* Magenta */ + { 63, 102, 63, 240}, /* Red */ + { 32, 240, 32, 118}, /* Blue */ + { 16, 128, 16, 128}, /* Black */ +}; +#endif //--------------------------------------------------------------------+ // Main @@ -65,7 +79,7 @@ int main(void) { // If using FreeRTOS: create blinky, tinyusb device, video task #if CFG_TUSB_OS == OPT_OS_FREERTOS - freertos_init_task(); + freertos_init(); #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { @@ -111,12 +125,43 @@ void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } +#ifdef CFG_EXAMPLE_VIDEO_BUFFERLESS + +#ifndef CFG_EXAMPLE_VIDEO_DISABLE_MJPEG + #error Demo only supports YUV2 please define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG +#endif + +void tud_video_prepare_payload_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, tud_video_payload_request_t* request) +{ + static uint32_t frame_counter = 0; + (void)ctl_idx; + (void)stm_idx; + + /* Offset will be zero at the start of a new frame */ + if (!request->offset) frame_counter++; + + for (size_t buf_pos = 0; buf_pos < request->length; buf_pos += 2) { + + /* Position within the current line (pixel relative) */ + int line_pos = ((request->offset + buf_pos)>>1) % FRAME_WIDTH; + + /* Choose color based on the position and change the table offset every 4 frames */ + const uint8_t* color = bar_color[(line_pos/(FRAME_WIDTH / 8) + (frame_counter>>2)) % 8]; + + /* Copy pixel data for odd or even pixels */ + memcpy(&((uint8_t*)request->buf)[buf_pos], &color[(line_pos & 1) ? 2 : 0], 2); + } + +} +#endif + //--------------------------------------------------------------------+ // USB Video //--------------------------------------------------------------------+ static unsigned frame_num = 0; static unsigned tx_busy = 0; static unsigned interval_ms = 1000 / FRAME_RATE; +#ifndef CFG_EXAMPLE_VIDEO_BUFFERLESS #ifdef CFG_EXAMPLE_VIDEO_READONLY // For mcus that does not have enough SRAM for frame buffer, we use fixed frame data. @@ -145,18 +190,6 @@ static struct { static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8]; static void fill_color_bar(uint8_t* buffer, unsigned start_position) { - /* EBU color bars: https://stackoverflow.com/questions/6939422 */ - static uint8_t const bar_color[8][4] = { - /* Y, U, Y, V */ - { 235, 128, 235, 128}, /* 100% White */ - { 219, 16, 219, 138}, /* Yellow */ - { 188, 154, 188, 16}, /* Cyan */ - { 173, 42, 173, 26}, /* Green */ - { 78, 214, 78, 230}, /* Magenta */ - { 63, 102, 63, 240}, /* Red */ - { 32, 240, 32, 118}, /* Blue */ - { 16, 128, 16, 128}, /* Black */ - }; uint8_t* p; /* Generate the 1st line */ @@ -183,6 +216,8 @@ static void fill_color_bar(uint8_t* buffer, unsigned start_position) { #endif +#endif /* NDEF CFG_EXAMPLE_VIDEO_BUFFERLESS */ + static void video_send_frame(void) { static unsigned start_ms = 0; static unsigned already_sent = 0; @@ -197,7 +232,9 @@ static void video_send_frame(void) { already_sent = 1; tx_busy = 1; start_ms = board_millis(); -#ifdef CFG_EXAMPLE_VIDEO_READONLY +#if defined(CFG_EXAMPLE_VIDEO_BUFFERLESS) + tud_video_n_frame_xfer(0, 0, NULL, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); +#elif defined (CFG_EXAMPLE_VIDEO_READONLY) #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); @@ -211,12 +248,18 @@ static void video_send_frame(void) { } unsigned cur = board_millis(); - if (cur - start_ms < interval_ms) return; // not enough time - if (tx_busy) return; + if (cur - start_ms < interval_ms) { + return; // not enough time + } + if (tx_busy) { + return; + } start_ms += interval_ms; tx_busy = 1; -#ifdef CFG_EXAMPLE_VIDEO_READONLY +#if defined(CFG_EXAMPLE_VIDEO_BUFFERLESS) + tud_video_n_frame_xfer(0, 0, NULL, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); +#elif defined(CFG_EXAMPLE_VIDEO_READONLY) #if defined(CFG_EXAMPLE_VIDEO_DISABLE_MJPEG) tud_video_n_frame_xfer(0, 0, (void*)(uintptr_t)&frame_buffer[(frame_num % (FRAME_WIDTH / 2)) * 4], FRAME_WIDTH * FRAME_HEIGHT * 16/8); @@ -273,7 +316,9 @@ void led_blinking_task(void* param) { #if CFG_TUSB_OS == OPT_OS_FREERTOS vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } #endif start_ms += blink_interval_ms; @@ -336,7 +381,7 @@ void usb_device_task(void *param) { } } -void freertos_init_task(void) { +void freertos_init(void) { #if configSUPPORT_STATIC_ALLOCATION xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index 4ba86ca65..1aa1a5ce7 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -110,9 +110,10 @@ //#define CFG_EXAMPLE_VIDEO_READONLY //#define CFG_EXAMPLE_VIDEO_DISABLE_MJPEG +//#define CFG_EXAMPLE_VIDEO_BUFFERLESS #ifdef __cplusplus } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/video_capture/src/usb_descriptors.c b/examples/device/video_capture/src/usb_descriptors.c index b3e19b0f0..b3382c82d 100644 --- a/examples/device/video_capture/src/usb_descriptors.c +++ b/examples/device/video_capture/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VIDEO, 5) | PID_MAP(VENDOR, 6) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -63,7 +63,7 @@ char const* string_desc_arr[] = { //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -384,9 +384,9 @@ static uint8_t * get_hs_configuration_desc(void) { } // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, +static tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = USB_BCD, .bDeviceClass = TUSB_CLASS_MISC, diff --git a/examples/device/video_capture_2ch/Makefile b/examples/device/video_capture_2ch/Makefile index d698a848d..6c248ab7b 100644 --- a/examples/device/video_capture_2ch/Makefile +++ b/examples/device/video_capture_2ch/Makefile @@ -1,4 +1,4 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk ifeq ($(DISABLE_MJPEG),1) CFLAGS += -DCFG_EXAMPLE_VIDEO_DISABLE_MJPEG @@ -9,10 +9,10 @@ endif INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index 0f6508226..af3b0de04 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -6,7 +6,6 @@ mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:STM32L0 -mcu:MCXA15 family:espressif board:curiosity_nano board:kuiic diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index f56738f67..79b149f2b 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -53,7 +53,7 @@ void usb_device_task(void *param); void video_task(void* param); #if CFG_TUSB_OS == OPT_OS_FREERTOS -void freertos_init_task(void); +void freertos_init(void); #endif @@ -65,7 +65,7 @@ int main(void) { // If using FreeRTOS: create blinky, tinyusb device, video task #if CFG_TUSB_OS == OPT_OS_FREERTOS - freertos_init_task(); + freertos_init(); #else // init device stack on configured roothub port tusb_rhport_init_t dev_init = { @@ -180,7 +180,7 @@ static void fill_color_bar(uint8_t* buffer, unsigned start_position) { } #endif -size_t get_framebuf(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, size_t fnum, void **fb) { +static size_t get_framebuf(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, size_t fnum, void **fb) { uint32_t idx = ctl_idx + stm_idx; if (idx == 0) { @@ -205,8 +205,7 @@ size_t get_framebuf(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, size_t fnum, voi //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ - -void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { +static void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { static unsigned start_ms[CFG_TUD_VIDEO_STREAMING] = {0, }; static unsigned already_sent = 0; @@ -344,7 +343,7 @@ void usb_device_task(void *param) { } } -void freertos_init_task(void) { +void freertos_init(void) { #if configSUPPORT_STATIC_ALLOCATION xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); diff --git a/examples/device/video_capture_2ch/src/tusb_config.h b/examples/device/video_capture_2ch/src/tusb_config.h index e84e49879..48ab4d20a 100644 --- a/examples/device/video_capture_2ch/src/tusb_config.h +++ b/examples/device/video_capture_2ch/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -117,4 +117,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/video_capture_2ch/src/usb_descriptors.c b/examples/device/video_capture_2ch/src/usb_descriptors.c index e78e452fc..8dc986da6 100644 --- a/examples/device/video_capture_2ch/src/usb_descriptors.c +++ b/examples/device/video_capture_2ch/src/usb_descriptors.c @@ -33,9 +33,9 @@ * Auto ProductID layout's Bitmap: * [MSB] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VIDEO, 5) | _PID_MAP(VENDOR, 6) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(AUDIO, 4) | PID_MAP(VIDEO, 5) | PID_MAP(VENDOR, 6) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -68,7 +68,7 @@ char const* string_desc_arr[] = { //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -551,9 +551,9 @@ static uint8_t * get_hs_configuration_desc(void) { } // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, +static tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = USB_BCD, .bDeviceClass = TUSB_CLASS_MISC, diff --git a/examples/device/webusb_serial/Makefile b/examples/device/webusb_serial/Makefile index 7fa475da5..035e90308 100644 --- a/examples/device/webusb_serial/Makefile +++ b/examples/device/webusb_serial/Makefile @@ -1,11 +1,11 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/device/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c index 4a724f45e..0c2acd94e 100644 --- a/examples/device/webusb_serial/src/main.c +++ b/examples/device/webusb_serial/src/main.c @@ -107,7 +107,7 @@ int main(void) { } // send characters to both CDC and WebUSB -void echo_all(const uint8_t buf[], uint32_t count) { +static void echo_all(const uint8_t buf[], uint32_t count) { // echo to web serial if (web_serial_connected) { tud_vendor_write(buf, count); diff --git a/examples/device/webusb_serial/src/tusb_config.h b/examples/device/webusb_serial/src/tusb_config.h index b86ad3752..b6cdf7e56 100644 --- a/examples/device/webusb_serial/src/tusb_config.h +++ b/examples/device/webusb_serial/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/device/webusb_serial/src/usb_descriptors.c b/examples/device/webusb_serial/src/usb_descriptors.c index 2b69a5b56..0ef41a68e 100644 --- a/examples/device/webusb_serial/src/usb_descriptors.c +++ b/examples/device/webusb_serial/src/usb_descriptors.c @@ -33,14 +33,14 @@ * Auto ProductID layout's Bitmap: * [MSB] MIDI | HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, @@ -228,7 +228,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = +static char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer diff --git a/examples/dual/host_hid_to_device_cdc/Makefile b/examples/dual/host_hid_to_device_cdc/Makefile index 474ae9814..a51251bf9 100644 --- a/examples/dual/host_hid_to_device_cdc/Makefile +++ b/examples/dual/host_hid_to_device_cdc/Makefile @@ -1,12 +1,12 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference @@ -15,4 +15,4 @@ SRC_C += \ src/host/hub.c \ src/host/usbh.c -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c index 9d57737fb..3efa30e20 100644 --- a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c +++ b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -122,7 +122,7 @@ enum { #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) // full speed configuration -uint8_t const desc_fs_configuration[] = { +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -134,7 +134,7 @@ uint8_t const desc_fs_configuration[] = { // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration // high speed configuration -uint8_t const desc_hs_configuration[] = { +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -143,10 +143,10 @@ uint8_t const desc_hs_configuration[] = { }; // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = USB_BCD, @@ -175,7 +175,7 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, CONFIG_TOTAL_LEN); diff --git a/examples/dual/host_info_to_device_cdc/CMakeLists.txt b/examples/dual/host_info_to_device_cdc/CMakeLists.txt index 6ae5b5766..ad3c5ddf0 100644 --- a/examples/dual/host_info_to_device_cdc/CMakeLists.txt +++ b/examples/dual/host_info_to_device_cdc/CMakeLists.txt @@ -10,6 +10,11 @@ project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + add_executable(${PROJECT}) # Example source @@ -25,7 +30,7 @@ target_include_directories(${PROJECT} PUBLIC # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. -family_configure_dual_usb_example(${PROJECT} noos) +family_configure_dual_usb_example(${PROJECT} ${RTOS}) # due to warnings from Pico-PIO-USB if (FAMILY STREQUAL rp2040) diff --git a/examples/dual/host_info_to_device_cdc/Makefile b/examples/dual/host_info_to_device_cdc/Makefile index 083c9169a..659cf6ff9 100644 --- a/examples/dual/host_info_to_device_cdc/Makefile +++ b/examples/dual/host_info_to_device_cdc/Makefile @@ -1,12 +1,12 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference @@ -14,4 +14,4 @@ SRC_C += \ src/host/hub.c \ src/host/usbh.c -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/dual/host_info_to_device_cdc/only.txt b/examples/dual/host_info_to_device_cdc/only.txt index 35f896f1e..4431065ba 100644 --- a/examples/dual/host_info_to_device_cdc/only.txt +++ b/examples/dual/host_info_to_device_cdc/only.txt @@ -8,3 +8,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:ESP32P4 diff --git a/examples/dual/host_info_to_device_cdc/src/CMakeLists.txt b/examples/dual/host_info_to_device_cdc/src/CMakeLists.txt new file mode 100644 index 000000000..cef2b46ee --- /dev/null +++ b/examples/dual/host_info_to_device_cdc/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "main.c" "usb_descriptors.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c index 67e905b9d..00d059b66 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -69,14 +69,18 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -static bool is_print[CFG_TUH_DEVICE_MAX+1] = { 0 }; +static bool is_printable[CFG_TUH_DEVICE_MAX + 1] = {0}; static tusb_desc_device_t descriptor_device[CFG_TUH_DEVICE_MAX+1]; static void print_utf16(uint16_t *temp_buf, size_t buf_len); static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device); -void led_blinking_task(void); -void cdc_task(void); +static void led_blinking_task(void); +static void cdc_task(void); + +#if CFG_TUSB_OS == OPT_OS_FREERTOS +static void freertos_init(void); +#endif #define cdc_printf(...) \ do { \ @@ -94,37 +98,90 @@ void cdc_task(void); } \ } while(0) -/*------------- MAIN -------------*/ -int main(void) { - board_init(); - - printf("TinyUSB Host Information -> Device CDC Example\r\n"); +static void usb_device_init(void) { // init device and host stack on configured roothub port tusb_rhport_init_t dev_init = { .role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO }; tusb_init(BOARD_TUD_RHPORT, &dev_init); + tud_cdc_configure_t cdc_cfg = TUD_CDC_CONFIGURE_DEFAULT(); + cdc_cfg.tx_persistent = true; + cdc_cfg.tx_overwritabe_if_not_connected = false; + tud_cdc_configure(&cdc_cfg); + board_init_after_tusb(); +} +static void usb_host_init(void) { + // init host stack on configured roothub port tusb_rhport_init_t host_init = { .role = TUSB_ROLE_HOST, .speed = TUSB_SPEED_AUTO }; tusb_init(BOARD_TUH_RHPORT, &host_init); - board_init_after_tusb(); +} + +//--------------------------------------------------------------------+ +// Main +//--------------------------------------------------------------------+ +static void main_task(void* param) { + (void) param; while (1) { - tud_task(); // tinyusb device task - tuh_task(); // tinyusb host task cdc_task(); led_blinking_task(); + + // preempted RTOS run device/host stack in its own task +#if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO + tud_task(); // tinyusb device task + tuh_task(); // tinyusb host task +#endif } +} + +int main(void) { + board_init(); + +#if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO + printf("TinyUSB Host Information -> Device CDC Example\r\n"); + + usb_device_init(); + usb_host_init(); + + main_task(NULL); +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + freertos_init(); // create RTOS tasks for device, host stack and main_task() +#else + #error RTOS not supported +#endif return 0; } +#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO +// USB Device Driver task for RTOS +static void usb_device_task(void *param) { + (void) param; + usb_device_init(); + while (1) { + // put this thread to waiting state until there is new events + tud_task(); + } +} + +static void usb_host_task(void *param) { + (void) param; + usb_host_init(); + while (1) { + // put this thread to waiting state until there is new events + tuh_task(); + } +} +#endif + + //--------------------------------------------------------------------+ // Device CDC //--------------------------------------------------------------------+ @@ -153,17 +210,23 @@ void tud_resume_cb(void) { } void cdc_task(void) { + static uint32_t connected_ms = 0; + if (!tud_cdc_connected()) { - // delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding. - // If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop - board_delay(20); + connected_ms = board_millis(); return; } + // delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding. + // If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop + if (board_millis() - connected_ms < 100) { + return; // wait for stable connection + } + for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) { if (tuh_mounted(daddr)) { - if (is_print[daddr]) { - is_print[daddr] = false; + if (is_printable[daddr]) { + is_printable[daddr] = false; print_device_info(daddr, &descriptor_device[daddr]); tud_cdc_write_flush(); } @@ -218,9 +281,7 @@ static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_devi cdc_printf("\r\n"); cdc_printf(" iSerialNumber %u " , desc_device->iSerialNumber); - cdc_printf((char*)serial); // serial is already to UTF-8 - cdc_printf("\r\n"); - + cdc_printf("%s \r\n", (char*)serial); // serial is already to UTF-8 cdc_printf(" bNumConfigurations %u\r\n" , desc_device->bNumConfigurations); } @@ -232,13 +293,13 @@ void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc void tuh_mount_cb(uint8_t daddr) { cdc_printf("mounted device %u\r\n", daddr); tud_cdc_write_flush(); - is_print[daddr] = true; + is_printable[daddr] = true; } void tuh_umount_cb(uint8_t daddr) { cdc_printf("unmounted device %u\r\n", daddr); tud_cdc_write_flush(); - is_print[daddr] = false; + is_printable[daddr] = false; } //--------------------------------------------------------------------+ @@ -261,7 +322,6 @@ void led_blinking_task(void) { //--------------------------------------------------------------------+ // String Descriptor Helper //--------------------------------------------------------------------+ - static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) { // TODO: Check for runover. (void)utf8_len; @@ -310,5 +370,55 @@ static void print_utf16(uint16_t *temp_buf, size_t buf_len) { _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); ((uint8_t*) temp_buf)[utf8_len] = '\0'; - cdc_printf((char*) temp_buf); + cdc_printf("%s", (char*) temp_buf); } + +//--------------------------------------------------------------------+ +// FreeRTOS +//--------------------------------------------------------------------+ +#if CFG_TUSB_OS == OPT_OS_FREERTOS + +#ifdef ESP_PLATFORM + #define USBD_STACK_SIZE 4096 + #define USBH_STACK_SIZE 4096 + void app_main(void) { + main(); + } +#else + // Increase stack size when debug log is enabled + #define USBD_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) + #define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) +#endif + +#define MAIN_STACK_SIZE (configMINIMAL_STACK_SIZE*4) + +// static task +#if configSUPPORT_STATIC_ALLOCATION +StackType_t main_stack[MAIN_STACK_SIZE]; +StaticTask_t main_taskdef; + +StackType_t usb_device_stack[USBD_STACK_SIZE]; +StaticTask_t usb_device_taskdef; + +StackType_t usb_host_stack[USBH_STACK_SIZE]; +StaticTask_t usb_host_taskdef; +#endif + +void freertos_init(void) { + #if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef); + xTaskCreateStatic(main_task, "main", MAIN_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, main_stack, &main_taskdef); + #else + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(main_task, "main", MAIN_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); + #endif + + // only start scheduler for non-espressif mcu + #ifndef ESP_PLATFORM + vTaskStartScheduler(); + #endif +} + +#endif diff --git a/examples/dual/host_info_to_device_cdc/src/tusb_config.h b/examples/dual/host_info_to_device_cdc/src/tusb_config.h index bb47fbf4a..601c27dae 100644 --- a/examples/dual/host_info_to_device_cdc/src/tusb_config.h +++ b/examples/dual/host_info_to_device_cdc/src/tusb_config.h @@ -112,7 +112,7 @@ // 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) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 256) // CDC Endpoint transfer buffer size, more is faster #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c index 9d57737fb..3efa30e20 100644 --- a/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c +++ b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c @@ -32,9 +32,9 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ + PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = { +static tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -122,7 +122,7 @@ enum { #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) // full speed configuration -uint8_t const desc_fs_configuration[] = { +static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -134,7 +134,7 @@ uint8_t const desc_fs_configuration[] = { // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration // high speed configuration -uint8_t const desc_hs_configuration[] = { +static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -143,10 +143,10 @@ uint8_t const desc_hs_configuration[] = { }; // other speed configuration -uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; +static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = { +static tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_qualifier_t), .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, .bcdUSB = USB_BCD, @@ -175,7 +175,7 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, CONFIG_TOTAL_LEN); diff --git a/examples/host/bare_api/Makefile b/examples/host/bare_api/Makefile index 0235e08c3..f8292385e 100644 --- a/examples/host/bare_api/Makefile +++ b/examples/host/bare_api/Makefile @@ -1,13 +1,13 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ src/main.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 213c02f9c..d72e91e74 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -1,8 +1,8 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ @@ -11,6 +11,6 @@ EXAMPLE_SOURCE = \ src/main.c \ src/msc_app.c \ -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/cdc_msc_hid/src/app.h b/examples/host/cdc_msc_hid/src/app.h new file mode 100644 index 000000000..49783b4ae --- /dev/null +++ b/examples/host/cdc_msc_hid/src/app.h @@ -0,0 +1,34 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 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 TUSB_TINYUSB_EXAMPLES_APP_H +#define TUSB_TINYUSB_EXAMPLES_APP_H + +#include <stdio.h> + +void cdc_app_task(void); +void hid_app_task(void); + +#endif diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index 97f1a96d6..4c2c5e807 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -26,6 +26,7 @@ #include "tusb.h" #include "bsp/board_api.h" +#include "app.h" static size_t get_console_inputs(uint8_t* buf, size_t bufsize) { size_t count = 0; @@ -50,7 +51,7 @@ void cdc_app_task(void) { for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { if (tuh_cdc_mounted(idx)) { // console --> cdc interfaces - if (count) { + if (count > 0) { tuh_cdc_write(idx, buf, count); tuh_cdc_write_flush(idx); } diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 6f01d6f45..eb20356cb 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -22,9 +22,9 @@ * THE SOFTWARE. * */ - #include "bsp/board_api.h" #include "tusb.h" +#include "app.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index e2dd6e5d2..c309a7cae 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -29,13 +29,12 @@ #include "bsp/board_api.h" #include "tusb.h" +#include "app.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ void led_blinking_task(void); -extern void cdc_app_task(void); -extern void hid_app_task(void); /*------------- MAIN -------------*/ int main(void) { diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 0e9c99766..dd4e22d7f 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -23,6 +23,7 @@ * */ +#include <stdio.h> #include "tusb.h" //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 2f8cb5e03..75de3511c 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -134,4 +134,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile index 178341f81..2e323ed56 100644 --- a/examples/host/cdc_msc_hid_freertos/Makefile +++ b/examples/host/cdc_msc_hid_freertos/Makefile @@ -1,9 +1,9 @@ RTOS = freertos -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE = \ @@ -12,6 +12,6 @@ EXAMPLE_SOURCE = \ src/main.c \ src/msc_app.c \ -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index 576271aff..ef0a1ac96 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -1,4 +1,3 @@ -mcu:ESP32P4 mcu:LPC175X_6X mcu:LPC177X_8X mcu:LPC18XX @@ -15,5 +14,6 @@ mcu:STM32F7 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 +family:espressif family:samd21 family:samd5x_e5x diff --git a/examples/host/cdc_msc_hid_freertos/src/app.h b/examples/host/cdc_msc_hid_freertos/src/app.h new file mode 100644 index 000000000..8892a1b6b --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/app.h @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 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 TUSB_TINYUSB_EXAMPLES_APP_H +#define TUSB_TINYUSB_EXAMPLES_APP_H + +#include <stdio.h> + +void cdc_app_init(void); +void hid_app_init(void); +void msc_app_init(void); + +#endif diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index d99760a02..0e0105980 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -26,6 +26,7 @@ #include "tusb.h" #include "bsp/board_api.h" +#include "app.h" #ifdef ESP_PLATFORM #define CDC_STACK_SZIE 2048 @@ -45,9 +46,9 @@ static void cdc_app_task(void* param); void cdc_app_init(void) { #if configSUPPORT_STATIC_ALLOCATION - xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + (void) xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); #else - xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); + (void) xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); #endif } @@ -56,7 +57,9 @@ static size_t get_console_inputs(uint8_t *buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { int ch = board_getchar(); - if (ch <= 0) break; + if (ch <= 0) { + break; + } buf[count] = (uint8_t) ch; count++; diff --git a/examples/host/cdc_msc_hid_freertos/src/hid_app.c b/examples/host/cdc_msc_hid_freertos/src/hid_app.c index 9ea5c1be0..79e0b5a28 100644 --- a/examples/host/cdc_msc_hid_freertos/src/hid_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/hid_app.c @@ -25,6 +25,7 @@ #include "bsp/board_api.h" #include "tusb.h" +#include "app.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION @@ -160,7 +161,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report) { // Mouse //--------------------------------------------------------------------+ -void cursor_movement(int8_t x, int8_t y, int8_t wheel) { +static void cursor_movement(int8_t x, int8_t y, int8_t wheel) { #if USE_ANSI_ESCAPE // Move X using ansi escape if ( x < 0) { @@ -210,6 +211,7 @@ static void process_mouse_report(hid_mouse_report_t const *report) { //--------------------------------------------------------------------+ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { (void) dev_addr; + (void) len; uint8_t const rpt_count = hid_info[instance].report_count; tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info; diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index d498c1b57..a41de2769 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -29,12 +29,13 @@ #include "bsp/board_api.h" #include "tusb.h" +#include "app.h" #ifdef ESP_PLATFORM #define USBH_STACK_SIZE 4096 #else // Increase stack size when debug log is enabled - #define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) + #define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2)) #endif @@ -65,9 +66,6 @@ TimerHandle_t blinky_tm; static void led_blinky_cb(TimerHandle_t xTimer); static void usb_host_task(void* param); -extern void cdc_app_init(void); -extern void hid_app_init(void); -extern void msc_app_init(void); /*------------- MAIN -------------*/ int main(void) { diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c index 6439495a8..fa864c364 100644 --- a/examples/host/cdc_msc_hid_freertos/src/msc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c @@ -23,7 +23,10 @@ * */ +#include <stdio.h> + #include "tusb.h" +#include "app.h" // define the buffer to be place in USB/DMA memory with correct alignment/cache line size CFG_TUH_MEM_SECTION static struct { diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index 3cdb227e2..8583e7176 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -139,4 +139,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/host/device_info/Makefile b/examples/host/device_info/Makefile index 0235e08c3..f8292385e 100644 --- a/examples/host/device_info/Makefile +++ b/examples/host/device_info/Makefile @@ -1,13 +1,13 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ src/main.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index 133a7c9a0..61a08f68d 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -1,7 +1,4 @@ mcu:CH32V20X -mcu:ESP32S2 -mcu:ESP32S3 -mcu:ESP32P4 mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X @@ -21,5 +18,6 @@ mcu:STM32F7 mcu:STM32H7 mcu:STM32H7RS mcu:STM32N6 +family:espressif family:samd21 family:samd5x_e5x diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index 419806551..5b914a2ee 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -99,6 +99,7 @@ int main(void) { #if CFG_TUSB_OS == OPT_OS_FREERTOS init_freertos_task(); #else + board_delay(100); // wait for uart to be ready init_tinyusb(); while (1) { tuh_task(); // tinyusb host task @@ -171,9 +172,7 @@ void tuh_mount_cb(uint8_t daddr) { printf("\r\n"); printf(" iSerialNumber %u ", desc.device.iSerialNumber); - printf((char*)desc.serial); // serial is already to UTF-8 - printf("\r\n"); - + printf("%s\r\n", (char*)desc.serial); // serial is already to UTF-8 printf(" bNumConfigurations %u\r\n", desc.device.bNumConfigurations); } @@ -291,6 +290,7 @@ void app_main(void) { void usb_host_task(void *param) { (void) param; + board_delay(100); // wait for uart to be ready init_tinyusb(); while (1) { tuh_task(); diff --git a/examples/host/hid_controller/Makefile b/examples/host/hid_controller/Makefile index 1377f1f90..732520c63 100644 --- a/examples/host/hid_controller/Makefile +++ b/examples/host/hid_controller/Makefile @@ -1,14 +1,14 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ src/hid_app.c \ src/main.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/hid_controller/src/app.h b/examples/host/hid_controller/src/app.h new file mode 100644 index 000000000..b4d072668 --- /dev/null +++ b/examples/host/hid_controller/src/app.h @@ -0,0 +1,33 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 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 TUSB_TINYUSB_EXAMPLES_APP_H +#define TUSB_TINYUSB_EXAMPLES_APP_H + +#include <stdio.h> + +void hid_app_task(void); + +#endif diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index 1d6ca8b07..f8c3d029b 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -25,6 +25,7 @@ #include "bsp/board_api.h" #include "tusb.h" +#include "app.h" /* From https://www.kernel.org/doc/html/latest/input/gamepad.html ____________________________ __ diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c index f3244db95..fa70d7d1a 100644 --- a/examples/host/hid_controller/src/main.c +++ b/examples/host/hid_controller/src/main.c @@ -34,18 +34,15 @@ #include "bsp/board_api.h" #include "tusb.h" +#include "app.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ void led_blinking_task(void); -extern void cdc_task(void); -extern void hid_app_task(void); - /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); printf("TinyUSB Host HID Controller Example\r\n"); @@ -60,19 +57,11 @@ int main(void) board_init_after_tusb(); - while (1) - { + while (1) { // tinyusb host task tuh_task(); led_blinking_task(); - -#if CFG_TUH_CDC - cdc_task(); -#endif - -#if CFG_TUH_HID hid_app_task(); -#endif } } @@ -83,8 +72,7 @@ int main(void) //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { const uint32_t interval_ms = 1000; static uint32_t start_ms = 0; diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h index 351fe0178..a5c202fda 100644 --- a/examples/host/hid_controller/src/tusb_config.h +++ b/examples/host/hid_controller/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -119,4 +119,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/host/midi_rx/CMakePresets.json b/examples/host/midi_rx/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/midi_rx/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/midi_rx/Makefile b/examples/host/midi_rx/Makefile index 0235e08c3..f8292385e 100644 --- a/examples/host/midi_rx/Makefile +++ b/examples/host/midi_rx/Makefile @@ -1,13 +1,13 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source EXAMPLE_SOURCE += \ src/main.c -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index 5ac75c04a..e9c15b7c1 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -27,10 +27,8 @@ target_sources(${PROJECT} PUBLIC ) # Suppress warnings on fatfs -if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - set_source_files_properties( - ${TOP}/lib/fatfs/source/ff.c - PROPERTIES +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${TOP}/lib/fatfs/source/ff.c PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual" ) endif () diff --git a/examples/host/msc_file_explorer/Makefile b/examples/host/msc_file_explorer/Makefile index f0872376f..39d00d982 100644 --- a/examples/host/msc_file_explorer/Makefile +++ b/examples/host/msc_file_explorer/Makefile @@ -1,10 +1,9 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk FATFS_PATH = lib/fatfs/source INC += \ src \ - $(TOP)/hw \ $(TOP)/$(FATFS_PATH) \ $(TOP)/lib/embedded-cli \ @@ -13,7 +12,7 @@ EXAMPLE_SOURCE = \ src/main.c \ src/msc_app.c \ -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) # FatFS source SRC_C += \ @@ -24,4 +23,4 @@ SRC_C += \ # suppress warning caused by fatfs CFLAGS_GCC += -Wno-error=cast-qual -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c index 506c3b015..f9ec0ff5f 100644 --- a/examples/host/msc_file_explorer/src/main.c +++ b/examples/host/msc_file_explorer/src/main.c @@ -56,7 +56,6 @@ */ #include <stdlib.h> -#include <stdio.h> #include <string.h> #include "bsp/board_api.h" diff --git a/examples/host/msc_file_explorer/src/msc_app.h b/examples/host/msc_file_explorer/src/msc_app.h index 3ba03d0dc..a99da5b5c 100644 --- a/examples/host/msc_file_explorer/src/msc_app.h +++ b/examples/host/msc_file_explorer/src/msc_app.h @@ -27,6 +27,7 @@ #define MSC_APP_H #include <stdbool.h> +#include <stdio.h> bool msc_app_init(void); void msc_app_task(void); diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index c1829c300..a9d24c89f 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -118,4 +118,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/examples/typec/power_delivery/Makefile b/examples/typec/power_delivery/Makefile index 7fa475da5..7f65c689a 100644 --- a/examples/typec/power_delivery/Makefile +++ b/examples/typec/power_delivery/Makefile @@ -1,11 +1,13 @@ -include ../../build_system/make/make.mk +include ../../../hw/bsp/family_support.mk INC += \ src \ - $(TOP)/hw \ + # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) -SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +EXAMPLE_SOURCE += \ + src/main.c + +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE)) -include ../../build_system/make/rules.mk +include ../../../hw/bsp/family_rules.mk diff --git a/examples/typec/power_delivery/src/tusb_config.h b/examples/typec/power_delivery/src/tusb_config.h index f7cb3cc04..ee013d056 100644 --- a/examples/typec/power_delivery/src/tusb_config.h +++ b/examples/typec/power_delivery/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -80,4 +80,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json index 24da362da..5df924138 100644 --- a/hw/bsp/BoardPresets.json +++ b/hw/bsp/BoardPresets.json @@ -13,7 +13,7 @@ } }, { - "name": "default single", + "name": "default single config", "hidden": true, "description": "Configure preset for the ${presetName} board", "generator": "Ninja", @@ -27,31 +27,67 @@ "inherits": "default" }, { - "name": "adafruit_feather_esp32_v2", - "inherits": "default single" + "name": "adafruit_feather_rp2040_usb_host", + "inherits": "default" }, { - "name": "adafruit_feather_esp32s2", - "inherits": "default single" + "name": "adafruit_fruit_jam", + "inherits": "default" }, { - "name": "adafruit_feather_esp32s3", - "inherits": "default single" + "name": "adafruit_metro_rp2350", + "inherits": "default" }, { - "name": "adafruit_magtag_29gray", + "name": "apard32690", "inherits": "default" }, { - "name": "adafruit_metro_esp32s2", - "inherits": "default single" + "name": "arduino_nano33_ble", + "inherits": "default" }, { - "name": "apard32690", + "name": "at32f403a_weact_blackpill", "inherits": "default" }, { - "name": "arduino_nano33_ble", + "name": "at_start_f402", + "inherits": "default" + }, + { + "name": "at_start_f403a", + "inherits": "default" + }, + { + "name": "at_start_f405", + "inherits": "default" + }, + { + "name": "at_start_f407", + "inherits": "default" + }, + { + "name": "at_start_f413", + "inherits": "default" + }, + { + "name": "at_start_f415", + "inherits": "default" + }, + { + "name": "at_start_f423", + "inherits": "default" + }, + { + "name": "at_start_f425", + "inherits": "default" + }, + { + "name": "at_start_f435", + "inherits": "default" + }, + { + "name": "at_start_f437", "inherits": "default" }, { @@ -139,42 +175,6 @@ "inherits": "default" }, { - "name": "espressif_addax_1", - "inherits": "default single" - }, - { - "name": "espressif_c3_devkitc", - "inherits": "default single" - }, - { - "name": "espressif_c6_devkitc", - "inherits": "default single" - }, - { - "name": "espressif_kaluga_1", - "inherits": "default single" - }, - { - "name": "espressif_p4_function_ev", - "inherits": "default single" - }, - { - "name": "espressif_s2_devkitc", - "inherits": "default single" - }, - { - "name": "espressif_s3_devkitc", - "inherits": "default single" - }, - { - "name": "espressif_s3_devkitm", - "inherits": "default single" - }, - { - "name": "espressif_saola_1", - "inherits": "default single" - }, - { "name": "f1c100s", "inherits": "default" }, @@ -227,6 +227,10 @@ "inherits": "default" }, { + "name": "frdm_mcxa156", + "inherits": "default" + }, + { "name": "frdm_mcxn947", "inherits": "default" }, @@ -359,6 +363,10 @@ "inherits": "default" }, { + "name": "metro_nrf52840", + "inherits": "default" + }, + { "name": "mimxrt1010_evk", "inherits": "default" }, @@ -411,19 +419,47 @@ "inherits": "default" }, { - "name": "pca10056", + "name": "nanoch32v305", + "inherits": "default" + }, + { + "name": "nrf52833dk", + "inherits": "default" + }, + { + "name": "nrf52840dk", "inherits": "default" }, { - "name": "pca10059", + "name": "nrf52840dongle", "inherits": "default" }, { - "name": "pca10095", + "name": "nrf5340dk", "inherits": "default" }, { - "name": "pca10100", + "name": "nrf54h20dk", + "inherits": "default" + }, + { + "name": "nutiny_nuc126v", + "inherits": "default" + }, + { + "name": "nutiny_sdk_nuc120", + "inherits": "default" + }, + { + "name": "nutiny_sdk_nuc121", + "inherits": "default" + }, + { + "name": "nutiny_sdk_nuc125", + "inherits": "default" + }, + { + "name": "nutiny_sdk_nuc505", "inherits": "default" }, { @@ -483,6 +519,14 @@ "inherits": "default" }, { + "name": "raspberry_pi_pico2_riscv", + "inherits": "default" + }, + { + "name": "raspberry_pi_pico_w", + "inherits": "default" + }, + { "name": "raspberrypi_cm4", "inherits": "default" }, @@ -503,6 +547,14 @@ "inherits": "default" }, { + "name": "same70_qmtech", + "inherits": "default" + }, + { + "name": "same70_xplained", + "inherits": "default" + }, + { "name": "samg55_xplained", "inherits": "default" }, @@ -523,10 +575,18 @@ "inherits": "default" }, { + "name": "sltb009a", + "inherits": "default" + }, + { "name": "sparkfun_samd21_mini_usb", "inherits": "default" }, { + "name": "spresense", + "inherits": "default" + }, + { "name": "stlinkv3mini", "inherits": "default" }, @@ -687,6 +747,10 @@ "inherits": "default" }, { + "name": "stm32l496nucleo", + "inherits": "default" + }, + { "name": "stm32l4p5nucleo", "inherits": "default" }, @@ -695,6 +759,18 @@ "inherits": "default" }, { + "name": "stm32n6570dk", + "inherits": "default" + }, + { + "name": "stm32n657nucleo", + "inherits": "default" + }, + { + "name": "stm32u083cdk", + "inherits": "default" + }, + { "name": "stm32u545nucleo", "inherits": "default" }, @@ -715,6 +791,10 @@ "inherits": "default" }, { + "name": "stm32wba_nucleo", + "inherits": "default" + }, + { "name": "teensy_35", "inherits": "default" }, @@ -745,6 +825,66 @@ { "name": "xmc4700_relax", "inherits": "default" + }, + { + "name": "adafruit_feather_esp32_v2", + "inherits": "default single config" + }, + { + "name": "adafruit_feather_esp32c6", + "inherits": "default single config" + }, + { + "name": "adafruit_feather_esp32s2", + "inherits": "default single config" + }, + { + "name": "adafruit_feather_esp32s3", + "inherits": "default single config" + }, + { + "name": "adafruit_magtag_29gray", + "inherits": "default single config" + }, + { + "name": "adafruit_metro_esp32s2", + "inherits": "default single config" + }, + { + "name": "espressif_addax_1", + "inherits": "default single config" + }, + { + "name": "espressif_c3_devkitc", + "inherits": "default single config" + }, + { + "name": "espressif_c6_devkitc", + "inherits": "default single config" + }, + { + "name": "espressif_kaluga_1", + "inherits": "default single config" + }, + { + "name": "espressif_p4_function_ev", + "inherits": "default single config" + }, + { + "name": "espressif_s2_devkitc", + "inherits": "default single config" + }, + { + "name": "espressif_s3_devkitc", + "inherits": "default single config" + }, + { + "name": "espressif_s3_devkitm", + "inherits": "default single config" + }, + { + "name": "espressif_saola_1", + "inherits": "default single config" } ], "buildPresets": [ @@ -759,6 +899,11 @@ "configurePreset": "adafruit_feather_esp32_v2" }, { + "name": "adafruit_feather_esp32c6", + "description": "Build preset for the adafruit_feather_esp32c6 board", + "configurePreset": "adafruit_feather_esp32c6" + }, + { "name": "adafruit_feather_esp32s2", "description": "Build preset for the adafruit_feather_esp32s2 board", "configurePreset": "adafruit_feather_esp32s2" @@ -769,6 +914,16 @@ "configurePreset": "adafruit_feather_esp32s3" }, { + "name": "adafruit_feather_rp2040_usb_host", + "description": "Build preset for the adafruit_feather_rp2040_usb_host board", + "configurePreset": "adafruit_feather_rp2040_usb_host" + }, + { + "name": "adafruit_fruit_jam", + "description": "Build preset for the adafruit_fruit_jam board", + "configurePreset": "adafruit_fruit_jam" + }, + { "name": "adafruit_magtag_29gray", "description": "Build preset for the adafruit_magtag_29gray board", "configurePreset": "adafruit_magtag_29gray" @@ -779,6 +934,11 @@ "configurePreset": "adafruit_metro_esp32s2" }, { + "name": "adafruit_metro_rp2350", + "description": "Build preset for the adafruit_metro_rp2350 board", + "configurePreset": "adafruit_metro_rp2350" + }, + { "name": "apard32690", "description": "Build preset for the apard32690 board", "configurePreset": "apard32690" @@ -789,6 +949,61 @@ "configurePreset": "arduino_nano33_ble" }, { + "name": "at32f403a_weact_blackpill", + "description": "Build preset for the at32f403a_weact_blackpill board", + "configurePreset": "at32f403a_weact_blackpill" + }, + { + "name": "at_start_f402", + "description": "Build preset for the at_start_f402 board", + "configurePreset": "at_start_f402" + }, + { + "name": "at_start_f403a", + "description": "Build preset for the at_start_f403a board", + "configurePreset": "at_start_f403a" + }, + { + "name": "at_start_f405", + "description": "Build preset for the at_start_f405 board", + "configurePreset": "at_start_f405" + }, + { + "name": "at_start_f407", + "description": "Build preset for the at_start_f407 board", + "configurePreset": "at_start_f407" + }, + { + "name": "at_start_f413", + "description": "Build preset for the at_start_f413 board", + "configurePreset": "at_start_f413" + }, + { + "name": "at_start_f415", + "description": "Build preset for the at_start_f415 board", + "configurePreset": "at_start_f415" + }, + { + "name": "at_start_f423", + "description": "Build preset for the at_start_f423 board", + "configurePreset": "at_start_f423" + }, + { + "name": "at_start_f425", + "description": "Build preset for the at_start_f425 board", + "configurePreset": "at_start_f425" + }, + { + "name": "at_start_f435", + "description": "Build preset for the at_start_f435 board", + "configurePreset": "at_start_f435" + }, + { + "name": "at_start_f437", + "description": "Build preset for the at_start_f437 board", + "configurePreset": "at_start_f437" + }, + { "name": "atsamd21_xpro", "description": "Build preset for the atsamd21_xpro board", "configurePreset": "atsamd21_xpro" @@ -1004,6 +1219,11 @@ "configurePreset": "frdm_mcxa153" }, { + "name": "frdm_mcxa156", + "description": "Build preset for the frdm_mcxa156 board", + "configurePreset": "frdm_mcxa156" + }, + { "name": "frdm_mcxn947", "description": "Build preset for the frdm_mcxn947 board", "configurePreset": "frdm_mcxn947" @@ -1169,6 +1389,11 @@ "configurePreset": "metro_m7_1011_sd" }, { + "name": "metro_nrf52840", + "description": "Build preset for the metro_nrf52840 board", + "configurePreset": "metro_nrf52840" + }, + { "name": "mimxrt1010_evk", "description": "Build preset for the mimxrt1010_evk board", "configurePreset": "mimxrt1010_evk" @@ -1234,24 +1459,59 @@ "configurePreset": "nanoch32v203" }, { - "name": "pca10056", - "description": "Build preset for the pca10056 board", - "configurePreset": "pca10056" + "name": "nanoch32v305", + "description": "Build preset for the nanoch32v305 board", + "configurePreset": "nanoch32v305" + }, + { + "name": "nrf52833dk", + "description": "Build preset for the nrf52833dk board", + "configurePreset": "nrf52833dk" + }, + { + "name": "nrf52840dk", + "description": "Build preset for the nrf52840dk board", + "configurePreset": "nrf52840dk" + }, + { + "name": "nrf52840dongle", + "description": "Build preset for the nrf52840dongle board", + "configurePreset": "nrf52840dongle" + }, + { + "name": "nrf5340dk", + "description": "Build preset for the nrf5340dk board", + "configurePreset": "nrf5340dk" }, { - "name": "pca10059", - "description": "Build preset for the pca10059 board", - "configurePreset": "pca10059" + "name": "nrf54h20dk", + "description": "Build preset for the nrf54h20dk board", + "configurePreset": "nrf54h20dk" }, { - "name": "pca10095", - "description": "Build preset for the pca10095 board", - "configurePreset": "pca10095" + "name": "nutiny_nuc126v", + "description": "Build preset for the nutiny_nuc126v board", + "configurePreset": "nutiny_nuc126v" }, { - "name": "pca10100", - "description": "Build preset for the pca10100 board", - "configurePreset": "pca10100" + "name": "nutiny_sdk_nuc120", + "description": "Build preset for the nutiny_sdk_nuc120 board", + "configurePreset": "nutiny_sdk_nuc120" + }, + { + "name": "nutiny_sdk_nuc121", + "description": "Build preset for the nutiny_sdk_nuc121 board", + "configurePreset": "nutiny_sdk_nuc121" + }, + { + "name": "nutiny_sdk_nuc125", + "description": "Build preset for the nutiny_sdk_nuc125 board", + "configurePreset": "nutiny_sdk_nuc125" + }, + { + "name": "nutiny_sdk_nuc505", + "description": "Build preset for the nutiny_sdk_nuc505 board", + "configurePreset": "nutiny_sdk_nuc505" }, { "name": "pico_sdk", @@ -1324,6 +1584,16 @@ "configurePreset": "raspberry_pi_pico2" }, { + "name": "raspberry_pi_pico2_riscv", + "description": "Build preset for the raspberry_pi_pico2_riscv board", + "configurePreset": "raspberry_pi_pico2_riscv" + }, + { + "name": "raspberry_pi_pico_w", + "description": "Build preset for the raspberry_pi_pico_w board", + "configurePreset": "raspberry_pi_pico_w" + }, + { "name": "raspberrypi_cm4", "description": "Build preset for the raspberrypi_cm4 board", "configurePreset": "raspberrypi_cm4" @@ -1349,6 +1619,16 @@ "configurePreset": "same54_xplained" }, { + "name": "same70_qmtech", + "description": "Build preset for the same70_qmtech board", + "configurePreset": "same70_qmtech" + }, + { + "name": "same70_xplained", + "description": "Build preset for the same70_xplained board", + "configurePreset": "same70_xplained" + }, + { "name": "samg55_xplained", "description": "Build preset for the samg55_xplained board", "configurePreset": "samg55_xplained" @@ -1374,11 +1654,21 @@ "configurePreset": "sipeed_longan_nano" }, { + "name": "sltb009a", + "description": "Build preset for the sltb009a board", + "configurePreset": "sltb009a" + }, + { "name": "sparkfun_samd21_mini_usb", "description": "Build preset for the sparkfun_samd21_mini_usb board", "configurePreset": "sparkfun_samd21_mini_usb" }, { + "name": "spresense", + "description": "Build preset for the spresense board", + "configurePreset": "spresense" + }, + { "name": "stlinkv3mini", "description": "Build preset for the stlinkv3mini board", "configurePreset": "stlinkv3mini" @@ -1579,6 +1869,11 @@ "configurePreset": "stm32l476disco" }, { + "name": "stm32l496nucleo", + "description": "Build preset for the stm32l496nucleo board", + "configurePreset": "stm32l496nucleo" + }, + { "name": "stm32l4p5nucleo", "description": "Build preset for the stm32l4p5nucleo board", "configurePreset": "stm32l4p5nucleo" @@ -1589,6 +1884,21 @@ "configurePreset": "stm32l4r5nucleo" }, { + "name": "stm32n6570dk", + "description": "Build preset for the stm32n6570dk board", + "configurePreset": "stm32n6570dk" + }, + { + "name": "stm32n657nucleo", + "description": "Build preset for the stm32n657nucleo board", + "configurePreset": "stm32n657nucleo" + }, + { + "name": "stm32u083cdk", + "description": "Build preset for the stm32u083cdk board", + "configurePreset": "stm32u083cdk" + }, + { "name": "stm32u545nucleo", "description": "Build preset for the stm32u545nucleo board", "configurePreset": "stm32u545nucleo" @@ -1614,6 +1924,11 @@ "configurePreset": "stm32wb55nucleo" }, { + "name": "stm32wba_nucleo", + "description": "Build preset for the stm32wba_nucleo board", + "configurePreset": "stm32wba_nucleo" + }, + { "name": "teensy_35", "description": "Build preset for the teensy_35 board", "configurePreset": "teensy_35" @@ -1682,6 +1997,19 @@ ] }, { + "name": "adafruit_feather_esp32c6", + "steps": [ + { + "type": "configure", + "name": "adafruit_feather_esp32c6" + }, + { + "type": "build", + "name": "adafruit_feather_esp32c6" + } + ] + }, + { "name": "adafruit_feather_esp32s2", "steps": [ { @@ -1708,6 +2036,32 @@ ] }, { + "name": "adafruit_feather_rp2040_usb_host", + "steps": [ + { + "type": "configure", + "name": "adafruit_feather_rp2040_usb_host" + }, + { + "type": "build", + "name": "adafruit_feather_rp2040_usb_host" + } + ] + }, + { + "name": "adafruit_fruit_jam", + "steps": [ + { + "type": "configure", + "name": "adafruit_fruit_jam" + }, + { + "type": "build", + "name": "adafruit_fruit_jam" + } + ] + }, + { "name": "adafruit_magtag_29gray", "steps": [ { @@ -1734,6 +2088,19 @@ ] }, { + "name": "adafruit_metro_rp2350", + "steps": [ + { + "type": "configure", + "name": "adafruit_metro_rp2350" + }, + { + "type": "build", + "name": "adafruit_metro_rp2350" + } + ] + }, + { "name": "apard32690", "steps": [ { @@ -1760,6 +2127,149 @@ ] }, { + "name": "at32f403a_weact_blackpill", + "steps": [ + { + "type": "configure", + "name": "at32f403a_weact_blackpill" + }, + { + "type": "build", + "name": "at32f403a_weact_blackpill" + } + ] + }, + { + "name": "at_start_f402", + "steps": [ + { + "type": "configure", + "name": "at_start_f402" + }, + { + "type": "build", + "name": "at_start_f402" + } + ] + }, + { + "name": "at_start_f403a", + "steps": [ + { + "type": "configure", + "name": "at_start_f403a" + }, + { + "type": "build", + "name": "at_start_f403a" + } + ] + }, + { + "name": "at_start_f405", + "steps": [ + { + "type": "configure", + "name": "at_start_f405" + }, + { + "type": "build", + "name": "at_start_f405" + } + ] + }, + { + "name": "at_start_f407", + "steps": [ + { + "type": "configure", + "name": "at_start_f407" + }, + { + "type": "build", + "name": "at_start_f407" + } + ] + }, + { + "name": "at_start_f413", + "steps": [ + { + "type": "configure", + "name": "at_start_f413" + }, + { + "type": "build", + "name": "at_start_f413" + } + ] + }, + { + "name": "at_start_f415", + "steps": [ + { + "type": "configure", + "name": "at_start_f415" + }, + { + "type": "build", + "name": "at_start_f415" + } + ] + }, + { + "name": "at_start_f423", + "steps": [ + { + "type": "configure", + "name": "at_start_f423" + }, + { + "type": "build", + "name": "at_start_f423" + } + ] + }, + { + "name": "at_start_f425", + "steps": [ + { + "type": "configure", + "name": "at_start_f425" + }, + { + "type": "build", + "name": "at_start_f425" + } + ] + }, + { + "name": "at_start_f435", + "steps": [ + { + "type": "configure", + "name": "at_start_f435" + }, + { + "type": "build", + "name": "at_start_f435" + } + ] + }, + { + "name": "at_start_f437", + "steps": [ + { + "type": "configure", + "name": "at_start_f437" + }, + { + "type": "build", + "name": "at_start_f437" + } + ] + }, + { "name": "atsamd21_xpro", "steps": [ { @@ -2319,6 +2829,19 @@ ] }, { + "name": "frdm_mcxa156", + "steps": [ + { + "type": "configure", + "name": "frdm_mcxa156" + }, + { + "type": "build", + "name": "frdm_mcxa156" + } + ] + }, + { "name": "frdm_mcxn947", "steps": [ { @@ -2748,6 +3271,19 @@ ] }, { + "name": "metro_nrf52840", + "steps": [ + { + "type": "configure", + "name": "metro_nrf52840" + }, + { + "type": "build", + "name": "metro_nrf52840" + } + ] + }, + { "name": "mimxrt1010_evk", "steps": [ { @@ -2917,54 +3453,145 @@ ] }, { - "name": "pca10056", + "name": "nanoch32v305", "steps": [ { "type": "configure", - "name": "pca10056" + "name": "nanoch32v305" }, { "type": "build", - "name": "pca10056" + "name": "nanoch32v305" } ] }, { - "name": "pca10059", + "name": "nrf52833dk", "steps": [ { "type": "configure", - "name": "pca10059" + "name": "nrf52833dk" }, { "type": "build", - "name": "pca10059" + "name": "nrf52833dk" } ] }, { - "name": "pca10095", + "name": "nrf52840dk", "steps": [ { "type": "configure", - "name": "pca10095" + "name": "nrf52840dk" }, { "type": "build", - "name": "pca10095" + "name": "nrf52840dk" } ] }, { - "name": "pca10100", + "name": "nrf52840dongle", "steps": [ { "type": "configure", - "name": "pca10100" + "name": "nrf52840dongle" }, { "type": "build", - "name": "pca10100" + "name": "nrf52840dongle" + } + ] + }, + { + "name": "nrf5340dk", + "steps": [ + { + "type": "configure", + "name": "nrf5340dk" + }, + { + "type": "build", + "name": "nrf5340dk" + } + ] + }, + { + "name": "nrf54h20dk", + "steps": [ + { + "type": "configure", + "name": "nrf54h20dk" + }, + { + "type": "build", + "name": "nrf54h20dk" + } + ] + }, + { + "name": "nutiny_nuc126v", + "steps": [ + { + "type": "configure", + "name": "nutiny_nuc126v" + }, + { + "type": "build", + "name": "nutiny_nuc126v" + } + ] + }, + { + "name": "nutiny_sdk_nuc120", + "steps": [ + { + "type": "configure", + "name": "nutiny_sdk_nuc120" + }, + { + "type": "build", + "name": "nutiny_sdk_nuc120" + } + ] + }, + { + "name": "nutiny_sdk_nuc121", + "steps": [ + { + "type": "configure", + "name": "nutiny_sdk_nuc121" + }, + { + "type": "build", + "name": "nutiny_sdk_nuc121" + } + ] + }, + { + "name": "nutiny_sdk_nuc125", + "steps": [ + { + "type": "configure", + "name": "nutiny_sdk_nuc125" + }, + { + "type": "build", + "name": "nutiny_sdk_nuc125" + } + ] + }, + { + "name": "nutiny_sdk_nuc505", + "steps": [ + { + "type": "configure", + "name": "nutiny_sdk_nuc505" + }, + { + "type": "build", + "name": "nutiny_sdk_nuc505" } ] }, @@ -3151,6 +3778,32 @@ ] }, { + "name": "raspberry_pi_pico2_riscv", + "steps": [ + { + "type": "configure", + "name": "raspberry_pi_pico2_riscv" + }, + { + "type": "build", + "name": "raspberry_pi_pico2_riscv" + } + ] + }, + { + "name": "raspberry_pi_pico_w", + "steps": [ + { + "type": "configure", + "name": "raspberry_pi_pico_w" + }, + { + "type": "build", + "name": "raspberry_pi_pico_w" + } + ] + }, + { "name": "raspberrypi_cm4", "steps": [ { @@ -3216,6 +3869,32 @@ ] }, { + "name": "same70_qmtech", + "steps": [ + { + "type": "configure", + "name": "same70_qmtech" + }, + { + "type": "build", + "name": "same70_qmtech" + } + ] + }, + { + "name": "same70_xplained", + "steps": [ + { + "type": "configure", + "name": "same70_xplained" + }, + { + "type": "build", + "name": "same70_xplained" + } + ] + }, + { "name": "samg55_xplained", "steps": [ { @@ -3281,6 +3960,19 @@ ] }, { + "name": "sltb009a", + "steps": [ + { + "type": "configure", + "name": "sltb009a" + }, + { + "type": "build", + "name": "sltb009a" + } + ] + }, + { "name": "sparkfun_samd21_mini_usb", "steps": [ { @@ -3294,6 +3986,19 @@ ] }, { + "name": "spresense", + "steps": [ + { + "type": "configure", + "name": "spresense" + }, + { + "type": "build", + "name": "spresense" + } + ] + }, + { "name": "stlinkv3mini", "steps": [ { @@ -3814,6 +4519,19 @@ ] }, { + "name": "stm32l496nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32l496nucleo" + }, + { + "type": "build", + "name": "stm32l496nucleo" + } + ] + }, + { "name": "stm32l4p5nucleo", "steps": [ { @@ -3840,6 +4558,45 @@ ] }, { + "name": "stm32n6570dk", + "steps": [ + { + "type": "configure", + "name": "stm32n6570dk" + }, + { + "type": "build", + "name": "stm32n6570dk" + } + ] + }, + { + "name": "stm32n657nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32n657nucleo" + }, + { + "type": "build", + "name": "stm32n657nucleo" + } + ] + }, + { + "name": "stm32u083cdk", + "steps": [ + { + "type": "configure", + "name": "stm32u083cdk" + }, + { + "type": "build", + "name": "stm32u083cdk" + } + ] + }, + { "name": "stm32u545nucleo", "steps": [ { @@ -3905,6 +4662,19 @@ ] }, { + "name": "stm32wba_nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32wba_nucleo" + }, + { + "type": "build", + "name": "stm32wba_nucleo" + } + ] + }, + { "name": "teensy_35", "steps": [ { diff --git a/hw/bsp/ansi_escape.h b/hw/bsp/ansi_escape.h index 15af2f3ab..0b72bea17 100644 --- a/hw/bsp/ansi_escape.h +++ b/hw/bsp/ansi_escape.h @@ -28,8 +28,8 @@ * \defgroup group_ansi_esc ANSI Escape Code * @{ */ -#ifndef _TUSB_ANSI_ESC_CODE_H_ -#define _TUSB_ANSI_ESC_CODE_H_ +#ifndef TUSB_ANSI_ESC_CODE_H_ +#define TUSB_ANSI_ESC_CODE_H_ #ifdef __cplusplus @@ -92,6 +92,6 @@ } #endif -#endif /* _TUSB_ANSI_ESC_CODE_H_ */ +#endif /* TUSB_ANSI_ESC_CODE_H_ */ /** @} */ diff --git a/hw/bsp/at32f402_405/at32f402_405_int.h b/hw/bsp/at32f402_405/at32f402_405_int.h index 207a7d6df..82f924b61 100644 --- a/hw/bsp/at32f402_405/at32f402_405_int.h +++ b/hw/bsp/at32f402_405/at32f402_405_int.h @@ -48,6 +48,12 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void OTGFS1_IRQHandler(void); +void OTGHS_IRQHandler(void); +void OTGFS1_WKUP_IRQHandler(void); +void OTGHS_WKUP_IRQHandler(void); + + #ifdef __cplusplus } #endif diff --git a/hw/bsp/at32f402_405/family.c b/hw/bsp/at32f402_405/family.c index cb5987cd4..beac1a7f8 100644 --- a/hw/bsp/at32f402_405/family.c +++ b/hw/bsp/at32f402_405/family.c @@ -29,6 +29,7 @@ */ #include "at32f402_405_clock.h" +#include "at32f402_405_int.h" #include "bsp/board_api.h" #include "board.h" @@ -40,20 +41,16 @@ void usb_gpio_config(void); //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void OTGFS1_IRQHandler(void) -{ +void OTGFS1_IRQHandler(void) { tusb_int_handler(0, true); } -void OTGHS_IRQHandler(void) -{ +void OTGHS_IRQHandler(void) { tusb_int_handler(1, true); } -void OTGFS1_WKUP_IRQHandler(void) -{ +void OTGFS1_WKUP_IRQHandler(void) { tusb_int_handler(0, true); } -void OTGHS_WKUP_IRQHandler(void) -{ +void OTGHS_WKUP_IRQHandler(void) { tusb_int_handler(1, true); } @@ -278,6 +275,7 @@ void HardFault_Handler(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/at32f402_405/family.cmake b/hw/bsp/at32f402_405/family.cmake index b10760cef..87869cfe9 100644 --- a/hw/bsp/at32f402_405/family.cmake +++ b/hw/bsp/at32f402_405/family.cmake @@ -32,25 +32,21 @@ if (NOT DEFINED RHPORT_HOST_SPEED) endif () #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c @@ -58,7 +54,6 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -74,58 +69,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/at32f403a_407/at32f403a_407_int.h b/hw/bsp/at32f403a_407/at32f403a_407_int.h index 6d85c70ca..242a4abe1 100644 --- a/hw/bsp/at32f403a_407/at32f403a_407_int.h +++ b/hw/bsp/at32f403a_407/at32f403a_407_int.h @@ -48,6 +48,12 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void USBFS_H_CAN1_TX_IRQHandler(void); +void USBFS_L_CAN1_RX0_IRQHandler(void); +void USBFS_MAPH_IRQHandler(void); +void USBFS_MAPL_IRQHandler(void); +void USBFSWakeUp_IRQHandler(void); + #ifdef __cplusplus } #endif diff --git a/hw/bsp/at32f403a_407/family.c b/hw/bsp/at32f403a_407/family.c index 8c8329323..dd9b85dc5 100644 --- a/hw/bsp/at32f403a_407/family.c +++ b/hw/bsp/at32f403a_407/family.c @@ -29,6 +29,7 @@ */ #include "at32f403a_407_clock.h" +#include "at32f403a_407_int.h" #include "bsp/board_api.h" #include "board.h" @@ -266,6 +267,7 @@ void HardFault_Handler(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/at32f403a_407/family.cmake b/hw/bsp/at32f403a_407/family.cmake index ae4037088..498b89c1a 100644 --- a/hw/bsp/at32f403a_407/family.cmake +++ b/hw/bsp/at32f403a_407/family.cmake @@ -15,25 +15,21 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c @@ -41,7 +37,6 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -51,56 +46,47 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/at32f413/at32f413_int.h b/hw/bsp/at32f413/at32f413_int.h index fbbf30dbc..46ce271e5 100644 --- a/hw/bsp/at32f413/at32f413_int.h +++ b/hw/bsp/at32f413/at32f413_int.h @@ -48,6 +48,12 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void USBFS_H_CAN1_TX_IRQHandler(void); +void USBFS_L_CAN1_RX0_IRQHandler(void); +void USBFS_MAPH_IRQHandler(void); +void USBFS_MAPL_IRQHandler(void); +void USBFSWakeUp_IRQHandler(void); + #ifdef __cplusplus } #endif diff --git a/hw/bsp/at32f413/family.c b/hw/bsp/at32f413/family.c index bb16d4d5b..bdaed523c 100644 --- a/hw/bsp/at32f413/family.c +++ b/hw/bsp/at32f413/family.c @@ -29,6 +29,7 @@ */ #include "at32f413_clock.h" +#include "at32f413_int.h" #include "board.h" #include "bsp/board_api.h" @@ -266,6 +267,7 @@ void HardFault_Handler(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/at32f413/family.cmake b/hw/bsp/at32f413/family.cmake index b534bcbbc..02692daf5 100644 --- a/hw/bsp/at32f413/family.cmake +++ b/hw/bsp/at32f413/family.cmake @@ -15,25 +15,21 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c @@ -41,7 +37,6 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -51,56 +46,48 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/at32f415/at32f415_int.h b/hw/bsp/at32f415/at32f415_int.h index 2106538b6..c6df83835 100644 --- a/hw/bsp/at32f415/at32f415_int.h +++ b/hw/bsp/at32f415/at32f415_int.h @@ -48,6 +48,9 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void OTGFS1_IRQHandler(void); +void OTGFS1_WKUP_IRQHandler(void); + #ifdef __cplusplus } #endif diff --git a/hw/bsp/at32f415/family.c b/hw/bsp/at32f415/family.c index 381b79eeb..2fbd4c821 100644 --- a/hw/bsp/at32f415/family.c +++ b/hw/bsp/at32f415/family.c @@ -29,6 +29,7 @@ */ #include "at32f415_clock.h" +#include "at32f415_int.h" #include "board.h" #include "bsp/board_api.h" @@ -262,6 +263,7 @@ void HardFault_Handler(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/at32f415/family.cmake b/hw/bsp/at32f415/family.cmake index 8ac946265..f28da6f47 100644 --- a/hw/bsp/at32f415/family.cmake +++ b/hw/bsp/at32f415/family.cmake @@ -15,32 +15,27 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -49,58 +44,50 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/inc ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/at32f423/at32f423_int.h b/hw/bsp/at32f423/at32f423_int.h index 28550331e..aa707346d 100644 --- a/hw/bsp/at32f423/at32f423_int.h +++ b/hw/bsp/at32f423/at32f423_int.h @@ -39,7 +39,7 @@ extern "C" { /* exported functions ------------------------------------------------------- */ void NMI_Handler(void); -//void HardFault_Handler(void); +void HardFault_Handler(void); void MemManage_Handler(void); void BusFault_Handler(void); void UsageFault_Handler(void); @@ -48,6 +48,9 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void OTGFS1_IRQHandler(void); +void OTGFS1_WKUP_IRQHandler(void); + #ifdef __cplusplus } #endif diff --git a/hw/bsp/at32f423/family.c b/hw/bsp/at32f423/family.c index 723a8a2c9..f30c6a83f 100644 --- a/hw/bsp/at32f423/family.c +++ b/hw/bsp/at32f423/family.c @@ -29,6 +29,7 @@ */ #include "at32f423_clock.h" +#include "at32f423_int.h" #include "board.h" #include "bsp/board_api.h" @@ -266,6 +267,7 @@ void HardFault_Handler(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/at32f423/family.cmake b/hw/bsp/at32f423/family.cmake index 17c3f37a2..3c666b132 100644 --- a/hw/bsp/at32f423/family.cmake +++ b/hw/bsp/at32f423/family.cmake @@ -15,25 +15,21 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c @@ -41,7 +37,6 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -51,58 +46,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/at32f425/at32f425_int.h b/hw/bsp/at32f425/at32f425_int.h index ad9dc308b..56bb52d87 100644 --- a/hw/bsp/at32f425/at32f425_int.h +++ b/hw/bsp/at32f425/at32f425_int.h @@ -48,6 +48,9 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void OTGFS1_IRQHandler(void); +void OTGFS1_WKUP_IRQHandler(void); + #ifdef __cplusplus } #endif diff --git a/hw/bsp/at32f425/family.c b/hw/bsp/at32f425/family.c index 963e1485f..4ff4c8d6a 100644 --- a/hw/bsp/at32f425/family.c +++ b/hw/bsp/at32f425/family.c @@ -29,6 +29,7 @@ */ #include "at32f425_clock.h" +#include "at32f425_int.h" #include "board.h" #include "bsp/board_api.h" @@ -270,6 +271,7 @@ void HardFault_Handler(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/at32f425/family.cmake b/hw/bsp/at32f425/family.cmake index 3f6b36a6b..39d98a220 100644 --- a/hw/bsp/at32f425/family.cmake +++ b/hw/bsp/at32f425/family.cmake @@ -15,32 +15,27 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -49,58 +44,50 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/inc ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/at32f435_437/at32f435_437_int.h b/hw/bsp/at32f435_437/at32f435_437_int.h index 76bfaaae4..1fa34419f 100644 --- a/hw/bsp/at32f435_437/at32f435_437_int.h +++ b/hw/bsp/at32f435_437/at32f435_437_int.h @@ -48,6 +48,11 @@ void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void OTGFS1_IRQHandler(void); +void OTGFS2_IRQHandler(void); +void OTGFS1_WKUP_IRQHandler(void); +void OTGFS2_WKUP_IRQHandler(void); + #ifdef __cplusplus } #endif diff --git a/hw/bsp/at32f435_437/family.c b/hw/bsp/at32f435_437/family.c index a65116729..4bd6ee73c 100644 --- a/hw/bsp/at32f435_437/family.c +++ b/hw/bsp/at32f435_437/family.c @@ -29,6 +29,7 @@ */ #include "at32f435_437_clock.h" +#include "at32f435_437_int.h" #include "board.h" #include "bsp/board_api.h" @@ -332,6 +333,7 @@ void HardFault_Handler(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/at32f435_437/family.cmake b/hw/bsp/at32f435_437/family.cmake index 085e5462b..32a401bb6 100644 --- a/hw/bsp/at32f435_437/family.cmake +++ b/hw/bsp/at32f435_437/family.cmake @@ -15,25 +15,21 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c @@ -42,7 +38,6 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_exint.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -58,58 +53,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/board.c b/hw/bsp/board.c index e141664da..483d9dc28 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -31,7 +31,7 @@ #ifdef __ICCARM__ #define sys_write __write #define sys_read __read -#elif defined(__MSP430__) || defined(__RX__) +#elif defined(__MSP430__) || defined(__RX__) || TU_CHECK_MCU(OPT_MCU_NUC120, OPT_MCU_NUC121, OPT_MCU_NUC126, OPT_MCU_NUC505) #define sys_write write #define sys_read read #else @@ -51,8 +51,7 @@ int sys_read(int fhdl, char *buf, size_t count) TU_ATTR_USED; int sys_write(int fhdl, const char *buf, size_t count) { (void) fhdl; - SEGGER_RTT_Write(0, (const char *) buf, (int) count); - return (int) count; + return (int) SEGGER_RTT_Write(0, buf, (int) count); } int sys_read(int fhdl, char *buf, size_t count) { @@ -111,16 +110,6 @@ int sys_read (int fhdl, char *buf, size_t count) { #endif -//int _close(int fhdl) { -// (void) fhdl; -// return 0; -//} - -//int _fstat(int file, struct stat *st) { -// memset(st, 0, sizeof(*st)); -// st->st_mode = S_IFCHR; -//} - // Clang use picolibc #if defined(__clang__) static int cl_putc(char c, FILE *f) { @@ -147,8 +136,8 @@ TU_ATTR_WEAK size_t board_get_unique_id(uint8_t id[], size_t max_len) { (void) max_len; // fixed serial string is 01234567889ABCDEF uint32_t* uid32 = (uint32_t*) (uintptr_t)id; - uid32[0] = 0x67452301; - uid32[1] = 0xEFCDAB89; + uid32[0] = 0x67452301u; + uid32[1] = 0xEFCDAB89u; return 8; } @@ -169,7 +158,7 @@ int board_getchar(void) { } void board_putchar(int c) { - sys_write(0, (const char*)&c, 1); + (void) sys_write(0, (const char*)&c, 1); } uint32_t tusb_time_millis_api(void) { @@ -180,9 +169,11 @@ uint32_t tusb_time_millis_api(void) { // FreeRTOS hooks //-------------------------------------------------------------------- #if CFG_TUSB_OS == OPT_OS_FREERTOS && !defined(ESP_PLATFORM) + #include "FreeRTOS.h" #include "task.h" +void vApplicationMallocFailedHook(void); // missing prototype void vApplicationMallocFailedHook(void) { taskDISABLE_INTERRUPTS(); TU_ASSERT(false, ); @@ -199,7 +190,7 @@ void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) { /* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is * used by the Idle task. */ -void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) { +void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) { /* If the buffers to be provided to the Idle task are declared inside this * function then they must be declared static - otherwise they will be allocated on * the stack and so not exists after this function exits. */ @@ -243,6 +234,8 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, Stack } #if CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X +void vApplicationSetupTimerInterrupt(void); + #include "iodefine.h" void vApplicationSetupTimerInterrupt(void) { /* Enable CMT0 */ diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 5ecd7797a..606ac484f 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -35,6 +35,7 @@ extern "C" { #include <inttypes.h> #include <stdbool.h> #include <string.h> +#include <stdio.h> #include "tusb.h" @@ -154,15 +155,17 @@ static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars // TODO work with make, but not working with esp32s3 cmake uid_len = board_get_unique_id(uid, sizeof(uid)); - if ( uid_len > max_chars / 2 ) uid_len = max_chars / 2; + if ( uid_len > max_chars / 2u ) { + uid_len = max_chars / 2u; + } for ( size_t i = 0; i < uid_len; i++ ) { for ( size_t j = 0; j < 2; j++ ) { - const char nibble_to_hex[16] = { + const unsigned char nibble_to_hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - uint8_t const nibble = (uid[i] >> (j * 4)) & 0xf; + const uint8_t nibble = (uint8_t) ((uid[i] >> (j * 4u)) & 0xfu); desc_str1[i * 2 + (1 - j)] = nibble_to_hex[nibble]; // UTF-16-LE } } diff --git a/hw/bsp/broadcom_32bit/family.cmake b/hw/bsp/broadcom_32bit/family.cmake index 5e57d8b1e..3f327861b 100644 --- a/hw/bsp/broadcom_32bit/family.cmake +++ b/hw/bsp/broadcom_32bit/family.cmake @@ -10,24 +10,20 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS BCM2835 CACHE INTERNAL "") - #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/broadcom/link.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - set(STARTUP_FILE_GNU ${SDK_DIR}/broadcom/boot.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/broadcom/link.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/broadcom/boot.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Startup & Linker script +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/broadcom/gen/interrupt_handlers.c ${SDK_DIR}/broadcom/gpio.c @@ -35,7 +31,6 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/broadcom/mmu.c ${SDK_DIR}/broadcom/caches.c ${SDK_DIR}/broadcom/vcmailbox.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_compile_options(${BOARD_TARGET} PUBLIC -O0 @@ -49,60 +44,53 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - "LINKER:--entry=_start" - --specs=nosys.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - "LINKER:--entry=_start" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_BCM2835) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_BCM2835) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + "LINKER:--entry=_start" + --specs=nosys.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + "LINKER:--entry=_start" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/broadcom_64bit/family.cmake b/hw/bsp/broadcom_64bit/family.cmake index 1a088c2c0..6294ebafd 100644 --- a/hw/bsp/broadcom_64bit/family.cmake +++ b/hw/bsp/broadcom_64bit/family.cmake @@ -11,24 +11,20 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/aarch64_${ set(FAMILY_MCUS BCM2711 BCM2835 CACHE INTERNAL "") - #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/broadcom/link8.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - set(STARTUP_FILE_GNU ${SDK_DIR}/broadcom/boot8.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/broadcom/link8.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/broadcom/boot8.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/broadcom/gen/interrupt_handlers.c ${SDK_DIR}/broadcom/gpio.c @@ -36,7 +32,6 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/broadcom/mmu.c ${SDK_DIR}/broadcom/caches.c ${SDK_DIR}/broadcom/vcmailbox.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_compile_options(${BOARD_TARGET} PUBLIC -O0 @@ -54,62 +49,53 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") -# target_compile_options(${BOARD_TARGET} PUBLIC -# ) - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - "LINKER:--entry=_start" - --specs=nosys.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - "LINKER:--entry=_start" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_BCM${BCM_VERSION}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_BCM${BCM_VERSION}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + "LINKER:--entry=_start" + --specs=nosys.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + "LINKER:--entry=_start" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/ch32f20x/ch32f20x_it.h b/hw/bsp/ch32f20x/ch32f20x_it.h index 34f3bbf96..7daf0d76e 100644 --- a/hw/bsp/ch32f20x/ch32f20x_it.h +++ b/hw/bsp/ch32f20x/ch32f20x_it.h @@ -1,9 +1,9 @@ /********************************** (C) COPYRIGHT ******************************* -* File Name : ch32f20x_it.h -* Author : WCH -* Version : V1.0.0 -* Date : 2021/08/08 -* Description : This file contains the headers of the interrupt handlers. + * File Name : ch32f20x_it.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains the headers of the interrupt handlers. ********************************************************************************* * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. * Attention: This software (modified or not) and binary are used for @@ -21,5 +21,7 @@ void BusFault_Handler(void); void UsageFault_Handler(void); void DebugMon_Handler(void); +void USBHS_IRQHandler(void); +void SysTick_Handler(void); #endif /* __CH32F20xIT_H */ diff --git a/hw/bsp/ch32f20x/family.c b/hw/bsp/ch32f20x/family.c index 7fef71d47..7eae62fa4 100644 --- a/hw/bsp/ch32f20x/family.c +++ b/hw/bsp/ch32f20x/family.c @@ -32,6 +32,7 @@ #include "debug_uart.h" #include "ch32f20x.h" +#include "ch32f20x_it.h" #include "bsp/board_api.h" #include "board.h" diff --git a/hw/bsp/ch32v10x/ch32v10x_it.h b/hw/bsp/ch32v10x/ch32v10x_it.h index 13afc2412..34615bb69 100644 --- a/hw/bsp/ch32v10x/ch32v10x_it.h +++ b/hw/bsp/ch32v10x/ch32v10x_it.h @@ -12,4 +12,18 @@ #ifndef __CH32V10x_IT_H #define __CH32V10x_IT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "ch32v10x.h" + +void USBHD_IRQHandler(void); +void USBWakeUp_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + #endif /* __CH32V10x_IT_H */ diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c index f25102494..dfc041462 100644 --- a/hw/bsp/ch32v10x/family.c +++ b/hw/bsp/ch32v10x/family.c @@ -12,6 +12,7 @@ #endif #include "ch32v10x.h" +#include "ch32v10x_it.h" #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -44,7 +45,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t SysTick_Config(uint32_t ticks) { +static uint32_t SysTick_Config(uint32_t ticks) { NVIC_EnableIRQ(SysTicK_IRQn); SysTick->CTLR = 0; SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0; diff --git a/hw/bsp/ch32v10x/family.cmake b/hw/bsp/ch32v10x/family.cmake index a73898050..fb9ccb3a3 100644 --- a/hw/bsp/ch32v10x/family.cmake +++ b/hw/bsp/ch32v10x/family.cmake @@ -16,24 +16,21 @@ set(FAMILY_MCUS CH32V103 CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${CH32_FAMILY}.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${CH32_FAMILY}.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_SRC_DIR}/Core/core_riscv.c ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c @@ -41,76 +38,61 @@ function(add_board_target BOARD_TARGET) ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_SRC_DIR}/Core ${SDK_SRC_DIR}/Peripheral/inc ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - ) update_board(${BOARD_TARGET}) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(${BOARD_TARGET} PUBLIC - -mcmodel=medany - ) - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} - -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for MSP432E4") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_options(${BOARD_TARGET} PUBLIC -mcmodel=medany) + endif() endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_CH32V103) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_CH32V103) - - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/wch/dcd_ch32_usbfs.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} + -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) family_flash_openocd_wch(${TARGET}) - - #family_add_uf2(${TARGET} ${UF2_FAMILY_ID}) #family_flash_uf2(${TARGET} ${UF2_FAMILY_ID}) endfunction() diff --git a/hw/bsp/ch32v20x/ch32v20x_it.h b/hw/bsp/ch32v20x/ch32v20x_it.h index e49c61ae2..d1e8db255 100644 --- a/hw/bsp/ch32v20x/ch32v20x_it.h +++ b/hw/bsp/ch32v20x/ch32v20x_it.h @@ -12,4 +12,21 @@ #ifndef __CH32V20x_IT_H #define __CH32V20x_IT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "ch32v20x.h" + +void USB_LP_CAN1_RX0_IRQHandler(void); +void USB_HP_CAN1_TX_IRQHandler(void); +void USBWakeUp_IRQHandler(void); +void USBHD_IRQHandler(void); +void USBHDWakeUp_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif + #endif /* __CH32V20x_IT_H */ diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 510f82981..690acee1e 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -12,6 +12,7 @@ manufacturer: WCH #endif #include "ch32v20x.h" +#include "ch32v20x_it.h" #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -74,7 +75,7 @@ __attribute__((interrupt)) void SysTick_Handler(void) { system_ticks++; } -uint32_t SysTick_Config(uint32_t ticks) { +static uint32_t SysTick_Config(uint32_t ticks) { NVIC_EnableIRQ(SysTicK_IRQn); SysTick->CTLR = 0; SysTick->SR = 0; diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index 10044d5b3..d8c7c5327 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -24,24 +24,21 @@ endif () set(RHPORT_HOST 1) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${CH32_FAMILY}.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${CH32_FAMILY}.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_SRC_DIR}/Core/core_riscv.c ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_flash.c @@ -50,7 +47,6 @@ function(add_board_target BOARD_TARGET) ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_SRC_DIR}/Core @@ -79,65 +75,55 @@ function(add_board_target BOARD_TARGET) ) endif() - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(${BOARD_TARGET} PUBLIC - -mcmodel=medany - ) - target_link_options(${BOARD_TARGET} PUBLIC - -nostartfiles - --specs=nosys.specs --specs=nano.specs - -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} - -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for CH32v") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_options(${TARGET} PUBLIC -mcmodel=medany) + endif() endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_CH32V20X) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ${TOP}/src/portable/wch/hcd_ch32_usbfs.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_CH32V20X) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + -nostartfiles + --specs=nosys.specs --specs=nano.specs + -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} + -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/wch/dcd_ch32_usbfs.c - ${TOP}/src/portable/wch/hcd_ch32_usbfs.c - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) family_flash_openocd_wch(${TARGET}) family_flash_wlink_rs(${TARGET}) - - #family_add_uf2(${TARGET} ${UF2_FAMILY_ID}) #family_flash_uf2(${TARGET} ${UF2_FAMILY_ID}) endfunction() diff --git a/hw/bsp/ch32v30x/ch32v30x_it.h b/hw/bsp/ch32v30x/ch32v30x_it.h index f3977a8be..b9bf0b82e 100644 --- a/hw/bsp/ch32v30x/ch32v30x_it.h +++ b/hw/bsp/ch32v30x/ch32v30x_it.h @@ -10,7 +10,19 @@ #ifndef __CH32V30x_IT_H #define __CH32V30x_IT_H -// #include "debug.h" +#ifdef __cplusplus +extern "C" { +#endif + +#include "ch32v30x.h" + +void USBHS_IRQHandler(void); +void OTG_FS_IRQHandler(void); +void SysTick_Handler(void); + +#ifdef __cplusplus +} +#endif #endif /* __CH32V30x_IT_H */ diff --git a/hw/bsp/ch32v30x/debug_uart.c b/hw/bsp/ch32v30x/debug_uart.c index 2fd3a9d64..4d2992c58 100644 --- a/hw/bsp/ch32v30x/debug_uart.c +++ b/hw/bsp/ch32v30x/debug_uart.c @@ -49,7 +49,8 @@ void USART1_IRQHandler(void) { __asm volatile ("call USART1_IRQHandler_impl; mret"); } -__attribute__((used)) void USART1_IRQHandler_impl(void) +void USART1_IRQHandler_impl(void) __attribute__((used)) ; +void USART1_IRQHandler_impl(void) { if(USART_GetITStatus(USART1, USART_IT_TC) != RESET) { diff --git a/hw/bsp/ch32v30x/family.c b/hw/bsp/ch32v30x/family.c index bd01f4f46..c694f1a08 100644 --- a/hw/bsp/ch32v30x/family.c +++ b/hw/bsp/ch32v30x/family.c @@ -40,6 +40,7 @@ #include "debug_uart.h" #include "ch32v30x.h" +#include "ch32v30x_it.h" #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -70,7 +71,7 @@ __attribute__((interrupt)) void OTG_FS_IRQHandler(void) { // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -uint32_t SysTick_Config(uint32_t ticks) { +static uint32_t SysTick_Config(uint32_t ticks) { NVIC_EnableIRQ(SysTicK_IRQn); SysTick->CTLR = 0; SysTick->SR = 0; diff --git a/hw/bsp/ch32v30x/family.cmake b/hw/bsp/ch32v30x/family.cmake index 0fd9b786a..b974bd5e7 100644 --- a/hw/bsp/ch32v30x/family.cmake +++ b/hw/bsp/ch32v30x/family.cmake @@ -20,24 +20,21 @@ if (NOT DEFINED SPEED) endif() #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/ch32v30x.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_D8C.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/ch32v30x.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}_D8C.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_SRC_DIR}/Core/core_riscv.c ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c @@ -46,7 +43,6 @@ function(add_board_target BOARD_TARGET) ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${CH32_FAMILY}_it.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_SRC_DIR}/Core @@ -73,54 +69,49 @@ function(add_board_target BOARD_TARGET) -fmessage-length=0 -fsigned-char ) - target_link_options(${BOARD_TARGET} PUBLIC - -nostartfiles - --specs=nosys.specs --specs=nano.specs - -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} - -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for CH32v") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_CH32V307) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug_uart.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/wch/dcd_ch32_usbhs.c + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_CH32V307) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/wch/dcd_ch32_usbhs.c - ${TOP}/src/portable/wch/dcd_ch32_usbfs.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + -nostartfiles + --specs=nosys.specs --specs=nano.specs + -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE} + -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE} + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..57b9d7dba --- /dev/null +++ b/hw/bsp/cxd56/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "nuttx/config.h" +#endif + +/* Cortex-M4F port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +// CXD56 (Cortex-M4F) has 3 priority bits +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif diff --git a/hw/bsp/cxd56/boards/spresense/board.cmake b/hw/bsp/cxd56/boards/spresense/board.cmake new file mode 100644 index 000000000..5fe77bfaf --- /dev/null +++ b/hw/bsp/cxd56/boards/spresense/board.cmake @@ -0,0 +1,6 @@ +set(SERIAL /dev/ttyUSB0 CACHE STRING "Serial port for flashing") + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + ) +endfunction() diff --git a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c b/hw/bsp/cxd56/boards/spresense/board.h index fea3e2a66..45b1bb3e3 100644 --- a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c +++ b/hw/bsp/cxd56/boards/spresense/board.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019, Ha Thach (tinyusb.org) + * Copyright 2019 Sony Semiconductor Solutions Corporation * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,25 +24,20 @@ * This file is part of the TinyUSB stack. */ -#include "tusb_option.h" +#ifndef BOARD_H_ +#define BOARD_H_ -#if CFG_TUH_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) +#ifdef __cplusplus + extern "C" { +#endif -#include "chip.h" -#include "host/hcd.h" -#include "host/usbh.h" +#include <arch/chip/pin.h> -void hcd_int_enable(uint8_t rhport) -{ - (void) rhport; - NVIC_EnableIRQ(USB_IRQn); -} +#define LED_PIN PIN_I2S1_BCK +#define BUTTON_PIN PIN_HIF_IRQ_OUT -void hcd_int_disable(uint8_t rhport) -{ - (void) rhport; - NVIC_DisableIRQ(USB_IRQn); -} +#ifdef __cplusplus + } +#endif #endif diff --git a/hw/bsp/cxd56/boards/spresense/board.mk b/hw/bsp/cxd56/boards/spresense/board.mk new file mode 100644 index 000000000..6c31c9d9d --- /dev/null +++ b/hw/bsp/cxd56/boards/spresense/board.mk @@ -0,0 +1,7 @@ +# Spresense board configuration +SERIAL ?= /dev/ttyUSB0 + +# flash +flash: $(BUILD)/$(PROJECT).spk + @echo FLASH $< + @$(PYTHON) $(TOP)/hw/mcu/sony/cxd56/tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $< diff --git a/hw/bsp/spresense/board_spresense.c b/hw/bsp/cxd56/family.c index 8cd04a49d..a8e2fd52b 100644 --- a/hw/bsp/spresense/board_spresense.c +++ b/hw/bsp/cxd56/family.c @@ -25,18 +25,21 @@ */ #include <sys/boardctl.h> + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + #include <nuttx/arch.h> #include <arch/board/board.h> -#include <arch/chip/pin.h> - -#include "bsp/board_api.h" -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ -#define LED_PIN PIN_I2S1_BCK +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif -#define BUTTON_PIN PIN_HIF_IRQ_OUT +#include "bsp/board_api.h" +#include "board.h" // Initialize on-board peripherals : led, button, uart and USB void board_init(void) @@ -50,6 +53,10 @@ void board_init(void) board_gpio_config(PIN_HIF_IRQ_OUT, 0, true, true, PIN_FLOAT); }; +void board_late_initialize(void) { + +} + //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ diff --git a/hw/bsp/cxd56/family.cmake b/hw/bsp/cxd56/family.cmake new file mode 100644 index 000000000..7cd2f51f8 --- /dev/null +++ b/hw/bsp/cxd56/family.cmake @@ -0,0 +1,126 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/sony/cxd56/spresense-exported-sdk) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS CXD56 CACHE INTERNAL "") + +# Detect platform for mkspk tool +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk) +else() + set(MKSPK ${TOP}/hw/mcu/sony/cxd56/mkspk/mkspk.exe) +endif() + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(LD_FILE_GNU ${SDK_DIR}/nuttx/scripts/ramconfig.ld) +set(LD_FILE_Clang ${LD_FILE_GNU}) + +#------------------------------------ +# BOARD Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + # Spresense uses NuttX libraries + add_library(${BOARD_TARGET} INTERFACE) + + target_include_directories(${BOARD_TARGET} INTERFACE + ${SDK_DIR}/nuttx/include + ${SDK_DIR}/nuttx/arch + ${SDK_DIR}/nuttx/arch/chip + ${SDK_DIR}/nuttx/arch/os + ${SDK_DIR}/sdk/include + ) + + target_compile_definitions(${BOARD_TARGET} INTERFACE + CONFIG_HAVE_DOUBLE + main=spresense_main + ) + + target_compile_options(${BOARD_TARGET} INTERFACE + -pipe + -std=gnu11 + -fno-builtin + -fno-strength-reduce + -fomit-frame-pointer + -Wno-error=undef + -Wno-error=cast-align + -Wno-error=unused-parameter + -Wno-error=shadow + -Wno-error=redundant-decls + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_CXD56) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/sony/cxd56/dcd_cxd56.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + target_link_libraries(${TARGET} PUBLIC + ${SDK_DIR}/nuttx/libs/libapps.a + ${SDK_DIR}/nuttx/libs/libnuttx.a + gcc # Compiler runtime support for FP operations like __aeabi_dmul + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -Xlinker --entry=__start + -nostartfiles + -nodefaultlibs + -Wl,--gc-sections + -u spresense_main + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + -Xlinker --entry=__start + -nostartfiles + -nodefaultlibs + -u spresense_main + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Build mkspk tool + add_custom_command(OUTPUT ${MKSPK} + COMMAND $(MAKE) -C ${TOP}/hw/mcu/sony/cxd56/mkspk + COMMENT "Building mkspk tool" + ) + + # Create .spk file + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.spk + COMMAND ${MKSPK} -c 2 $<TARGET_FILE:${TARGET}> nuttx ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.spk + DEPENDS ${TARGET} ${MKSPK} + COMMENT "Creating ${TARGET}.spk" + ) +endfunction() diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/cxd56/family.mk index 24f39d2b6..adfe9ee82 100644 --- a/hw/bsp/spresense/board.mk +++ b/hw/bsp/cxd56/family.mk @@ -1,3 +1,5 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + # Platforms are: Linux, Darwin, MSYS, CYGWIN PLATFORM := $(firstword $(subst _, ,$(shell uname -s 2>/dev/null))) @@ -12,19 +14,11 @@ else MKSPK = $(TOP)/hw/mcu/sony/cxd56/mkspk/mkspk.exe endif -SERIAL ?= /dev/ttyUSB0 - CFLAGS += \ -DCONFIG_HAVE_DOUBLE \ -Dmain=spresense_main \ -pipe \ -std=gnu11 \ - -mcpu=cortex-m4 \ - -mthumb \ - -mfpu=fpv4-sp-d16 \ - -mfloat-abi=hard \ - -mabi=aapcs \ - -fno-builtin \ -fno-strength-reduce \ -fomit-frame-pointer \ -Wno-error=undef \ @@ -32,6 +26,8 @@ CFLAGS += \ -Wno-error=unused-parameter \ -DCFG_TUSB_MCU=OPT_MCU_CXD56 \ +CPU_CORE ?= cortex-m4 + # suppress following warnings from mcu driver # lwip/src/core/raw.c:334:43: error: declaration of 'recv' shadows a global declaration CFLAGS += -Wno-error=shadow -Wno-error=redundant-decls @@ -48,6 +44,7 @@ INC += \ $(SPRESENSE_SDK)/nuttx/arch/chip \ $(SPRESENSE_SDK)/nuttx/arch/os \ $(SPRESENSE_SDK)/sdk/include \ + $(TOP)/$(BOARD_PATH) LIBS += \ $(SPRESENSE_SDK)/nuttx/libs/libapps.a \ @@ -69,7 +66,5 @@ $(BUILD)/$(PROJECT).spk: $(MKSPK) @echo CREATE $@ @$(MKSPK) -c 2 $(BUILD)/$(PROJECT).elf nuttx $@ -# flash -flash: $(BUILD)/$(PROJECT).spk - @echo FLASH $< - @$(PYTHON) $(TOP)/hw/mcu/sony/cxd56/tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $< +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F diff --git a/hw/bsp/da1469x/family.cmake b/hw/bsp/da1469x/family.cmake index 20d6cbc44..40070ba10 100644 --- a/hw/bsp/da1469x/family.cmake +++ b/hw/bsp/da1469x/family.cmake @@ -10,28 +10,24 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS DA1469X CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/da1469x.ld) - endif () - - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gcc_startup_da1469x.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - endif () +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/da1469x.ld) +endif () +if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) +set(STARTUP_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/gcc_startup_da1469x.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +endif () +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${MCU_DIR}/src/system_da1469x.c ${MCU_DIR}/src/da1469x_clock.c ${MCU_DIR}/src/hal_gpio.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_compile_options(${BOARD_TARGET} PUBLIC -mthumb-interwork) target_compile_definitions(${BOARD_TARGET} PUBLIC @@ -46,31 +42,11 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -L${NRFX_DIR}/mdk - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -L${NRFX_DIR}/mdk - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ - function(family_flash_jlink_dialog TARGET) set(JLINKEXE JLinkExe) set(JLINK_IF swd) @@ -107,32 +83,42 @@ endfunction() function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_DA1469X) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/dialog/da146xx/dcd_da146xx.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_DA1469X) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/dialog/da146xx/dcd_da146xx.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..0b3e7cd2d --- /dev/null +++ b/hw/bsp/efm32/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "em_device.h" +#endif + +/* Cortex-M4F port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +// EFM32GG12B has 3 priority bits +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif diff --git a/hw/bsp/efm32/boards/sltb009a/board.cmake b/hw/bsp/efm32/boards/sltb009a/board.cmake new file mode 100644 index 000000000..7a84950b6 --- /dev/null +++ b/hw/bsp/efm32/boards/sltb009a/board.cmake @@ -0,0 +1,8 @@ +set(EFM32_FAMILY efm32gg12b) +set(EFM32_MCU EFM32GG12B810F1024GM64) +set(JLINK_DEVICE ${EFM32_MCU}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + ) +endfunction() diff --git a/hw/bsp/efm32/boards/sltb009a/board.h b/hw/bsp/efm32/boards/sltb009a/board.h new file mode 100644 index 000000000..8ed6abe9f --- /dev/null +++ b/hw/bsp/efm32/boards/sltb009a/board.h @@ -0,0 +1,49 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Rafael Silva (@perigoso) + * 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_PORT 0 // A +#define LED_PIN_R 12 // 12 +#define LED_PIN_B 13 // 13 +#define LED_PIN_G 14 // 14 +#define LED_STATE_ON 0 // active-low + +#define BUTTON_PORT 3 // D +#define BUTTON_PIN 5 // 5 +#define BUTTON_STATE_ACTIVE 0 // active-low + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/efm32/boards/sltb009a/board.mk b/hw/bsp/efm32/boards/sltb009a/board.mk new file mode 100644 index 000000000..4b3e2a4e5 --- /dev/null +++ b/hw/bsp/efm32/boards/sltb009a/board.mk @@ -0,0 +1,9 @@ +EFM32_FAMILY = efm32gg12b +EFM32_MCU = EFM32GG12B810F1024GM64 +JLINK_DEVICE = $(EFM32_MCU) + +CFLAGS += \ + -D$(EFM32_MCU) \ + +# For flash-jlink target +flash: flash-jlink diff --git a/hw/bsp/sltb009a/sltb009a.c b/hw/bsp/efm32/family.c index 23ef6d7cd..39166bc4d 100644 --- a/hw/bsp/sltb009a/sltb009a.c +++ b/hw/bsp/efm32/family.c @@ -25,7 +25,8 @@ * This file is part of the TinyUSB stack. */ -#include "../board_api.h" +#include "bsp/board_api.h" +#include "board.h" #include "em_device.h" @@ -33,16 +34,6 @@ /* MACRO TYPEDEF CONSTANT ENUM */ /*--------------------------------------------------------------------*/ -#define LED_PORT 0 // A -#define LED_PIN_R 12 // 12 -#define LED_PIN_B 13 // 13 -#define LED_PIN_G 14 // 14 -#define LED_STATE_ON 0 // active-low - -#define BUTTON_PORT 3 // D -#define BUTTON_PIN 5 // 5 -#define BUTTON_STATE_ACTIVE 0 // active-low - /*--------------------------------------------------------------------*/ /* Forward USB interrupt events to TinyUSB IRQ Handler */ /*--------------------------------------------------------------------*/ @@ -82,6 +73,7 @@ void UsageFault_Handler(void) // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { @@ -91,12 +83,12 @@ void _init(void) /* Initing Funcs */ /*--------------------------------------------------------------------*/ -void emu_init(uint8_t immediate_switch) +static void emu_init(uint8_t immediate_switch) { EMU->PWRCTRL = (immediate_switch ? EMU_PWRCTRL_IMMEDIATEPWRSWITCH : 0) | EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD; } -void emu_reg_init(float target_voltage) +static void emu_reg_init(float target_voltage) { if(target_voltage < 2300.f || target_voltage >= 3800.f) return; @@ -108,7 +100,7 @@ void emu_reg_init(float target_voltage) EMU->R5VOUTLEVEL = level; /* Reg output to 3.3V*/ } -void emu_dcdc_init(float target_voltage, float max_ln_current, float max_lp_current, float max_reverse_current) +static void emu_dcdc_init(float target_voltage, float max_ln_current, float max_lp_current, float max_reverse_current) { if(target_voltage < 1800.f || target_voltage >= 3000.f) return; @@ -279,7 +271,7 @@ void emu_dcdc_init(float target_voltage, float max_ln_current, float max_lp_curr EMU->PWRCTRL = EMU_PWRCTRL_REGPWRSEL_DVDD | EMU_PWRCTRL_ANASW_AVDD; } -void cmu_hfxo_startup_calib(uint16_t ib_trim, uint16_t c_tune) +static void cmu_hfxo_startup_calib(uint16_t ib_trim, uint16_t c_tune) { if(CMU->STATUS & CMU_STATUS_HFXOENS) return; @@ -287,7 +279,7 @@ void cmu_hfxo_startup_calib(uint16_t ib_trim, uint16_t c_tune) CMU->HFXOSTARTUPCTRL = (CMU->HFXOSTARTUPCTRL & ~(_CMU_HFXOSTARTUPCTRL_CTUNE_MASK | _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTARTUPCTRL_CTUNE_SHIFT) & _CMU_HFXOSTARTUPCTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTARTUPCTRL_IBTRIMXOCORE_MASK); } -void cmu_hfxo_steady_calib(uint16_t ib_trim, uint16_t c_tune) +static void cmu_hfxo_steady_calib(uint16_t ib_trim, uint16_t c_tune) { if(CMU->STATUS & CMU_STATUS_HFXOENS) return; @@ -295,7 +287,7 @@ void cmu_hfxo_steady_calib(uint16_t ib_trim, uint16_t c_tune) CMU->HFXOSTEADYSTATECTRL = (CMU->HFXOSTEADYSTATECTRL & ~(_CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK | _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK)) | (((uint32_t)c_tune << _CMU_HFXOSTEADYSTATECTRL_CTUNE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_CTUNE_MASK) | (((uint32_t)ib_trim << _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_SHIFT) & _CMU_HFXOSTEADYSTATECTRL_IBTRIMXOCORE_MASK); } -void cmu_hfrco_calib(uint32_t calibration) +static void cmu_hfrco_calib(uint32_t calibration) { if(CMU->STATUS & CMU_STATUS_DPLLENS) return; @@ -307,7 +299,7 @@ void cmu_hfrco_calib(uint32_t calibration) while(CMU->SYNCBUSY & CMU_SYNCBUSY_HFRCOBSY); } -void cmu_ushfrco_calib(uint8_t enable, uint32_t calibration) +static void cmu_ushfrco_calib(uint8_t enable, uint32_t calibration) { if(CMU->USBCRCTRL & CMU_USBCRCTRL_USBCREN) return; @@ -334,7 +326,7 @@ void cmu_ushfrco_calib(uint8_t enable, uint32_t calibration) } } -void cmu_auxhfrco_calib(uint8_t enable, uint32_t calibration) +static void cmu_auxhfrco_calib(uint8_t enable, uint32_t calibration) { if(!enable) { @@ -359,7 +351,7 @@ void cmu_auxhfrco_calib(uint8_t enable, uint32_t calibration) } -void cmu_init(void) +static void cmu_init(void) { // Change SDIO clock to HFXO if HFRCO selected and disable it CMU->SDIOCTRL = CMU_SDIOCTRL_SDIOCLKDIS | CMU_SDIOCTRL_SDIOCLKSEL_HFXO; @@ -441,7 +433,7 @@ void cmu_init(void) CMU->LFECLKSEL = CMU_LFECLKSEL_LFE_ULFRCO; } -void systick_init(void) +static void systick_init(void) { SysTick->LOAD = (72000000 / 1000) - 1; SysTick->VAL = 0; @@ -450,7 +442,7 @@ void systick_init(void) SCB->SHP[11] = 7 << (8 - __NVIC_PRIO_BITS); // Set priority 3,1 (min) } -void gpio_init(void) +static void gpio_init(void) { CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO; diff --git a/hw/bsp/efm32/family.cmake b/hw/bsp/efm32/family.cmake new file mode 100644 index 000000000..8c521eee0 --- /dev/null +++ b/hw/bsp/efm32/family.cmake @@ -0,0 +1,91 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# EFM32_FAMILY should be set by board.cmake (e.g. efm32gg12b) +string(TOUPPER ${EFM32_FAMILY} EFM32_FAMILY_UPPER) +set(SILABS_CMSIS ${TOP}/hw/mcu/silabs/cmsis-dfp-${EFM32_FAMILY}/Device/SiliconLabs/${EFM32_FAMILY_UPPER}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS EFM32GG CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(LD_FILE_GNU ${SILABS_CMSIS}/Source/GCC/${EFM32_FAMILY}.ld) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SILABS_CMSIS}/Source/GCC/startup_${EFM32_FAMILY}.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SILABS_CMSIS}/Source/system_${EFM32_FAMILY}.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMSIS_5}/CMSIS/Core/Include + ${SILABS_CMSIS}/Include + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + __STARTUP_CLEAR_BSS + __START=main + ${EFM32_MCU} + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_EFM32GG) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/sltb009a/board.mk b/hw/bsp/efm32/family.mk index 5dd7a158f..f115b6bd4 100644 --- a/hw/bsp/sltb009a/board.mk +++ b/hw/bsp/efm32/family.mk @@ -1,3 +1,5 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ -flto \ -mthumb \ @@ -7,38 +9,31 @@ CFLAGS += \ -nostdlib -nostartfiles \ -D__STARTUP_CLEAR_BSS \ -D__START=main \ - -DEFM32GG12B810F1024GM64 \ -DCFG_TUSB_MCU=OPT_MCU_EFM32GG -# mcu driver cause following warnings -#CFLAGS += -Wno-error=unused-parameter +CPU_CORE ?= cortex-m4 -SILABS_FAMILY = efm32gg12b -SILABS_CMSIS = hw/mcu/silabs/cmsis-dfp-$(SILABS_FAMILY)/Device/SiliconLabs/$(shell echo $(SILABS_FAMILY) | tr a-z A-Z) +# EFM32_FAMILY should be set by board.mk (e.g. efm32gg12b) +SILABS_CMSIS = hw/mcu/silabs/cmsis-dfp-$(EFM32_FAMILY)/Device/SiliconLabs/$(shell echo $(EFM32_FAMILY) | tr a-z A-Z) LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs # All source paths should be relative to the top level. -LD_FILE = $(SILABS_CMSIS)/Source/GCC/$(SILABS_FAMILY).ld +LD_FILE = $(SILABS_CMSIS)/Source/GCC/$(EFM32_FAMILY).ld SRC_C += \ - $(SILABS_CMSIS)/Source/system_$(SILABS_FAMILY).c \ + $(SILABS_CMSIS)/Source/system_$(EFM32_FAMILY).c \ src/portable/synopsys/dwc2/dcd_dwc2.c \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ SRC_S += \ - $(SILABS_CMSIS)/Source/GCC/startup_$(SILABS_FAMILY).S + $(SILABS_CMSIS)/Source/GCC/startup_$(EFM32_FAMILY).S INC += \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(SILABS_CMSIS)/Include \ - $(TOP)/hw/bsp/$(BOARD) + $(TOP)/$(BOARD_PATH) # For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F - -# For flash-jlink target -JLINK_DEVICE = EFM32GG12B810F1024 - -flash: flash-jlink diff --git a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt index 00e288bad..2f529dd68 100644 --- a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt +++ b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt @@ -1,12 +1,12 @@ idf_build_get_property(target IDF_TARGET) +include(CMakePrintHelpers) -set(srcs) -set(includes_public) -set(compile_options) -set(tusb_src "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src") +set(tusb_src ${CMAKE_CURRENT_LIST_DIR}/../../../../../src) +get_filename_component(tusb_src ${tusb_src} ABSOLUTE) +include(${tusb_src}/CMakeLists.txt) string(TOUPPER OPT_MCU_${target} tusb_mcu) -list(APPEND compile_definitions +set(compile_definitions CFG_TUSB_MCU=${tusb_mcu} CFG_TUSB_OS=OPT_OS_FREERTOS BOARD_TUD_RHPORT=${RHPORT_DEVICE} @@ -23,35 +23,11 @@ if (target STREQUAL esp32p4) ) endif () +tinyusb_sources_get(srcs) list(APPEND srcs - # common - ${tusb_src}/tusb.c - ${tusb_src}/common/tusb_fifo.c - # device - ${tusb_src}/device/usbd.c - ${tusb_src}/device/usbd_control.c - ${tusb_src}/class/audio/audio_device.c - ${tusb_src}/class/cdc/cdc_device.c - ${tusb_src}/class/dfu/dfu_device.c - ${tusb_src}/class/dfu/dfu_rt_device.c - ${tusb_src}/class/hid/hid_device.c - ${tusb_src}/class/midi/midi_device.c - ${tusb_src}/class/msc/msc_device.c - ${tusb_src}/class/net/ecm_rndis_device.c - ${tusb_src}/class/net/ncm_device.c - ${tusb_src}/class/usbtmc/usbtmc_device.c - ${tusb_src}/class/vendor/vendor_device.c - ${tusb_src}/class/video/video_device.c ${tusb_src}/portable/synopsys/dwc2/dcd_dwc2.c ${tusb_src}/portable/synopsys/dwc2/hcd_dwc2.c ${tusb_src}/portable/synopsys/dwc2/dwc2_common.c - # host - ${tusb_src}/host/usbh.c - ${tusb_src}/host/hub.c - ${tusb_src}/class/cdc/cdc_host.c - ${tusb_src}/class/hid/hid_host.c - ${tusb_src}/class/msc/msc_host.c - ${tusb_src}/class/vendor/vendor_host.c ) # use max3421 as host controller @@ -73,7 +49,6 @@ if(DEFINED CFLAGS_CLI) list(APPEND compile_definitions ${CFLAGS_CLI}) endif() - idf_component_register(SRCS ${srcs} INCLUDE_DIRS ${tusb_src} REQUIRES src @@ -81,4 +56,3 @@ idf_component_register(SRCS ${srcs} ) target_compile_definitions(${COMPONENT_LIB} PUBLIC ${compile_definitions}) -target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format) diff --git a/hw/bsp/f1c100s/family.cmake b/hw/bsp/f1c100s/family.cmake index 211c6645c..5522eeec7 100644 --- a/hw/bsp/f1c100s/family.cmake +++ b/hw/bsp/f1c100s/family.cmake @@ -11,25 +11,21 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS F1C100S CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # LD_FILE and STARTUP_FILE can be defined in board.cmake - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/f1c100s.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/machine/start.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/f1c100s.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_DIR}/machine/start.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/lib/malloc.c ${SDK_DIR}/lib/printf.c @@ -43,70 +39,70 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/machine/sys-mmu.c ${SDK_DIR}/machine/sys-spi-flash.c ${SDK_DIR}/machine/f1c100s-intc.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) - target_compile_definitions(${BOARD_TARGET} PUBLIC __ARM32_ARCH__=5 + __ARM926EJS__ + ) + target_compile_options(${BOARD_TARGET} PUBLIC + -ffreestanding + -std=gnu99 + -mno-thumb-interwork + -Wno-float-equal + -Wno-unused-parameter + -Wno-error=array-bounds ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR}/include ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -lgcc - --specs=nosys.specs --specs=nano.specs - "LINKER:--defsym=__bss_end__=__bss_end" - "LINKER:--defsym=__bss_start__=__bss_start" - "LINKER:--defsym=end=__bss_end" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_F1C100S) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/sunxi/dcd_sunxi_musb.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_F1C100S) - target_sources(${TARGET} PRIVATE - ${TOP}/src/portable/sunxi/dcd_sunxi_musb.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${TARGET} PUBLIC + gcc + ) + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + "LINKER:--defsym=__bss_end__=__bss_end" + "LINKER:--defsym=__bss_start__=__bss_start" + "LINKER:--defsym=end=__bss_end" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/examples/build_system/make/rules.mk b/hw/bsp/family_rules.mk index 86de17b6c..ccf49dd0e 100644 --- a/examples/build_system/make/rules.mk +++ b/hw/bsp/family_rules.mk @@ -171,24 +171,6 @@ DSLITE ?= dslite.sh flash-uniflash: $(BUILD)/$(PROJECT).hex ${DSLITE} ${UNIFLASH_OPTION} -f $< -#-------------- Artifacts -------------- - -# Create binary directory -$(BIN): -ifeq ($(CMDEXE),1) - @$(MKDIR) $(subst /,\,$@) -else - @$(MKDIR) -p $@ -endif - -# Copy binaries .elf, .bin, .hex, .uf2 to BIN for upload -# due to large size of combined artifacts, only uf2 is uploaded for now -copy-artifact: $(BIN) - @$(CP) $(BUILD)/$(PROJECT).uf2 $(BIN) - #@$(CP) $(BUILD)/$(PROJECT).bin $(BIN) - #@$(CP) $(BUILD)/$(PROJECT).hex $(BIN) - #@$(CP) $(BUILD)/$(PROJECT).elf $(BIN) - # Print out the value of a make variable. # https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile print-%: diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 9ec80df91..2b9612186 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -1,6 +1,8 @@ include_guard(GLOBAL) include(CMakePrintHelpers) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +#set(CMAKE_C_STANDARD 11) # TOP is path to root directory set(TOP "${CMAKE_CURRENT_LIST_DIR}/../..") @@ -8,36 +10,99 @@ get_filename_component(TOP ${TOP} ABSOLUTE) set(UF2CONV_PY ${TOP}/tools/uf2/utils/uf2conv.py) -#------------------------------------------------------------- -# RTOS -#------------------------------------------------------------- -if (NOT DEFINED RTOS) - set(RTOS noos CACHE STRING "RTOS") -endif () +function(family_resolve_board BOARD_NAME BOARD_PATH_OUT) + if ("${BOARD_NAME}" STREQUAL "") + message(FATAL_ERROR "You must set BOARD (e.g. metro_m4_express, raspberry_pi_pico). Use -DBOARD=xxx on the cmake command line.") + endif() + + file(GLOB _board_paths + LIST_DIRECTORIES true + RELATIVE ${TOP}/hw/bsp + ${TOP}/hw/bsp/*/boards/* + ) + + set(_hint_names "") + foreach(_board_path ${_board_paths}) + get_filename_component(_board_name ${_board_path} NAME) + if (_board_name STREQUAL "${BOARD_NAME}") + set(${BOARD_PATH_OUT} ${_board_path} PARENT_SCOPE) + return() + endif() + string(FIND "${_board_name}" "${BOARD_NAME}" _pos) + if (_pos EQUAL 0) + list(APPEND _hint_names ${_board_name}) + endif() + endforeach() + + if (_hint_names) + list(REMOVE_DUPLICATES _hint_names) + list(SORT _hint_names) + list(JOIN _hint_names ", " _hint_str) + message(FATAL_ERROR "BOARD '${BOARD_NAME}' not found. Boards with the same prefix:\n${_hint_str}") + else() + message(FATAL_ERROR "BOARD '${BOARD_NAME}' not found under hw/bsp/*/boards") + endif() +endfunction() #------------------------------------------------------------- # Toolchain -# Can be changed via -DTOOLCHAIN=gcc|iar or -DCMAKE_C_COMPILER= +# Can be changed via -DTOOLCHAIN=gcc|iar or -DCMAKE_C_COMPILER= or ENV{CC}= #------------------------------------------------------------- -# Detect toolchain based on CMAKE_C_COMPILER -if (DEFINED CMAKE_C_COMPILER) - string(FIND ${CMAKE_C_COMPILER} "iccarm" IS_IAR) - string(FIND ${CMAKE_C_COMPILER} "clang" IS_CLANG) - string(FIND ${CMAKE_C_COMPILER} "gcc" IS_GCC) +function(detect_compiler COMPILER_PATH RESULT) + string(FIND ${COMPILER_PATH} "iccarm" IS_IAR) + string(FIND ${COMPILER_PATH} "clang" IS_CLANG) + string(FIND ${COMPILER_PATH} "gcc" IS_GCC) if (NOT IS_IAR EQUAL -1) - set(TOOLCHAIN iar) + set(${RESULT} iar PARENT_SCOPE) elseif (NOT IS_CLANG EQUAL -1) - set(TOOLCHAIN clang) + set(${RESULT} clang PARENT_SCOPE) elseif (NOT IS_GCC EQUAL -1) - set(TOOLCHAIN gcc) + set(${RESULT} gcc PARENT_SCOPE) endif () +endfunction() + +# Detect toolchain based on CMAKE_C_COMPILER or ENV{CC} +if (DEFINED CMAKE_C_COMPILER) + detect_compiler(${CMAKE_C_COMPILER} TOOLCHAIN) +elseif (DEFINED ENV{CC}) + detect_compiler($ENV{CC} TOOLCHAIN) endif () if (NOT DEFINED TOOLCHAIN) set(TOOLCHAIN gcc) endif () +set(WARN_FLAGS_GNU + -Wall + -Wextra + -Werror + -Wfatal-errors + -Wdouble-promotion + -Wstrict-prototypes + -Wstrict-overflow + -Werror-implicit-function-declaration + -Wfloat-equal + -Wundef + -Wshadow + -Wwrite-strings + -Wsign-compare + -Wmissing-format-attribute + -Wunreachable-code + -Wcast-align + -Wcast-function-type + -Wcast-qual + -Wnull-dereference + -Wuninitialized + -Wunused + -Wunused-function + -Wreturn-type + -Wredundant-decls + -Wmissing-prototypes +# -Wconversion + ) +set(WARN_FLAGS_Clang ${WARN_FLAGS_GNU}) + # Optimization if (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Build type" FORCE) @@ -47,21 +112,8 @@ endif () # FAMILY and BOARD #------------------------------------------------------------- if (NOT DEFINED FAMILY) - if (NOT DEFINED BOARD) - message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, espressif). - You can do this via -DFAMILY=xxx on the cmake command line") - endif () + family_resolve_board("${BOARD}" BOARD_PATH) - # Find path contains BOARD - file(GLOB BOARD_PATH LIST_DIRECTORIES true - RELATIVE ${TOP}/hw/bsp - ${TOP}/hw/bsp/*/boards/${BOARD} - ) - if (NOT BOARD_PATH) - message(FATAL_ERROR "Could not detect FAMILY from BOARD=${BOARD}") - endif () - - # replace / with ; so that we can get the first element as FAMILY string(REPLACE "/" ";" BOARD_PATH ${BOARD_PATH}) list(GET BOARD_PATH 0 FAMILY) set(FAMILY ${FAMILY} CACHE STRING "Board family") @@ -86,12 +138,21 @@ if (NOT NO_WARN_RWX_SEGMENTS_SUPPORTED) endif() #---------------------------------- -# Zephyr +# RTOS #---------------------------------- +if (NOT DEFINED RTOS) + set(RTOS noos CACHE STRING "RTOS") +endif () + if (RTOS STREQUAL zephyr) set(BOARD_ROOT ${TOP}/hw/bsp/${FAMILY}) set(ZEPHYR_BOARD_ALIASES ${CMAKE_CURRENT_LIST_DIR}/zephyr_board_aliases.cmake) find_package(Zephyr REQUIRED HINTS ${TOP}/zephyr) + list(REMOVE_ITEM WARN_FLAGS_GNU + -Wredundant-decls + -Wundef + -Wcast-align + ) endif () #------------------------------------------------------------- @@ -166,6 +227,9 @@ endfunction() # Common Target Configure # Most families use these settings except rp2040 and espressif #------------------------------------------------------------- +function(family_add_board BOARD_TARGET) + # empty function, should be redefined in FAMILY/family.cmake +endfunction() # Add RTOS to example function(family_add_rtos TARGET RTOS) @@ -191,6 +255,22 @@ endfunction() # Add common configuration to example function(family_configure_common TARGET RTOS) + # Add board target + set(BOARD_TARGET board_${BOARD}) + if (NOT RTOS STREQUAL zephyr) + if (NOT TARGET ${BOARD_TARGET}) + family_add_board(${BOARD_TARGET}) + set_target_properties(${BOARD_TARGET} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib + SKIP_LINTING ON # need cmake 4.2 + ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_target_properties(${BOARD_TARGET} PROPERTIES COMPILE_OPTIONS -w) + endif () + endif () + target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET}) + endif () + family_add_rtos(${TARGET} ${RTOS}) # Add BOARD_${BOARD} define @@ -220,39 +300,14 @@ function(family_configure_common TARGET RTOS) target_sources(${TARGET} PUBLIC ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c) target_include_directories(${TARGET} PUBLIC ${TOP}/lib/SEGGER_RTT/RTT) # target_compile_definitions(${TARGET} PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) + set_source_files_properties(${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c PROPERTIES SKIP_LINTING ON) endif () else () target_compile_definitions(${TARGET} PUBLIC LOGGER_UART) endif () if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_compile_options(${TARGET} PRIVATE - -Wall - -Wextra - #-Werror - -Wfatal-errors - -Wdouble-promotion - -Wstrict-prototypes - -Wstrict-overflow - -Werror-implicit-function-declaration - -Wfloat-equal - -Wundef - -Wshadow - -Wwrite-strings - -Wsign-compare - -Wmissing-format-attribute - -Wunreachable-code - -Wcast-align - -Wcast-function-type - -Wcast-qual - -Wnull-dereference - -Wuninitialized - -Wunused - -Wunused-function - -Wreturn-type - -Wredundant-decls - -Wmissing-prototypes - ) + target_compile_options(${TARGET} PRIVATE ${WARN_FLAGS_${CMAKE_C_COMPILER_ID}}) target_link_options(${TARGET} PUBLIC "LINKER:-Map=$<TARGET_FILE:${TARGET}>.map") if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND NO_WARN_RWX_SEGMENTS_SUPPORTED AND (NOT RTOS STREQUAL zephyr)) @@ -260,6 +315,21 @@ function(family_configure_common TARGET RTOS) endif () elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${TARGET} PUBLIC "LINKER:--map=$<TARGET_FILE:${TARGET}>.map") + + if (IAR_CSTAT) + # link time analysis with C-STAT + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND ${CMAKE_C_ICSTAT} + --db=${CMAKE_BINARY_DIR}/cstat.db + link_analyze -- ${CMAKE_LINKER} $<TARGET_OBJECTS:${TARGET}> + COMMAND_EXPAND_LISTS + ) + # generate C-STAT report + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/cstat_report + COMMAND ireport --db=${CMAKE_BINARY_DIR}/cstat.db --full --project ${TARGET} --output ${CMAKE_CURRENT_BINARY_DIR}/cstat_report/index.html + ) + endif () endif () # run size after build @@ -273,8 +343,8 @@ endfunction() # Add tinyusb to target function(family_add_tinyusb TARGET OPT_MCU) - # tinyusb's CMakeList.txt - add_subdirectory(${TOP}/src ${CMAKE_CURRENT_BINARY_DIR}/tinyusb) + # tinyusb's CMakeLists.txt + include(${TOP}/src/CMakeLists.txt) # Add TinyUSB sources, include and common define tinyusb_target_add(${TARGET}) @@ -347,56 +417,6 @@ function(family_example_missing_dependency TARGET DEPENDENCY) endfunction() #---------------------------------- -# RPI specific: refactor later -#---------------------------------- -function(family_add_default_example_warnings TARGET) - target_compile_options(${TARGET} PUBLIC - -Wall - -Wextra - -Werror - -Wfatal-errors - -Wdouble-promotion - -Wfloat-equal - # FIXME commented out because of https://github.com/raspberrypi/pico-sdk/issues/1468 - #-Wshadow - -Wwrite-strings - -Wsign-compare - -Wmissing-format-attribute - -Wunreachable-code - -Wcast-align - -Wcast-qual - -Wnull-dereference - -Wuninitialized - -Wunused - -Wredundant-decls - #-Wstrict-prototypes - #-Werror-implicit-function-declaration - #-Wundef - ) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND NO_WARN_RWX_SEGMENTS_SUPPORTED) - target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments") - endif() - - # GCC 10 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0) - target_compile_options(${TARGET} PUBLIC -Wconversion) - endif() - - # GCC 8 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) - target_compile_options(${TARGET} PUBLIC -Wcast-function-type -Wstrict-overflow) - endif() - - # GCC 6 - if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) - target_compile_options(${TARGET} PUBLIC -Wno-strict-aliasing) - endif() - endif() -endfunction() - -#---------------------------------- # Flashing target #---------------------------------- @@ -532,6 +552,18 @@ function(family_flash_openocd_adi TARGET) family_flash_openocd(${TARGET}) endfunction() +# Add flash openocd-nuvoton target +# compiled from https://github.com/OpenNuvoton/OpenOCD-Nuvoton +function(family_flash_openocd_nuvoton TARGET) + if (NOT DEFINED OPENOCD) + set(OPENOCD $ENV{HOME}/app/OpenOCD-Nuvoton/src/openocd) + set(OPENOCD_OPTION2 "-s $ENV{HOME}/app/OpenOCD-Nuvoton/tcl") + endif () + + family_flash_openocd(${TARGET}) +endfunction() + + # Add flash with https://github.com/ch32-rs/wlink function(family_flash_wlink_rs TARGET) if (NOT DEFINED WLINK_RS) diff --git a/examples/build_system/make/make.mk b/hw/bsp/family_support.mk index f70748d34..db410a657 100644 --- a/examples/build_system/make/make.mk +++ b/hw/bsp/family_support.mk @@ -22,21 +22,19 @@ ifndef TOOLCHAIN TOOLCHAIN = gcc endif -#-------------- TOP and CURRENT_PATH ------------ +#-------------- TOP and EXAMPLE_PATH ------------ # Set TOP to be the path to get from the current directory (where make was invoked) to the top of the tree. # $(lastword $(MAKEFILE_LIST)) returns the name of this makefile relative to where make was invoked. THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -# strip off /examples/build_system/make to get for example ../../.. -# and Set TOP to an absolute path -TOP = $(abspath $(subst make.mk,../../..,$(THIS_MAKEFILE))) +# Set TOP to an absolute path +TOP = $(abspath $(subst family_support.mk,../..,$(THIS_MAKEFILE))) -# Set CURRENT_PATH to the relative path from TOP to the current directory, ie examples/device/cdc_msc_freertos -CURRENT_PATH = $(subst $(TOP)/,,$(abspath .)) +# Set EXAMPLE_PATH to the relative path from TOP to the current directory, ie examples/device/cdc_msc +EXAMPLE_PATH = $(subst $(TOP)/,,$(abspath .)) #-------------- Linux/Windows ------------ - # Detect whether shell style is windows or not # https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069 ifeq '$(findstring ;,$(PATH))' ';' @@ -60,42 +58,26 @@ else PYTHON = python3 endif - # Build directory BUILD := _build/$(BOARD) PROJECT := $(notdir $(CURDIR)) -BIN := $(TOP)/_bin/$(BOARD)/$(notdir $(CURDIR)) #------------------------------------------------------------- -# Board / Family +# Family and Board #------------------------------------------------------------- - -# Board without family -ifneq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/board.mk),) - BOARD_PATH := hw/bsp/$(BOARD) - FAMILY := -endif - -# Board within family -ifeq ($(BOARD_PATH),) - BOARD_PATH := $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD))) - FAMILY := $(word 3, $(subst /, ,$(BOARD_PATH))) - FAMILY_PATH = hw/bsp/$(FAMILY) -endif +BOARD_PATH := $(subst $(TOP)/,,$(wildcard $(TOP)/hw/bsp/*/boards/$(BOARD))) +FAMILY := $(word 3, $(subst /, ,$(BOARD_PATH))) +FAMILY_PATH = hw/bsp/$(FAMILY) ifeq ($(BOARD_PATH),) $(info You must provide a BOARD parameter with 'BOARD=') $(error Invalid BOARD specified) endif -ifeq ($(FAMILY),) - include $(TOP)/hw/bsp/$(BOARD)/board.mk -else - # Include Family and Board specific defs - include $(TOP)/$(FAMILY_PATH)/family.mk - SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) -endif +# Include Family and Board specific defs +include $(TOP)/$(FAMILY_PATH)/family.mk +SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) #------------------------------------------------------------- # Source files and compiler flags @@ -111,6 +93,7 @@ SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(BOARD_PATH)/*.c)) INC += \ $(TOP)/$(FAMILY_PATH) \ $(TOP)/src \ + $(TOP)/hw \ BOARD_UPPER = $(call to_upper,$(BOARD)) CFLAGS += -DBOARD_$(BOARD_UPPER) @@ -134,8 +117,8 @@ endif ifeq ($(LOGGER),rtt) CFLAGS += -DLOGGER_RTT #CFLAGS += -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL - INC += $(TOP)/$(lib/SEGGER_RTT)/RTT - SRC_C += $(lib/SEGGER_RTT)/RTT/SEGGER_RTT.c + INC += $(TOP)/lib/SEGGER_RTT/RTT + SRC_C += lib/SEGGER_RTT/RTT/SEGGER_RTT.c endif ifeq ($(LOGGER),swo) CFLAGS += -DLOGGER_SWO diff --git a/hw/bsp/fomu/family.c b/hw/bsp/fomu/family.c index 61943cb01..9d7977bea 100644 --- a/hw/bsp/fomu/family.c +++ b/hw/bsp/fomu/family.c @@ -38,7 +38,6 @@ //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ - void fomu_error(uint32_t line) { (void)line; diff --git a/hw/bsp/fomu/family.cmake b/hw/bsp/fomu/family.cmake index 639373695..ac3c0c446 100644 --- a/hw/bsp/fomu/family.cmake +++ b/hw/bsp/fomu/family.cmake @@ -10,80 +10,68 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TO set(FAMILY_MCUS VALENTYUSB_EPTRI CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/fomu.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/crt0-vexriscv.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/fomu.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/crt0-vexriscv.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} INTERFACE) + target_include_directories(${BOARD_TARGET} INTERFACE ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/include ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for MSP432E4") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_VALENTYUSB_EPTRI) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/valentyusb/eptri/dcd_eptri.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_VALENTYUSB_EPTRI) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/valentyusb/eptri/dcd_eptri.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/fomu/family.mk b/hw/bsp/fomu/family.mk index 69a546964..c29b1c70f 100644 --- a/hw/bsp/fomu/family.mk +++ b/hw/bsp/fomu/family.mk @@ -27,7 +27,7 @@ FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V # flash using dfu-util $(BUILD)/$(PROJECT).dfu: $(BUILD)/$(PROJECT).bin @echo "Create $@" - python $(TOP)/hw/bsp/$(BOARD)/dfu.py -b $^ -D 0x1209:0x5bf0 $@ + python $(TOP)/$(FAMILY_PATH)/dfu.py -b $^ -D 0x1209:0x5bf0 $@ flash: $(BUILD)/$(PROJECT).dfu dfu-util -D $^ diff --git a/hw/bsp/gd32vf103/family.cmake b/hw/bsp/gd32vf103/family.cmake index a47871b38..76f520ea8 100644 --- a/hw/bsp/gd32vf103/family.cmake +++ b/hw/bsp/gd32vf103/family.cmake @@ -15,34 +15,30 @@ set(FAMILY_MCUS GD32VF103 CACHE INTERNAL "") set(JLINK_IF jtag) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - message(FATAL_ERROR "LD_FILE_GNU is not defined") - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU - ${SOC_DIR}/Common/Source/GCC/startup_gd32vf103.S - ${SOC_DIR}/Common/Source/GCC/intexc_gd32vf103.S - ) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +message(FATAL_ERROR "LD_FILE_GNU is not defined") +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU +${SOC_DIR}/Common/Source/GCC/startup_gd32vf103.S +${SOC_DIR}/Common/Source/GCC/intexc_gd32vf103.S +) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_gd32vf103.c ${SOC_DIR}/Common/Source/Drivers/gd32vf103_rcu.c ${SOC_DIR}/Common/Source/Drivers/gd32vf103_gpio.c ${SOC_DIR}/Common/Source/Drivers/Usb/gd32vf103_usb_hw.c ${SOC_DIR}/Common/Source/Drivers/gd32vf103_usart.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR}/NMSIS/Core/Include @@ -61,33 +57,17 @@ function(add_board_target BOARD_TARGET) -mcmodel=medlow -mstrict-align ) - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for MSP432E4") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_GD32VF103) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${SOC_DIR}/Common/Source/Stubs/sbrk.c @@ -96,24 +76,45 @@ function(family_configure_example TARGET RTOS) ${SOC_DIR}/Common/Source/Stubs/fstat.c ${SOC_DIR}/Common/Source/Stubs/lseek.c ${SOC_DIR}/Common/Source/Stubs/read.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_GD32VF103) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties( + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${SOC_DIR}/Common/Source/Stubs/sbrk.c + ${SOC_DIR}/Common/Source/Stubs/close.c + ${SOC_DIR}/Common/Source/Stubs/isatty.c + ${SOC_DIR}/Common/Source/Stubs/fstat.c + ${SOC_DIR}/Common/Source/Stubs/lseek.c + ${SOC_DIR}/Common/Source/Stubs/read.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index 9cd59b7d7..84b083e29 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -249,6 +249,7 @@ TU_ATTR_UNUSED void _start(void) { #ifdef __clang__ void _exit(int __status) { + (void) __status; while (1) {} } #endif diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index feec4973f..11cc00983 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -16,29 +16,25 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS MIMXRT1XXX CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # LD_FILE and STARTUP_FILE can be defined in board.cmake - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx${MCU_CORE}_flexspi_nor.ld) - set(LD_FILE_IAR ${SDK_DIR}/devices/${MCU_VARIANT}/iar/${MCU_VARIANT}xxxxx${MCU_CORE}_flexspi_nor.icf) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}xxxxx${MCU_CORE}_flexspi_nor.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED LD_FILE_IAR) +set(LD_FILE_IAR ${SDK_DIR}/devices/${MCU_VARIANT}/iar/${MCU_VARIANT}xxxxx${MCU_CORE}_flexspi_nor.icf) +endif () - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT_WITH_CORE}.S) - set(STARTUP_FILE_IAR ${SDK_DIR}/devices/${MCU_VARIANT}/iar/startup_${MCU_VARIANT_WITH_CORE}.s) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT_WITH_CORE}.S) +set(STARTUP_FILE_IAR ${SDK_DIR}/devices/${MCU_VARIANT}/iar/startup_${MCU_VARIANT_WITH_CORE}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board/clock_config.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/board/pin_mux.c ${SDK_DIR}/drivers/common/fsl_common.c @@ -60,10 +56,9 @@ function(add_board_target BOARD_TARGET) endif() endforeach() - target_compile_definitions(${BOARD_TARGET} PUBLIC __STARTUP_CLEAR_BSS - CFG_TUSB_MEM_SECTION=__attribute__\(\(section\(\"NonCacheable\"\)\)\) + [=[CFG_TUSB_MEM_SECTION=__attribute__((section("NonCacheable")))]=] ) if (NOT M4 STREQUAL "1") @@ -88,9 +83,31 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_MIMXRT1XXX) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" -nostartfiles --specs=nosys.specs --specs=nano.specs @@ -99,48 +116,23 @@ function(add_board_target BOARD_TARGET) -Wl,-ug_boot_data ) elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}" -Wl,-uimage_vector_table -Wl,-ug_boot_data ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}" ) endif () -endfunction() - - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) - - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MIMXRT1XXX) - target_sources(${TARGET} PRIVATE - ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c - ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c - ${TOP}/src/portable/ehci/ehci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/kinetis_k/family.c b/hw/bsp/kinetis_k/family.c index 59d80fa18..816c5c87e 100644 --- a/hw/bsp/kinetis_k/family.c +++ b/hw/bsp/kinetis_k/family.c @@ -159,6 +159,7 @@ TU_ATTR_UNUSED void _start(void) { #ifdef __clang__ void _exit (int __status) { + (void) __status; while (1) {} } #endif diff --git a/hw/bsp/kinetis_k/family.cmake b/hw/bsp/kinetis_k/family.cmake index ce91777c9..e1b5c221e 100644 --- a/hw/bsp/kinetis_k/family.cmake +++ b/hw/bsp/kinetis_k/family.cmake @@ -18,21 +18,17 @@ set(FAMILY_MCUS KINETIS_K CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # LD_FILE and STARTUP_FILE can be defined in board.cmake - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${SDK_DIR}/drivers/gpio/fsl_gpio.c ${SDK_DIR}/drivers/uart/fsl_uart.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c @@ -54,63 +50,53 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_KINETIS_K) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c + ${TOP}/src/portable/nxp/khci/hcd_khci.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_KINETIS_K) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c - ${TOP}/src/portable/nxp/khci/hcd_khci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) - - if (DEFINED TEENSY_MCU) - family_flash_teensy(${TARGET}) - endif () + family_flash_teensy(${TARGET}) endfunction() diff --git a/hw/bsp/kinetis_k32l2/family.c b/hw/bsp/kinetis_k32l2/family.c index 2fcc1b2af..2062b8b18 100644 --- a/hw/bsp/kinetis_k32l2/family.c +++ b/hw/bsp/kinetis_k32l2/family.c @@ -167,6 +167,7 @@ TU_ATTR_UNUSED void _start(void) { #ifdef __clang__ void _exit (int __status) { + (void) __status; while (1) {} } #endif diff --git a/hw/bsp/kinetis_k32l2/family.cmake b/hw/bsp/kinetis_k32l2/family.cmake index 946614a03..110335ab2 100644 --- a/hw/bsp/kinetis_k32l2/family.cmake +++ b/hw/bsp/kinetis_k32l2/family.cmake @@ -14,21 +14,17 @@ set(FAMILY_MCUS KINETIS_K32L CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # LD_FILE and STARTUP_FILE can be defined in board.cmake - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${SDK_DIR}/drivers/gpio/fsl_gpio.c ${SDK_DIR}/drivers/lpuart/fsl_lpuart.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c @@ -49,63 +45,53 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_KINETIS_K32L) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/khci/dcd_khci.c + ${TOP}/src/portable/nxp/khci/hcd_khci.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_KINETIS_K32L) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/khci/dcd_khci.c - ${TOP}/src/portable/nxp/khci/hcd_khci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_flash_jlink(${TARGET}) family_add_bin_hex(${TARGET}) - - if (DEFINED TEENSY_MCU) - family_flash_teensy(${TARGET}) - endif () + family_flash_teensy(${TARGET}) endfunction() diff --git a/hw/bsp/kinetis_kl/family.c b/hw/bsp/kinetis_kl/family.c index fe864f3a0..000006372 100644 --- a/hw/bsp/kinetis_kl/family.c +++ b/hw/bsp/kinetis_kl/family.c @@ -159,6 +159,7 @@ TU_ATTR_UNUSED void _start(void) { #ifdef __clang__ void _exit (int __status) { + (void) __status; while (1) {} } #endif diff --git a/hw/bsp/kinetis_kl/family.cmake b/hw/bsp/kinetis_kl/family.cmake index 51a646258..230a3057d 100644 --- a/hw/bsp/kinetis_kl/family.cmake +++ b/hw/bsp/kinetis_kl/family.cmake @@ -18,20 +18,16 @@ set(FAMILY_MCUS KINETIS_KL CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # LD_FILE and STARTUP_FILE can be defined in board.cmake - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${SDK_DIR}/drivers/gpio/fsl_gpio.c ${SDK_DIR}/drivers/lpsci/fsl_lpsci.c ${SDK_DIR}/drivers/uart/fsl_uart.c @@ -53,57 +49,50 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/drivers/uart ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_KINETIS_KL) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c + ${TOP}/src/portable/nxp/khci/hcd_khci.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_KINETIS_KL) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/chipidea/ci_fs/dcd_ci_fs.c - ${TOP}/src/portable/nxp/khci/hcd_khci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/lpc11/boards/lpcxpresso11u68/board.cmake b/hw/bsp/lpc11/boards/lpcxpresso11u68/board.cmake index b7393cb2f..36296fb54 100644 --- a/hw/bsp/lpc11/boards/lpcxpresso11u68/board.cmake +++ b/hw/bsp/lpc11/boards/lpcxpresso11u68/board.cmake @@ -5,7 +5,7 @@ set(PYOCD_TARGET LPC11U68) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/lpc11u68.ld) function(update_board TARGET) - target_sources(${TARGET} PUBLIC + target_sources(${TARGET} PRIVATE ${SDK_DIR}/src/gpio_${LPC_FAMILY}.c ${SDK_DIR}/src/syscon_${LPC_FAMILY}.c ) diff --git a/hw/bsp/lpc11/family.cmake b/hw/bsp/lpc11/family.cmake index 6781b20c6..fceafcf61 100644 --- a/hw/bsp/lpc11/family.cmake +++ b/hw/bsp/lpc11/family.cmake @@ -21,11 +21,7 @@ set(FAMILY_MCUS LPC11UXX CACHE INTERNAL "") # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/../gcc/cr_startup_lpc${LPC_FAMILY}.c ${SDK_DIR}/src/chip_${LPC_FAMILY}.c @@ -48,24 +44,7 @@ function(add_board_target BOARD_TARGET) update_board(${BOARD_TARGET}) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(${BOARD_TARGET} PUBLIC - -nostdlib - -Wno-error=incompatible-pointer-types - ) - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () + set_target_properties(${BOARD_TARGET} PROPERTIES COMPILE_FLAGS "-Wno-incompatible-pointer-types") endfunction() @@ -74,16 +53,14 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC11UXX) #---------- Port Specific ---------- # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c ) target_include_directories(${TARGET} PUBLIC # family, hw, board @@ -92,14 +69,24 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC11UXX) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${TARGET} PUBLIC + -nostdlib + -Wno-error=incompatible-pointer-types + ) + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/lpc13/family.cmake b/hw/bsp/lpc13/family.cmake index e3c0b18c7..6a66cfe95 100644 --- a/hw/bsp/lpc13/family.cmake +++ b/hw/bsp/lpc13/family.cmake @@ -18,11 +18,7 @@ set(FAMILY_MCUS LPC13XX CACHE INTERNAL "") # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/../gcc/cr_startup_lpc${LPC_FAMILY}.c ${SDK_DIR}/src/chip_${LPC_FAMILY}.c @@ -68,17 +64,18 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC13XX) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -86,15 +83,6 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC13XX) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - - # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc15/family.cmake b/hw/bsp/lpc15/family.cmake index 761c5a619..8de26421d 100644 --- a/hw/bsp/lpc15/family.cmake +++ b/hw/bsp/lpc15/family.cmake @@ -18,11 +18,7 @@ set(FAMILY_MCUS LPC15XX CACHE INTERNAL "") # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/../gcc/cr_startup_lpc${LPC_FAMILY}.c ${SDK_DIR}/src/chip_${LPC_FAMILY}.c @@ -70,17 +66,18 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC15XX) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -88,15 +85,6 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC15XX) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - - # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc17/family.c b/hw/bsp/lpc17/family.c index 7d3231f6a..1edab6cd4 100644 --- a/hw/bsp/lpc17/family.c +++ b/hw/bsp/lpc17/family.c @@ -96,7 +96,11 @@ void board_init(void) { // 0x1B // Host + Device + OTG + AHB }; - uint32_t const clk_en = CFG_TUD_ENABLED ? USBCLK_DEVCIE : USBCLK_HOST; +#if CFG_TUD_ENABLED + uint32_t const clk_en = USBCLK_DEVCIE; +#else + uint32_t const clk_en = USBCLK_HOST; +#endif LPC_USB->OTGClkCtrl = clk_en; while ((LPC_USB->OTGClkSt & clk_en) != clk_en) {} diff --git a/hw/bsp/lpc17/family.cmake b/hw/bsp/lpc17/family.cmake index 771a0f405..919b8f3bc 100644 --- a/hw/bsp/lpc17/family.cmake +++ b/hw/bsp/lpc17/family.cmake @@ -17,11 +17,7 @@ set(FAMILY_MCUS LPC175X_6X CACHE INTERNAL "") # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/../gcc/cr_startup_lpc175x_6x.c ${SDK_DIR}/src/chip_17xx_40xx.c @@ -67,17 +63,19 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC175X_6X) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/lpc17_40/dcd_lpc17_40.c + ${TOP}/src/portable/ohci/ohci.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -85,17 +83,6 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC175X_6X) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc17_40/dcd_lpc17_40.c - ${TOP}/src/portable/nxp/lpc17_40/hcd_lpc17_40.c - ${TOP}/src/portable/ohci/ohci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - - # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc17/family.mk b/hw/bsp/lpc17/family.mk index e8d707ea5..f1ed1a7d0 100644 --- a/hw/bsp/lpc17/family.mk +++ b/hw/bsp/lpc17/family.mk @@ -20,7 +20,6 @@ LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs SRC_C += \ src/portable/nxp/lpc17_40/dcd_lpc17_40.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c \ src/portable/ohci/ohci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc175x_6x.c \ $(MCU_DIR)/src/chip_17xx_40xx.c \ diff --git a/hw/bsp/lpc18/family.cmake b/hw/bsp/lpc18/family.cmake index 6af1149bf..27ee00f4c 100644 --- a/hw/bsp/lpc18/family.cmake +++ b/hw/bsp/lpc18/family.cmake @@ -17,11 +17,7 @@ set(FAMILY_MCUS LPC18XX CACHE INTERNAL "") # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/../gcc/cr_startup_lpc18xx.c ${SDK_DIR}/src/chip_18xx_43xx.c @@ -65,16 +61,14 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC18XX) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c ) target_include_directories(${TARGET} PUBLIC # family, hw, board @@ -83,17 +77,6 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC18XX) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c - ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c - ${TOP}/src/portable/ehci/ehci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - - # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc40/family.cmake b/hw/bsp/lpc40/family.cmake index 3a680eae6..01430bbb1 100644 --- a/hw/bsp/lpc40/family.cmake +++ b/hw/bsp/lpc40/family.cmake @@ -17,11 +17,7 @@ set(FAMILY_MCUS LPC40XX CACHE INTERNAL "") # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/../gcc/cr_startup_lpc40xx.c ${SDK_DIR}/src/chip_17xx_40xx.c @@ -68,17 +64,19 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC40XX) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/lpc17_40/dcd_lpc17_40.c + ${TOP}/src/portable/ohci/ohci.c ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + target_include_directories(${TARGET} PUBLIC # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -86,17 +84,6 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC40XX) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc17_40/dcd_lpc17_40.c - ${TOP}/src/portable/nxp/lpc17_40/hcd_lpc17_40.c - ${TOP}/src/portable/ohci/ohci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - - # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/lpc40/family.mk b/hw/bsp/lpc40/family.mk index c72631235..c21923000 100644 --- a/hw/bsp/lpc40/family.mk +++ b/hw/bsp/lpc40/family.mk @@ -18,7 +18,6 @@ LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs # All source paths should be relative to the top level. SRC_C += \ src/portable/nxp/lpc17_40/dcd_lpc17_40.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c \ src/portable/ohci/ohci.c \ $(MCU_DIR)/../gcc/cr_startup_lpc40xx.c \ $(MCU_DIR)/src/chip_17xx_40xx.c \ diff --git a/hw/bsp/lpc43/family.cmake b/hw/bsp/lpc43/family.cmake index 23c4aecea..878b0eecc 100644 --- a/hw/bsp/lpc43/family.cmake +++ b/hw/bsp/lpc43/family.cmake @@ -14,22 +14,18 @@ set(FAMILY_MCUS LPC43XX CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${SDK_DIR}/../gcc/cr_startup_lpc43xx.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${SDK_DIR}/../iar/iar_startup_lpc18xx43xx.s) - set(LD_FILE_IAR ${SDK_DIR}/../iar/linker/lpc18xx_43xx_ldscript_iflash.icf) +set(STARTUP_FILE_GNU ${SDK_DIR}/../gcc/cr_startup_lpc43xx.c) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${SDK_DIR}/../iar/iar_startup_lpc18xx43xx.s) +set(LD_FILE_IAR ${SDK_DIR}/../iar/linker/lpc18xx_43xx_ldscript_iflash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${SDK_DIR}/src/chip_18xx_43xx.c ${SDK_DIR}/src/clock_18xx_43xx.c ${SDK_DIR}/src/fpu_init.c @@ -50,60 +46,51 @@ function(add_board_target BOARD_TARGET) update_board(${BOARD_TARGET}) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(${BOARD_TARGET} PUBLIC - -nostdlib - -Wno-error=incompatible-pointer-types - ) - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) + # warning by LPCOpen + if (TOOLCHAIN STREQUAL "gcc" OR TOOLCHAIN STREQUAL "clang") + set_target_properties(${BOARD_TARGET} PROPERTIES COMPILE_FLAGS -Wno-error=incompatible-pointer-types) endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC43XX) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c + ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c + ${TOP}/src/portable/ehci/ehci.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC43XX) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/chipidea/ci_hs/dcd_ci_hs.c - ${TOP}/src/portable/chipidea/ci_hs/hcd_ci_hs.c - ${TOP}/src/portable/ehci/ehci.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/lpc51/family.c b/hw/bsp/lpc51/family.c index 0afe33d41..c963b76bd 100644 --- a/hw/bsp/lpc51/family.c +++ b/hw/bsp/lpc51/family.c @@ -138,6 +138,7 @@ TU_ATTR_UNUSED void _start(void) { #ifdef __clang__ void _exit (int __status) { + (void) __status; while (1) {} } #endif diff --git a/hw/bsp/lpc51/family.cmake b/hw/bsp/lpc51/family.cmake index 09d97d256..1823b64fc 100644 --- a/hw/bsp/lpc51/family.cmake +++ b/hw/bsp/lpc51/family.cmake @@ -13,26 +13,22 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS LPC51 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}_flash.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_VARIANT}_flash.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_VARIANT}.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} # driver ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c @@ -62,57 +58,49 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC51) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC51) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/lpc54/family.c b/hw/bsp/lpc54/family.c index 9b9b5841b..094866d9b 100644 --- a/hw/bsp/lpc54/family.c +++ b/hw/bsp/lpc54/family.c @@ -233,6 +233,7 @@ TU_ATTR_UNUSED void _start(void) { #ifdef __clang__ void _exit (int __status) { + (void) __status; while (1) {} } #endif diff --git a/hw/bsp/lpc54/family.cmake b/hw/bsp/lpc54/family.cmake index 66320870a..c6145bd41 100644 --- a/hw/bsp/lpc54/family.cmake +++ b/hw/bsp/lpc54/family.cmake @@ -20,26 +20,22 @@ endif() set(HOST_PORT $<NOT:${PORT}>) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} # driver ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/common/fsl_common_arm.c @@ -90,63 +86,49 @@ function(add_board_target BOARD_TARGET) endif () update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC54) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) - - # https://github.com/gsteiert/sct_neopixel/pull/1 - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - set_source_files_properties(${TOP}/lib/sct_neopixel/sct_neopixel.c PROPERTIES - COMPILE_FLAGS "-Wno-unused-parameter") - endif () - target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC54) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/lpc55/boards/double_m33_express/board.cmake b/hw/bsp/lpc55/boards/double_m33_express/board.cmake index 3324ce888..186655b5a 100644 --- a/hw/bsp/lpc55/boards/double_m33_express/board.cmake +++ b/hw/bsp/lpc55/boards/double_m33_express/board.cmake @@ -7,11 +7,6 @@ set(NXPLINK_DEVICE LPC55S69:LPCXpresso55S69) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/LPC55S69_cm33_core0_uf2.ld) -# Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) -endif() - function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC CPU_LPC55S69JBD100_cm33_core0 diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake index b3d0c3349..d935b70e6 100644 --- a/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake +++ b/hw/bsp/lpc55/boards/lpcxpresso55s28/board.cmake @@ -5,11 +5,6 @@ set(JLINK_DEVICE LPC55S28) set(PYOCD_TARGET LPC55S28) set(NXPLINK_DEVICE LPC55S28:LPCXpresso55S28) -# Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) -endif() - function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC CPU_LPC55S28JBD100 diff --git a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake index b52ec2f9d..f46775b27 100644 --- a/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake +++ b/hw/bsp/lpc55/boards/lpcxpresso55s69/board.cmake @@ -5,11 +5,6 @@ set(JLINK_DEVICE LPC55S69_M33_0) set(PYOCD_TARGET LPC55S69) set(NXPLINK_DEVICE LPC55S69:LPCXpresso55S69) -# Device port default to PORT1 Highspeed -if (NOT DEFINED PORT) - set(PORT 1) -endif() - function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC CPU_LPC55S69JBD100_cm33_core0 diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index dbf8d71b7..f1ef58926 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -55,6 +55,7 @@ #define IOCON_PIO_MODE_INACT 0x00u // No addition pin function #define IOCON_PIO_OPENDRAIN_DI 0x00u // Open drain is disabled #define IOCON_PIO_SLEW_STANDARD 0x00u // Standard mode, output slew rate control is enabled +#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ #define IOCON_PIO_DIG_FUNC0_EN (IOCON_PIO_DIGITAL_EN | IOCON_PIO_FUNC0) // Digital pin function 0 enabled #define IOCON_PIO_DIG_FUNC1_EN (IOCON_PIO_DIGITAL_EN | IOCON_PIO_FUNC1) // Digital pin function 1 enabled @@ -197,13 +198,14 @@ void board_init(void) { USART_Init(UART_DEV, &uart_config, 12000000); #endif - // USB VBUS +#if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 0) /* PORT0 PIN22 configured as USB0_VBUS */ IOCON_PinMuxSet(IOCON, 0U, 22U, IOCON_PIO_DIG_FUNC7_EN); - -#if defined(BOARD_TUD_RHPORT) && BOARD_TUD_RHPORT == 0 // Port0 is Full Speed + NVIC_ClearPendingIRQ(USB0_IRQn); + NVIC_ClearPendingIRQ(USB0_NEEDCLK_IRQn); + /* Turn on USB0 Phy */ POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); @@ -212,21 +214,55 @@ void board_init(void) { RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn); RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn); - // Enable USB Clock Adjustments to trim the FRO for the full speed controller - ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK; - CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); - CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); + if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0) { + // Enable USB Clock Adjustments to trim the FRO for the full speed controller + ANACTRL->FRO192M_CTRL |= ANACTRL_FRO192M_CTRL_USBCLKADJ_MASK; + CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false); + CLOCK_AttachClk(kFRO_HF_to_USB0_CLK); + + /*According to reference manual, device mode setting has to be set by access usb host register */ + CLOCK_EnableClock(kCLOCK_Usbhsl0); // enable usb0 host clock + USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; + CLOCK_DisableClock(kCLOCK_Usbhsl0); // disable usb0 host clock + /* enable USB Device clock */ + CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); + } else { + const uint32_t port1_pin12_config = (/* Pin is configured as USB0_PORTPWRN */ + IOCON_PIO_FUNC4 | + /* Selects pull-up function */ + IOCON_PIO_MODE_PULLUP | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT1 PIN12 (coords: 67) is configured as USB0_PORTPWRN */ + IOCON_PinMuxSet(IOCON, 1U, 12U, port1_pin12_config); - /*According to reference manual, device mode setting has to be set by access usb host register */ - CLOCK_EnableClock(kCLOCK_Usbhsl0); // enable usb0 host clock - USBFSH->PORTMODE |= USBFSH_PORTMODE_DEV_ENABLE_MASK; - CLOCK_DisableClock(kCLOCK_Usbhsl0); // disable usb0 host clock + const uint32_t port0_pin28_config = (/* Pin is configured as USB0_OVERCURRENTN */ + IOCON_PIO_FUNC7 | + /* Selects pull-up function */ + IOCON_PIO_MODE_PULLUP | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT0 PIN28 (coords: 66) is configured as USB0_OVERCURRENTN */ + IOCON_PinMuxSet(IOCON, 0U, 28U, port0_pin28_config); - /* enable USB Device clock */ - CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFreq(kCLOCK_FroHf)); + CLOCK_EnableUsbfs0HostClock(kCLOCK_UsbfsSrcPll1, 48000000U); + USBFSH->PORTMODE &= ~USBFSH_PORTMODE_DEV_ENABLE_MASK; + } #endif -#if defined(BOARD_TUD_RHPORT) && BOARD_TUD_RHPORT == 1 +#if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 1) // Port1 is High Speed /* Turn on USB1 Phy */ @@ -266,9 +302,9 @@ void board_init(void) { // phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06); // USBPHY->TX = phytx; - ARM_MPU_SetMemAttr(0, 0x44); // Normal memory, non-cacheable (inner and outer) - ARM_MPU_SetRegion(0, ARM_MPU_RBAR(0x40100000, ARM_MPU_SH_NON, 0, 1, 1), ARM_MPU_RLAR(0x40104000, 0)); - ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); + ARM_MPU_SetMemAttr(0, 0x44); // Normal memory, non-cacheable (inner and outer) + ARM_MPU_SetRegion(0, ARM_MPU_RBAR(0x40100000, ARM_MPU_SH_NON, 0, 1, 1), ARM_MPU_RLAR(0x40104000, 0)); + ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); #endif } @@ -333,6 +369,7 @@ TU_ATTR_UNUSED void _start(void) { #ifdef __clang__ void _exit (int __status) { + (void) __status; while (1) {} } #endif diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index a89548635..1f18f9bad 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -12,34 +12,48 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS LPC55 CACHE INTERNAL "") -if (NOT DEFINED PORT) - set(PORT 0) -endif() +# ---------------------- +# Port & Speed Selection +# ---------------------- -# Host port will be the other port if available -set(HOST_PORT $<NOT:${PORT}>) +# default device port to USB1 highspeed, host to USB0 fullspeed +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif () +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 0) +endif () + +# port 0 is fullspeed, port 1 is highspeed +set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) + +if (NOT DEFINED RHPORT_DEVICE_SPEED) + list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) +endif () +if (NOT DEFINED RHPORT_HOST_SPEED) + list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) +endif () + +cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() +if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} # driver ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/common/fsl_common_arm.c @@ -67,86 +81,73 @@ function(add_board_target BOARD_TARGET) ) target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\) - BOARD_TUD_RHPORT=${PORT} - BOARD_TUH_RHPORT=${HOST_PORT} + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} + BOARD_TUH_RHPORT=${RHPORT_HOST} + BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} __STARTUP_CLEAR_BSS ) # Port 0 is Fullspeed, Port 1 is Highspeed. Port1 controller can only access USB_SRAM - if (PORT EQUAL 1) + if (RHPORT_DEVICE EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) ) - else () + elseif (RHPORT_HOST EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED CFG_TUH_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) ) endif () update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_LPC55) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - # external driver ${TOP}/lib/sct_neopixel/sct_neopixel.c + ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c + ${TOP}/src/portable/ohci/ohci.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) - - # https://github.com/gsteiert/sct_neopixel/pull/1 - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - set_source_files_properties(${TOP}/lib/sct_neopixel/sct_neopixel.c PROPERTIES - COMPILE_FLAGS "-Wno-unused-parameter") - endif () - target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_LPC55) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + set_source_files_properties(${TOP}/lib/sct_neopixel/sct_neopixel.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-unused-parameter") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/maxim/family.c b/hw/bsp/maxim/family.c index 0ef6b8c4d..92b5adb6d 100644 --- a/hw/bsp/maxim/family.c +++ b/hw/bsp/maxim/family.c @@ -31,6 +31,7 @@ #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstrict-prototypes" // _mxc_crit_get_state() +#pragma GCC diagnostic ignored "-Wredundant-decls" #endif #include "gpio.h" @@ -154,6 +155,7 @@ uint32_t board_button_read(void) { size_t board_get_unique_id(uint8_t id[], size_t max_len) { #if defined(MAX32650) // USN is 13 bytes on this device + (void) max_len; MXC_SYS_GetUSN(id, 13); return 13; #else diff --git a/hw/bsp/maxim/family.cmake b/hw/bsp/maxim/family.cmake index 75daec753..d890113e6 100644 --- a/hw/bsp/maxim/family.cmake +++ b/hw/bsp/maxim/family.cmake @@ -38,26 +38,21 @@ else() endif() #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/GCC/startup_${MAX_DEVICE}.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MAX_DEVICE}.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/GCC/startup_${MAX_DEVICE}.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${MAX_DEVICE}.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) # Common add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/heap.c ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/system_${MAX_DEVICE}.c ${MSDK_LIB}/PeriphDrivers/Source/SYS/mxc_assert.c @@ -139,53 +134,51 @@ function(add_board_target BOARD_TARGET) -Wno-error=strict-prototypes ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${MAX_DEVICE_UPPER}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/mentor/musb/dcd_musb.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${MAX_DEVICE_UPPER}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mentor/musb/dcd_musb.c - ) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + # warnings caused by MSDK headers + target_compile_options(${TARGET} PRIVATE -Wno-error=strict-prototypes) + if (${MAX_DEVICE} STREQUAL "max78002") + target_compile_options(${TARGET} PRIVATE -Wno-error=redundant-decls) + endif () + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake b/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake index 7cd8991e6..e6619992f 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.cmake @@ -14,8 +14,11 @@ function(update_board TARGET) BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED CFG_EXAMPLE_VIDEO_READONLY ) - target_sources(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clock_config.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/pin_mux.c + target_sources(${TARGET} PRIVATE + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/board/clock_config.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/board/pin_mux.c + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/board ) endfunction() diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.mk b/hw/bsp/mcx/boards/frdm_mcxa153/board.mk index af8416d8e..34558b43e 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.mk +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.mk @@ -6,6 +6,14 @@ CPU_CORE = cortex-m33-nodsp-nofp CFLAGS += \ -DCPU_MCXA153VLH \ -DCFG_TUSB_MCU=OPT_MCU_MCXA15 \ + -DCFG_EXAMPLE_VIDEO_READONLY + +SRC_C += \ + ${BOARD_PATH}/board/clock_config.c \ + ${BOARD_PATH}/board/pin_mux.c + +INC += \ + $(TOP)/$(BOARD_PATH)/board JLINK_DEVICE = MCXA153 PYOCD_TARGET = MCXA153 diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.c index 5a132dc67..599110d7a 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2025 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -25,11 +25,12 @@ /* clang-format off */ /* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!GlobalInfo -product: Clocks v12.0 +product: Clocks v18.0 processor: MCXA153 package_id: MCXA153VLH mcu_data: ksdk2_0 -processor_version: 0.13.0 +processor_version: 25.09.10 +board: FRDM-MCXA153 * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ /* clang-format on */ @@ -45,13 +46,14 @@ processor_version: 0.13.0 * Variables ******************************************************************************/ /* System clock frequency. */ -//extern uint32_t SystemCoreClock; +extern uint32_t SystemCoreClock; /******************************************************************************* ************************ BOARD_InitBootClocks function ************************ ******************************************************************************/ void BOARD_InitBootClocks(void) { + BOARD_BootClockFRO96M(); } /******************************************************************************* @@ -68,9 +70,13 @@ outputs: - {id: MAIN_clock.outFreq, value: 12 MHz} - {id: Slow_clock.outFreq, value: 3 MHz} - {id: System_clock.outFreq, value: 12 MHz} +- {id: TRACE_clock.outFreq, value: 12 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_clock.outFreq, value: 1 MHz} settings: - {id: SCGMode, value: SIRC} -- {id: FRO_HF_PERIPHERALS_EN_CFG, value: Disabled} +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} - {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} - {id: SCG.SCSSEL.sel, value: SCG.SIRC} - {id: SCG_FIRCCSR_FIRCEN_CFG, value: Disabled} @@ -106,6 +112,9 @@ void BOARD_BootClockFRO12M(void) (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); } + + /*!< Set up system dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO12M */ @@ -125,9 +134,11 @@ void BOARD_BootClockFRO12M(void) } /*!< Set up clock selectors - Attach clocks to the peripheries */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ /*!< Set up dividers */ - CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV divider to value 1 */ /* Set SystemCoreClock variable */ SystemCoreClock = BOARD_BOOTCLOCKFRO12M_CORE_CLOCK; @@ -149,9 +160,14 @@ outputs: - {id: MAIN_clock.outFreq, value: 48 MHz} - {id: Slow_clock.outFreq, value: 6 MHz} - {id: System_clock.outFreq, value: 24 MHz} +- {id: TRACE_clock.outFreq, value: 24 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_clock.outFreq, value: 1 MHz} settings: +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} - {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} -- {id: SYSCON.AHBCLKDIV.scale, value: '2', locked: true} +- {id: SYSCON.AHBCLKDIV.scale, value: '2'} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ /* clang-format on */ @@ -184,6 +200,11 @@ void BOARD_BootClockFRO24M(void) (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); } + + /*!< Set up system dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 2U); /* !< Set AHBCLKDIV divider to value 2 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ @@ -205,10 +226,21 @@ void BOARD_BootClockFRO24M(void) } /*!< Set up clock selectors - Attach clocks to the peripheries */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ /*!< Set up dividers */ - CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 2U); /* !< Set AHBCLKDIV divider to value 2 */ - CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV divider to value 1 */ /* Set SystemCoreClock variable */ SystemCoreClock = BOARD_BOOTCLOCKFRO24M_CORE_CLOCK; @@ -230,7 +262,12 @@ outputs: - {id: MAIN_clock.outFreq, value: 48 MHz} - {id: Slow_clock.outFreq, value: 12 MHz} - {id: System_clock.outFreq, value: 48 MHz} +- {id: TRACE_clock.outFreq, value: 48 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_clock.outFreq, value: 1 MHz} settings: +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} - {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ /* clang-format on */ @@ -264,6 +301,11 @@ void BOARD_BootClockFRO48M(void) (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); } + + /*!< Set up system dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ @@ -285,10 +327,21 @@ void BOARD_BootClockFRO48M(void) } /*!< Set up clock selectors - Attach clocks to the peripheries */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ /*!< Set up dividers */ - CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ - CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV divider to value 1 */ /* Set SystemCoreClock variable */ SystemCoreClock = BOARD_BOOTCLOCKFRO48M_CORE_CLOCK; @@ -310,8 +363,13 @@ outputs: - {id: MAIN_clock.outFreq, value: 64 MHz} - {id: Slow_clock.outFreq, value: 16 MHz} - {id: System_clock.outFreq, value: 64 MHz} +- {id: TRACE_clock.outFreq, value: 64 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_clock.outFreq, value: 1 MHz} settings: - {id: VDD_CORE, value: voltage_1v1} +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} - {id: MRCC.FROHFDIV.scale, value: '1', locked: true} - {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} - {id: SYSCON.AHBCLKDIV.scale, value: '1', locked: true} @@ -349,6 +407,11 @@ void BOARD_BootClockFRO64M(void) (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); } + + /*!< Set up system dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetupFROHFClocking(64000000U); /*!< Enable FRO HF(64MHz) output */ CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ @@ -370,10 +433,21 @@ void BOARD_BootClockFRO64M(void) } /*!< Set up clock selectors - Attach clocks to the peripheries */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ /*!< Set up dividers */ - CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ - CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV divider to value 1 */ /* Set SystemCoreClock variable */ SystemCoreClock = BOARD_BOOTCLOCKFRO64M_CORE_CLOCK; @@ -385,6 +459,7 @@ void BOARD_BootClockFRO64M(void) /* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!Configuration name: BOARD_BootClockFRO96M +called_from_default_init: true outputs: - {id: CLK_1M_clock.outFreq, value: 1 MHz} - {id: CLK_48M_clock.outFreq, value: 48 MHz} @@ -395,12 +470,14 @@ outputs: - {id: MAIN_clock.outFreq, value: 96 MHz} - {id: Slow_clock.outFreq, value: 24 MHz} - {id: System_clock.outFreq, value: 96 MHz} +- {id: TRACE_clock.outFreq, value: 96 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +- {id: WWDT0_clock.outFreq, value: 1 MHz} settings: - {id: VDD_CORE, value: voltage_1v1} -- {id: CLKOUTDIV_HALT, value: Enable} -- {id: MRCC.FROHFDIV.scale, value: '1', locked: true} +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} - {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} -- {id: SYSCON.AHBCLKDIV.scale, value: '1', locked: true} sources: - {id: SCG.FIRC.outFreq, value: 96 MHz} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ @@ -435,6 +512,11 @@ void BOARD_BootClockFRO96M(void) (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); } + + /*!< Set up system dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetupFROHFClocking(96000000U); /*!< Enable FRO HF(96MHz) output */ CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ @@ -456,10 +538,21 @@ void BOARD_BootClockFRO96M(void) } /*!< Set up clock selectors - Attach clocks to the peripheries */ + CLOCK_AttachClk(kCPU_CLK_to_TRACE); /* !< Switch TRACE to CPU_CLK */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI0); /* !< Switch LPSPI0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPSPI1); /* !< Switch LPSPI1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPI2C0); /* !< Switch LPI2C0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART0); /* !< Switch LPUART0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART1); /* !< Switch LPUART1 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPUART2); /* !< Switch LPUART2 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_LPTMR0); /* !< Switch LPTMR0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_I3C0FCLK); /* !< Switch I3C0FCLK to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP0); /* !< Switch CMP0 to FRO_HF_DIV */ + CLOCK_AttachClk(kFRO_HF_DIV_to_CMP1); /* !< Switch CMP1 to FRO_HF_DIV */ /*!< Set up dividers */ - CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ - CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivTRACE, 1U); /* !< Set TRACECLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivWWDT0, 1U); /* !< Set WWDT0CLKDIV divider to value 1 */ /* Set SystemCoreClock variable */ SystemCoreClock = BOARD_BOOTCLOCKFRO96M_CORE_CLOCK; diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.h new file mode 100644 index 000000000..d609eb468 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/clock_config.h @@ -0,0 +1,385 @@ +/* + * Copyright 2025 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _CLOCK_CONFIG_H_ +#define _CLOCK_CONFIG_H_ + +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes default configuration of clocks. + * + */ +void BOARD_InitBootClocks(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO12M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO12M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO12M_CORE_CLOCK 12000000U /*!< Core clock frequency: 12000000Hz */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO12M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO12M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO12M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO12M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO12M_CLK_48M_CLOCK 0UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO12M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO12M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO12M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO12M_CPU_CLOCK 12000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO12M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO12M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO12M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO12M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO12M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_FRO_HF_DIV_CLOCK 0UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_FRO_HF_CLOCK 0UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO12M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO12M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO12M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO12M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO12M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO12M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO12M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO12M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO12M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO12M_MAIN_CLOCK 12000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO12M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO12M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_SLOW_CLOCK 3000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO12M_SYSTEM_CLOCK 12000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO12M_TRACE_CLOCK 12000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO12M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO12M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO12M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO12M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO12M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO12M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO24M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO24M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO24M_CORE_CLOCK 24000000U /*!< Core clock frequency: 24000000Hz */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO24M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO24M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO24M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO24M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO24M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO24M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO24M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO24M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO24M_CPU_CLOCK 24000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO24M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO24M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO24M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO24M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO24M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_FRO_HF_DIV_CLOCK 48000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_FRO_HF_CLOCK 48000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO24M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO24M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO24M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO24M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO24M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO24M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO24M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO24M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO24M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO24M_MAIN_CLOCK 48000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO24M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO24M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_SLOW_CLOCK 6000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO24M_SYSTEM_CLOCK 24000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO24M_TRACE_CLOCK 24000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO24M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO24M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO24M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO24M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO24M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO24M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO48M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO48M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO48M_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO48M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO48M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO48M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO48M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO48M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO48M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO48M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO48M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO48M_CPU_CLOCK 48000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO48M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO48M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO48M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO48M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO48M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_FRO_HF_DIV_CLOCK 48000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_FRO_HF_CLOCK 48000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO48M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO48M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO48M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO48M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO48M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO48M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO48M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO48M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO48M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO48M_MAIN_CLOCK 48000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO48M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO48M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_SLOW_CLOCK 12000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO48M_SYSTEM_CLOCK 48000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO48M_TRACE_CLOCK 48000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO48M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO48M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO48M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO48M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO48M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO48M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO64M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO64M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO64M_CORE_CLOCK 64000000U /*!< Core clock frequency: 64000000Hz */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO64M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO64M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO64M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO64M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO64M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO64M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO64M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO64M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO64M_CPU_CLOCK 64000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO64M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO64M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO64M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO64M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO64M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_FRO_HF_DIV_CLOCK 64000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_FRO_HF_CLOCK 64000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO64M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO64M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO64M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO64M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO64M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO64M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO64M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO64M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO64M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO64M_MAIN_CLOCK 64000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO64M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO64M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_SLOW_CLOCK 16000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO64M_SYSTEM_CLOCK 64000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO64M_TRACE_CLOCK 64000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO64M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO64M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO64M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO64M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO64M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO64M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO96M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO96M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO96M_CORE_CLOCK 96000000U /*!< Core clock frequency: 96000000Hz */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKFRO96M_ADC0_CLOCK 0UL /* Clock consumers of ADC0_clock output : ADC0 */ +#define BOARD_BOOTCLOCKFRO96M_CLK16K_0_CLOCK 0UL /* Clock consumers of CLK16K_0_clock output : CMP0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO96M_CLK16K_1_CLOCK 0UL /* Clock consumers of CLK16K_1_clock output : CMP1, LPTMR0, WAKETIMER0 */ +#define BOARD_BOOTCLOCKFRO96M_CLKOUT_CLOCK 0UL /* Clock consumers of CLKOUT_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CLK_1M_CLOCK 1000000UL /* Clock consumers of CLK_1M_clock output : CMC */ +#define BOARD_BOOTCLOCKFRO96M_CLK_48M_CLOCK 48000000UL /* Clock consumers of CLK_48M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CLK_IN_CLOCK 0UL /* Clock consumers of CLK_IN_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CMP0FDIV_CLOCK 0UL /* Clock consumers of CMP0FDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO96M_CMP0RRDIV_CLOCK 0UL /* Clock consumers of CMP0RRDIV_clock output : CMP0 */ +#define BOARD_BOOTCLOCKFRO96M_CMP1FDIV_CLOCK 0UL /* Clock consumers of CMP1FDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO96M_CMP1RRDIV_CLOCK 0UL /* Clock consumers of CMP1RRDIV_clock output : CMP1 */ +#define BOARD_BOOTCLOCKFRO96M_CPU_CLOCK 96000000UL /* Clock consumers of CPU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_CTIMER0_CLOCK 0UL /* Clock consumers of CTIMER0_clock output : CTIMER0 */ +#define BOARD_BOOTCLOCKFRO96M_CTIMER1_CLOCK 0UL /* Clock consumers of CTIMER1_clock output : CTIMER1 */ +#define BOARD_BOOTCLOCKFRO96M_CTIMER2_CLOCK 0UL /* Clock consumers of CTIMER2_clock output : CTIMER2 */ +#define BOARD_BOOTCLOCKFRO96M_FREQME_REFERENCE_CLOCK 0UL /* Clock consumers of FREQME_reference_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO96M_FREQME_TARGET_CLOCK 0UL /* Clock consumers of FREQME_target_clock output : FREQME0 */ +#define BOARD_BOOTCLOCKFRO96M_FRO_12M_CLOCK 12000000UL /* Clock consumers of FRO_12M_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_FRO_HF_DIV_CLOCK 96000000UL /* Clock consumers of FRO_HF_DIV_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_FRO_HF_CLOCK 96000000UL /* Clock consumers of FRO_HF_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_I3C_FCLK_CLOCK 0UL /* Clock consumers of I3C_FCLK_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO96M_I3C_SLOW_TC_CLOCK 0UL /* Clock consumers of I3C_SLOW_TC_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO96M_I3C_SLOW_CLOCK 0UL /* Clock consumers of I3C_SLOW_clock output : I3C0 */ +#define BOARD_BOOTCLOCKFRO96M_LPI2C0_CLOCK 0UL /* Clock consumers of LPI2C0_clock output : LPI2C0 */ +#define BOARD_BOOTCLOCKFRO96M_LPSPI0_CLOCK 0UL /* Clock consumers of LPSPI0_clock output : LPSPI0 */ +#define BOARD_BOOTCLOCKFRO96M_LPSPI1_CLOCK 0UL /* Clock consumers of LPSPI1_clock output : LPSPI1 */ +#define BOARD_BOOTCLOCKFRO96M_LPTMR0_CLOCK 0UL /* Clock consumers of LPTMR0_clock output : LPTMR0 */ +#define BOARD_BOOTCLOCKFRO96M_LPUART0_CLOCK 0UL /* Clock consumers of LPUART0_clock output : LPUART0 */ +#define BOARD_BOOTCLOCKFRO96M_LPUART1_CLOCK 0UL /* Clock consumers of LPUART1_clock output : LPUART1 */ +#define BOARD_BOOTCLOCKFRO96M_LPUART2_CLOCK 0UL /* Clock consumers of LPUART2_clock output : LPUART2 */ +#define BOARD_BOOTCLOCKFRO96M_MAIN_CLOCK 96000000UL /* Clock consumers of MAIN_clock output : FLEXPWM0 */ +#define BOARD_BOOTCLOCKFRO96M_OSTIMER_CLOCK 0UL /* Clock consumers of OSTIMER_clock output : OSTIMER0 */ +#define BOARD_BOOTCLOCKFRO96M_FIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.FIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_SIRC_TRIM_CLOCK 0UL /* Clock consumers of SCG.SIRC_TRIM_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_SLOW_CLOCK 24000000UL /* Clock consumers of Slow_clock output : AOI0, CMC, CMP0, LPTMR0, WAKETIMER0, WUU0 */ +#define BOARD_BOOTCLOCKFRO96M_SYSTEM_CLOCK 96000000UL /* Clock consumers of System_clock output : ADC0, CMP1, CTIMER0, CTIMER1, CTIMER2, DMA0, FLEXPWM0, FREQME0, GPIO0, GPIO1, GPIO2, GPIO3, I3C0, INPUTMUX0, LPI2C0, LPSPI0, LPSPI1, LPUART0, LPUART1, LPUART2, OSTIMER0, PORT0, PORT1, PORT2, PORT3, QDC0, SWD, SysTick, USB0, UTICK0, WWDT0 */ +#define BOARD_BOOTCLOCKFRO96M_TRACE_CLOCK 96000000UL /* Clock consumers of TRACE_clock output : SWD */ +#define BOARD_BOOTCLOCKFRO96M_USB0_CLOCK 0UL /* Clock consumers of USB0_clock output : USB0 */ +#define BOARD_BOOTCLOCKFRO96M_UTICK_CLOCK 1000000UL /* Clock consumers of UTICK_clock output : UTICK0 */ +#define BOARD_BOOTCLOCKFRO96M_WUU_CLOCK 0UL /* Clock consumers of WUU_clock output : N/A */ +#define BOARD_BOOTCLOCKFRO96M_WWDT0_CLOCK 1000000UL /* Clock consumers of WWDT0_clock output : WWDT0 */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO96M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO96M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +#endif /* _CLOCK_CONFIG_H_ */ diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.c new file mode 100644 index 000000000..58b0f47e9 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.c @@ -0,0 +1,492 @@ +/* + * Copyright 2025 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Pins v17.0 +processor: MCXA153 +package_id: MCXA153VLH +mcu_data: ksdk2_0 +processor_version: 25.09.10 +board: FRDM-MCXA153 +external_user_signals: {} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +#include "fsl_common.h" +#include "fsl_port.h" +#include "fsl_gpio.h" +#include "pin_mux.h" + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) +{ + BOARD_InitDEBUG_UARTPins(); + BOARD_InitLEDsPins(); + BOARD_InitBUTTONsPins(); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitDEBUG_UARTPins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '51', peripheral: LPUART0, signal: RX, pin_signal: P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/I3C0_PUR, slew_rate: fast, open_drain: disable, + drive_strength: high, pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '52', peripheral: LPUART0, signal: TX, pin_signal: P0_3/TDI/LPUART0_TXD/LPSPI0_SDO/CT0_MAT1/UTICK_CAP1/CMP0_OUT/CMP1_IN1, slew_rate: fast, open_drain: disable, + drive_strength: low, pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitDEBUG_UARTPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitDEBUG_UARTPins(void) +{ + /* Write to PORT0: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT0); + /* LPUART0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); + /* PORT0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); + + const port_pin_config_t DEBUG_UART_RX = {/* Internal pull-up/down resistor is disabled */ + .pullSelect = kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* High drive strength is configured */ + .driveStrength = kPORT_HighDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as LPUART0_RXD */ + .mux = kPORT_MuxAlt2, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_2 (pin 51) is configured as LPUART0_RXD */ + PORT_SetPinConfig(BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PORT, BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PIN, &DEBUG_UART_RX); + + const port_pin_config_t DEBUG_UART_TX = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as LPUART0_TXD */ + .mux = kPORT_MuxAlt2, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_3 (pin 52) is configured as LPUART0_TXD */ + PORT_SetPinConfig(BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PORT, BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PIN, &DEBUG_UART_TX); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitSWD_DEBUGPins: +- options: {callFromInitBoot: 'false', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '50', peripheral: SWD, signal: SWCLK, pin_signal: P0_1/TCLK/SWCLK/LPUART0_CTS_B/LPSPI0_SDI/CT_INP1, slew_rate: fast, open_drain: disable, drive_strength: low, + pull_select: down, pull_enable: enable, input_buffer: enable, invert_input: normal} + - {pin_num: '49', peripheral: SWD, signal: SWDIO, pin_signal: P0_0/TMS/SWDIO/LPUART0_RTS_B/LPSPI0_PCS0/CT_INP0, slew_rate: fast, open_drain: disable, drive_strength: high, + pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} + - {pin_num: '51', peripheral: SWD, signal: SWO, pin_signal: P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/I3C0_PUR, slew_rate: fast, open_drain: disable, + drive_strength: high, pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitSWD_DEBUGPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitSWD_DEBUGPins(void) +{ + /* Write to PORT0: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT0); + /* PORT0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); + /* LPUART0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); + + const port_pin_config_t DEBUG_SWD_SWDIO = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* High drive strength is configured */ + .driveStrength = kPORT_HighDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as SWDIO */ + .mux = kPORT_MuxAlt1, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_0 (pin 49) is configured as SWDIO */ + PORT_SetPinConfig(BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PORT, BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PIN, &DEBUG_SWD_SWDIO); + + const port_pin_config_t DEBUG_SWD_SWDCLK = {/* Internal pull-down resistor is enabled */ + .pullSelect = kPORT_PullDown, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as SWCLK */ + .mux = kPORT_MuxAlt1, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_1 (pin 50) is configured as SWCLK */ + PORT_SetPinConfig(BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PORT, BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PIN, &DEBUG_SWD_SWDCLK); + + const port_pin_config_t DEBUG_UART_RX = {/* Internal pull-up/down resistor is disabled */ + .pullSelect = kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* High drive strength is configured */ + .driveStrength = kPORT_HighDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as SWO */ + .mux = kPORT_MuxAlt1, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT0_2 (pin 51) is configured as SWO */ + PORT_SetPinConfig(BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PORT, BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PIN, &DEBUG_UART_RX); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitLEDsPins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '37', peripheral: GPIO3, signal: 'GPIO, 13', pin_signal: P3_13/LPUART2_CTS_B/CT1_MAT3/PWM0_X1, direction: OUTPUT, gpio_init_state: 'true', slew_rate: fast, + open_drain: disable, drive_strength: low, pull_select: up, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '38', peripheral: GPIO3, signal: 'GPIO, 12', pin_signal: P3_12/LPUART2_RTS_B/CT1_MAT2/PWM0_X0, direction: OUTPUT, gpio_init_state: 'true', slew_rate: fast, + open_drain: disable, drive_strength: low, pull_select: up, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '46', peripheral: GPIO3, signal: 'GPIO, 0', pin_signal: P3_0/WUU0_IN22/TRIG_IN0/CT_INP16/PWM0_A0, direction: OUTPUT, gpio_init_state: 'true', slew_rate: fast, + open_drain: disable, drive_strength: low, pull_select: up, pull_enable: disable, passive_filter: disable, input_buffer: enable, invert_input: normal} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitLEDsPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitLEDsPins(void) +{ + /* Write to GPIO3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GateGPIO3); + /* Write to PORT3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT3); + /* GPIO3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); + /* PORT3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); + + gpio_pin_config_t LED_BLUE_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO3_0 (pin 46) */ + GPIO_PinInit(BOARD_INITLEDSPINS_LED_BLUE_GPIO, BOARD_INITLEDSPINS_LED_BLUE_PIN, &LED_BLUE_config); + + gpio_pin_config_t LED_RED_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO3_12 (pin 38) */ + GPIO_PinInit(BOARD_INITLEDSPINS_LED_RED_GPIO, BOARD_INITLEDSPINS_LED_RED_PIN, &LED_RED_config); + + gpio_pin_config_t LED_GREEN_config = { + .pinDirection = kGPIO_DigitalOutput, + .outputLogic = 1U + }; + /* Initialize GPIO functionality on pin PIO3_13 (pin 37) */ + GPIO_PinInit(BOARD_INITLEDSPINS_LED_GREEN_GPIO, BOARD_INITLEDSPINS_LED_GREEN_PIN, &LED_GREEN_config); + + /* PORT3_0 (pin 46) is configured as P3_0 */ + PORT_SetPinMux(BOARD_INITLEDSPINS_LED_BLUE_PORT, BOARD_INITLEDSPINS_LED_BLUE_PIN, kPORT_MuxAlt0); + + PORT3->PCR[0] = + ((PORT3->PCR[0] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_SRE_MASK | PORT_PCR_PFE_MASK | PORT_PCR_ODE_MASK | PORT_PCR_DSE_MASK | PORT_PCR_IBE_MASK | PORT_PCR_INV_MASK))) + + /* Pull Select: Enables internal pullup resistor. */ + | PORT_PCR_PS(PCR_PS_ps1) + + /* Pull Enable: Disables. */ + | PORT_PCR_PE(PCR_PE_pe0) + + /* Slew Rate Enable: Fast. */ + | PORT_PCR_SRE(PCR_SRE_sre0) + + /* Passive Filter Enable: Disables. */ + | PORT_PCR_PFE(PCR_PFE_pfe0) + + /* Open Drain Enable: Disables. */ + | PORT_PCR_ODE(PCR_ODE_ode0) + + /* Drive Strength Enable: Low. */ + | PORT_PCR_DSE(PCR_DSE_dse0) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1) + + /* Invert Input: Does not invert. */ + | PORT_PCR_INV(PCR_INV_inv0)); + + /* PORT3_12 (pin 38) is configured as P3_12 */ + PORT_SetPinMux(BOARD_INITLEDSPINS_LED_RED_PORT, BOARD_INITLEDSPINS_LED_RED_PIN, kPORT_MuxAlt0); + + PORT3->PCR[12] = + ((PORT3->PCR[12] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_SRE_MASK | PORT_PCR_ODE_MASK | PORT_PCR_DSE_MASK | PORT_PCR_IBE_MASK | PORT_PCR_INV_MASK))) + + /* Pull Select: Enables internal pullup resistor. */ + | PORT_PCR_PS(PCR_PS_ps1) + + /* Pull Enable: Disables. */ + | PORT_PCR_PE(PCR_PE_pe0) + + /* Slew Rate Enable: Fast. */ + | PORT_PCR_SRE(PCR_SRE_sre0) + + /* Open Drain Enable: Disables. */ + | PORT_PCR_ODE(PCR_ODE_ode0) + + /* Drive Strength Enable: Low. */ + | PORT_PCR_DSE(PCR_DSE_dse0) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1) + + /* Invert Input: Does not invert. */ + | PORT_PCR_INV(PCR_INV_inv0)); + + /* PORT3_13 (pin 37) is configured as P3_13 */ + PORT_SetPinMux(BOARD_INITLEDSPINS_LED_GREEN_PORT, BOARD_INITLEDSPINS_LED_GREEN_PIN, kPORT_MuxAlt0); + + PORT3->PCR[13] = + ((PORT3->PCR[13] & + /* Mask bits to zero which are setting */ + (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_SRE_MASK | PORT_PCR_ODE_MASK | PORT_PCR_DSE_MASK | PORT_PCR_IBE_MASK | PORT_PCR_INV_MASK))) + + /* Pull Select: Enables internal pullup resistor. */ + | PORT_PCR_PS(PCR_PS_ps1) + + /* Pull Enable: Disables. */ + | PORT_PCR_PE(PCR_PE_pe0) + + /* Slew Rate Enable: Fast. */ + | PORT_PCR_SRE(PCR_SRE_sre0) + + /* Open Drain Enable: Disables. */ + | PORT_PCR_ODE(PCR_ODE_ode0) + + /* Drive Strength Enable: Low. */ + | PORT_PCR_DSE(PCR_DSE_dse0) + + /* Input Buffer Enable: Enables. */ + | PORT_PCR_IBE(PCR_IBE_ibe1) + + /* Invert Input: Does not invert. */ + | PORT_PCR_INV(PCR_INV_inv0)); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitBUTTONsPins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '1', peripheral: GPIO1, signal: 'GPIO, 7', pin_signal: P1_7/WUU0_IN9/TRIG_OUT2/LPUART2_CTS_B/CT_INP7/ADC0_A23, slew_rate: fast, open_drain: disable, + drive_strength: low, pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '8', peripheral: GPIO1, signal: 'GPIO, 29', pin_signal: P1_29/RESET_B/SPC_LPREQ, slew_rate: fast, open_drain: enable, drive_strength: low, pull_select: up, + pull_enable: enable, passive_filter: enable, pull_value: low, input_buffer: enable, invert_input: normal} + - {pin_num: '32', peripheral: GPIO3, signal: 'GPIO, 29', pin_signal: P3_29/WUU0_IN27/ISPMODE_N/CT_INP3/ADC0_A14, slew_rate: fast, open_drain: disable, drive_strength: low, + pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBUTTONsPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitBUTTONsPins(void) +{ + /* Write to PORT1: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT1); + /* Write to PORT3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT3); + /* GPIO1 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO1_RST_SHIFT_RSTn); + /* PORT1 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn); + /* GPIO3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); + /* PORT3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); + + const port_pin_config_t SW1 = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is enabled */ + .passiveFilterEnable = kPORT_PassiveFilterEnable, + /* Open drain output is enabled */ + .openDrainEnable = kPORT_OpenDrainEnable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as P1_29 */ + .mux = kPORT_MuxAlt0, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT1_29 (pin 8) is configured as P1_29 */ + PORT_SetPinConfig(BOARD_INITBUTTONSPINS_SW1_PORT, BOARD_INITBUTTONSPINS_SW1_PIN, &SW1); + + const port_pin_config_t SW3 = {/* Internal pull-up/down resistor is disabled */ + .pullSelect = kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as P1_7 */ + .mux = kPORT_MuxAlt0, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT1_7 (pin 1) is configured as P1_7 */ + PORT_SetPinConfig(BOARD_INITBUTTONSPINS_SW3_PORT, BOARD_INITBUTTONSPINS_SW3_PIN, &SW3); + + const port_pin_config_t ISP = {/* Internal pull-up resistor is enabled */ + .pullSelect = kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + .pullValueSelect = kPORT_LowPullResistor, + /* Fast slew rate is configured */ + .slewRate = kPORT_FastSlewRate, + /* Passive input filter is disabled */ + .passiveFilterEnable = kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + .openDrainEnable = kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + .driveStrength = kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + .driveStrength1 = kPORT_NormalDriveStrength, + /* Pin is configured as P3_29 */ + .mux = kPORT_MuxAlt0, + /* Digital input enabled */ + .inputBuffer = kPORT_InputBufferEnable, + /* Digital input is not inverted */ + .invertInput = kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + .lockRegister = kPORT_UnlockRegister}; + /* PORT3_29 (pin 32) is configured as P3_29 */ + PORT_SetPinConfig(BOARD_INITBUTTONSPINS_ISP_PORT, BOARD_INITBUTTONSPINS_ISP_PIN, &ISP); +} +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h new file mode 100644 index 000000000..4a42f266d --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board/pin_mux.h @@ -0,0 +1,211 @@ +/* + * Copyright 2025 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _PIN_MUX_H_ +#define _PIN_MUX_H_ + +/*! + * @addtogroup pin_mux + * @{ + */ + +/*********************************************************************************************************************** + * API + **********************************************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Calls initialization functions. + * + */ +void BOARD_InitBootPins(void); + +/*! @name PORT0_2 (number 51), P0_2/SWO/J25[3]/J18[6] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PIN 2U /*!<@brief PORT pin number */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_RX_PIN_MASK (1U << 2U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT0_3 (number 52), P0_3/J25[1]/J18[8] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PIN 3U /*!<@brief PORT pin number */ +#define BOARD_INITDEBUG_UARTPINS_DEBUG_UART_TX_PIN_MASK (1U << 3U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitDEBUG_UARTPins(void); + +/*! @name PORT0_1 (number 50), P0_1/SWCLK/JP10[2]/J18[4] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PIN 1U /*!<@brief PORT pin number */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDCLK_PIN_MASK (1U << 1U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT0_0 (number 49), P0_0/SWDIO/J18[2] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PIN 0U /*!<@brief PORT pin number */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_SWD_SWDIO_PIN_MASK (1U << 0U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT0_2 (number 51), P0_2/SWO/J25[3]/J18[6] + @{ */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PORT PORT0 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PIN 2U /*!<@brief PORT pin number */ +#define BOARD_INITSWD_DEBUGPINS_DEBUG_UART_RX_PIN_MASK (1U << 2U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitSWD_DEBUGPins(void); + +#define PCR_DSE_dse0 0x00u /*!<@brief Drive Strength Enable: Low */ +#define PCR_IBE_ibe1 0x01u /*!<@brief Input Buffer Enable: Enables */ +#define PCR_INV_inv0 0x00u /*!<@brief Invert Input: Does not invert */ +#define PCR_ODE_ode0 0x00u /*!<@brief Open Drain Enable: Disables */ +#define PCR_PE_pe0 0x00u /*!<@brief Pull Enable: Disables */ +#define PCR_PFE_pfe0 0x00u /*!<@brief Passive Filter Enable: Disables */ +#define PCR_PS_ps1 0x01u /*!<@brief Pull Select: Enables internal pullup resistor */ +#define PCR_SRE_sre0 0x00u /*!<@brief Slew Rate Enable: Fast */ + +/*! @name PORT3_13 (number 37), P3_13/J1[14] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITLEDSPINS_LED_GREEN_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_GREEN_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDSPINS_LED_GREEN_GPIO_PIN 13U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDSPINS_LED_GREEN_GPIO_PIN_MASK (1U << 13U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITLEDSPINS_LED_GREEN_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_GREEN_PIN 13U /*!<@brief PORT pin number */ +#define BOARD_INITLEDSPINS_LED_GREEN_PIN_MASK (1U << 13U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT3_12 (number 38), P3_12/J1[12]/J5[1] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITLEDSPINS_LED_RED_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_RED_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDSPINS_LED_RED_GPIO_PIN 12U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDSPINS_LED_RED_GPIO_PIN_MASK (1U << 12U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITLEDSPINS_LED_RED_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_RED_PIN 12U /*!<@brief PORT pin number */ +#define BOARD_INITLEDSPINS_LED_RED_PIN_MASK (1U << 12U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT3_0 (number 46), P3_0/J1[8] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITLEDSPINS_LED_BLUE_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_BLUE_INIT_GPIO_VALUE 1U /*!<@brief GPIO output initial state */ +#define BOARD_INITLEDSPINS_LED_BLUE_GPIO_PIN 0U /*!<@brief GPIO pin number */ +#define BOARD_INITLEDSPINS_LED_BLUE_GPIO_PIN_MASK (1U << 0U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITLEDSPINS_LED_BLUE_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITLEDSPINS_LED_BLUE_PIN 0U /*!<@brief PORT pin number */ +#define BOARD_INITLEDSPINS_LED_BLUE_PIN_MASK (1U << 0U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitLEDsPins(void); + +/*! @name PORT1_7 (number 1), P1_7/J1[1] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITBUTTONSPINS_SW3_GPIO GPIO1 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW3_GPIO_PIN 7U /*!<@brief GPIO pin number */ +#define BOARD_INITBUTTONSPINS_SW3_GPIO_PIN_MASK (1U << 7U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITBUTTONSPINS_SW3_PORT PORT1 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW3_PIN 7U /*!<@brief PORT pin number */ +#define BOARD_INITBUTTONSPINS_SW3_PIN_MASK (1U << 7U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT1_29 (number 8), P1_29/J3[6]/J18[10] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITBUTTONSPINS_SW1_GPIO GPIO1 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW1_GPIO_PIN 29U /*!<@brief GPIO pin number */ +#define BOARD_INITBUTTONSPINS_SW1_GPIO_PIN_MASK (1U << 29U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITBUTTONSPINS_SW1_PORT PORT1 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_SW1_PIN 29U /*!<@brief PORT pin number */ +#define BOARD_INITBUTTONSPINS_SW1_PIN_MASK (1U << 29U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PORT3_29 (number 32), P3_29/J18[7]/J4[11] + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITBUTTONSPINS_ISP_GPIO GPIO3 /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_ISP_GPIO_PIN 29U /*!<@brief GPIO pin number */ +#define BOARD_INITBUTTONSPINS_ISP_GPIO_PIN_MASK (1U << 29U) /*!<@brief GPIO pin mask */ + +/* Symbols to be used with PORT driver */ +#define BOARD_INITBUTTONSPINS_ISP_PORT PORT3 /*!<@brief PORT peripheral base pointer */ +#define BOARD_INITBUTTONSPINS_ISP_PIN 29U /*!<@brief PORT pin number */ +#define BOARD_INITBUTTONSPINS_ISP_PIN_MASK (1U << 29U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitBUTTONsPins(void); + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h deleted file mode 100644 index aae811052..000000000 --- a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2023 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _CLOCK_CONFIG_H_ -#define _CLOCK_CONFIG_H_ - -#include "fsl_common.h" - -/******************************************************************************* - * Definitions - ******************************************************************************/ - -/******************************************************************************* - ************************ BOARD_InitBootClocks function ************************ - ******************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes default configuration of clocks. - * - */ -void BOARD_InitBootClocks(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO12M ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFRO12M_CORE_CLOCK 12000000U /*!< Core clock frequency: 12000000Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFRO12M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFRO12M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO24M ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFRO24M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFRO24M_CORE_CLOCK 24000000U /*!< Core clock frequency: 24000000Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFRO24M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFRO24M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO48M ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFRO48M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFRO48M_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFRO48M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFRO48M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO64M ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFRO64M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFRO64M_CORE_CLOCK 64000000U /*!< Core clock frequency: 64000000Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFRO64M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFRO64M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -/******************************************************************************* - ******************** Configuration BOARD_BootClockFRO96M ********************** - ******************************************************************************/ -/******************************************************************************* - * Definitions for BOARD_BootClockFRO96M configuration - ******************************************************************************/ -#define BOARD_BOOTCLOCKFRO96M_CORE_CLOCK 96000000U /*!< Core clock frequency: 96000000Hz */ - - -/******************************************************************************* - * API for BOARD_BootClockFRO96M configuration - ******************************************************************************/ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus*/ - -/*! - * @brief This function executes configuration of clocks. - * - */ -void BOARD_BootClockFRO96M(void); - -#if defined(__cplusplus) -} -#endif /* __cplusplus*/ - -#endif /* _CLOCK_CONFIG_H_ */ diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/frdm_mcxa153.mex b/hw/bsp/mcx/boards/frdm_mcxa153/frdm_mcxa153.mex new file mode 100644 index 000000000..43fea73db --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa153/frdm_mcxa153.mex @@ -0,0 +1,573 @@ +<?xml version="1.0" encoding= "UTF-8" ?> +<configuration name="FRDM-MCXA153" xsi:schemaLocation="http://mcuxpresso.nxp.com/XSD/mex_configuration_19 http://mcuxpresso.nxp.com/XSD/mex_configuration_19.xsd" uuid="39087bef-8f98-40a9-aaf4-e556fb7a1ce1" version="19" xmlns="http://mcuxpresso.nxp.com/XSD/mex_configuration_19" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <common> + <processor>MCXA153</processor> + <package>MCXA153VLH</package> + <board>FRDM-MCXA153</board> + <mcu_data>ksdk2_0</mcu_data> + <cores selected="cm33_core0"> + <core name="Cortex-M33" id="cm33_core0" description="M33 core"/> + </cores> + <description></description> + </common> + <preferences> + <validate_boot_init_only>true</validate_boot_init_only> + <generate_code_modified_registers_only>false</generate_code_modified_registers_only> + <custom_copyright> + <text>/* + * Copyright 2025 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +</text> + <enabled>true</enabled> + </custom_copyright> + <update_include_paths>true</update_include_paths> + <enable_parallel_routing>true</enable_parallel_routing> + <generate_registers_defines>false</generate_registers_defines> + </preferences> + <tools> + <pins name="Pins" version="17.0" enabled="true" update_project_code="true"> + <generated_project_files> + <file path="board/pin_mux.c" update_enabled="true"/> + <file path="board/pin_mux.h" update_enabled="true"/> + </generated_project_files> + <pins_profile> + <processor_version>25.09.10</processor_version> + <external_user_signals> + <properties/> + </external_user_signals> + </pins_profile> + <functions_list> + <function name="BOARD_InitDEBUG_UARTPins"> + <description>Configures pin routing and optionally pin electrical features.</description> + <options> + <callFromInitBoot>true</callFromInitBoot> + <coreID>cm33_core0</coreID> + <enableClock>true</enableClock> + </options> + <dependencies> + <dependency resourceType="Peripheral" resourceId="LPUART0" description="Peripheral LPUART0 signals are routed in the Pins Tool, but the peripheral is not initialized in the Peripherals Tool." problem_level="1" source="Pins:BOARD_InitDEBUG_UARTPins"> + <feature name="initialized" evaluation="equal"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Pins initialization requires the COMMON Driver in the project." problem_level="2" source="Pins:BOARD_InitDEBUG_UARTPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.port" description="Pins initialization requires the PORT Driver in the project." problem_level="2" source="Pins:BOARD_InitDEBUG_UARTPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <pins> + <pin peripheral="LPUART0" signal="RX" pin_num="51" pin_signal="P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/I3C0_PUR"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="high"/> + <pin_feature name="pull_select" value="down"/> + <pin_feature name="pull_enable" value="disable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + <pin peripheral="LPUART0" signal="TX" pin_num="52" pin_signal="P0_3/TDI/LPUART0_TXD/LPSPI0_SDO/CT0_MAT1/UTICK_CAP1/CMP0_OUT/CMP1_IN1"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="up"/> + <pin_feature name="pull_enable" value="enable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + </pins> + </function> + <function name="BOARD_InitSWD_DEBUGPins"> + <description>Configures pin routing and optionally pin electrical features.</description> + <options> + <callFromInitBoot>false</callFromInitBoot> + <coreID>cm33_core0</coreID> + <enableClock>true</enableClock> + </options> + <dependencies> + <dependency resourceType="Peripheral" resourceId="SWD" description="Peripheral SWD signals are routed in the Pins Tool, but the peripheral is not initialized in the Peripherals Tool." problem_level="1" source="Pins:BOARD_InitSWD_DEBUGPins"> + <feature name="initialized" evaluation="equal"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Pins initialization requires the COMMON Driver in the project." problem_level="2" source="Pins:BOARD_InitSWD_DEBUGPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.port" description="Pins initialization requires the PORT Driver in the project." problem_level="2" source="Pins:BOARD_InitSWD_DEBUGPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <pins> + <pin peripheral="SWD" signal="SWCLK" pin_num="50" pin_signal="P0_1/TCLK/SWCLK/LPUART0_CTS_B/LPSPI0_SDI/CT_INP1"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="down"/> + <pin_feature name="pull_enable" value="enable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + <pin peripheral="SWD" signal="SWDIO" pin_num="49" pin_signal="P0_0/TMS/SWDIO/LPUART0_RTS_B/LPSPI0_PCS0/CT_INP0"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="high"/> + <pin_feature name="pull_select" value="up"/> + <pin_feature name="pull_enable" value="enable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + <pin peripheral="SWD" signal="SWO" pin_num="51" pin_signal="P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/I3C0_PUR"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="high"/> + <pin_feature name="pull_select" value="down"/> + <pin_feature name="pull_enable" value="disable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + </pins> + </function> + <function name="BOARD_InitLEDsPins"> + <description>Configures pin routing and optionally pin electrical features.</description> + <options> + <callFromInitBoot>true</callFromInitBoot> + <coreID>cm33_core0</coreID> + <enableClock>true</enableClock> + </options> + <dependencies> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Pins initialization requires the COMMON Driver in the project." problem_level="2" source="Pins:BOARD_InitLEDsPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.port" description="Pins initialization requires the PORT Driver in the project." problem_level="2" source="Pins:BOARD_InitLEDsPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.gpio" description="Pins initialization requires the GPIO Driver in the project." problem_level="2" source="Pins:BOARD_InitLEDsPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <pins> + <pin peripheral="GPIO3" signal="GPIO, 13" pin_num="37" pin_signal="P3_13/LPUART2_CTS_B/CT1_MAT3/PWM0_X1"> + <pin_features> + <pin_feature name="direction" value="OUTPUT"/> + <pin_feature name="gpio_init_state" value="true"/> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="up"/> + <pin_feature name="pull_enable" value="disable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + <pin peripheral="GPIO3" signal="GPIO, 12" pin_num="38" pin_signal="P3_12/LPUART2_RTS_B/CT1_MAT2/PWM0_X0"> + <pin_features> + <pin_feature name="direction" value="OUTPUT"/> + <pin_feature name="gpio_init_state" value="true"/> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="up"/> + <pin_feature name="pull_enable" value="disable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + <pin peripheral="GPIO3" signal="GPIO, 0" pin_num="46" pin_signal="P3_0/WUU0_IN22/TRIG_IN0/CT_INP16/PWM0_A0"> + <pin_features> + <pin_feature name="direction" value="OUTPUT"/> + <pin_feature name="gpio_init_state" value="true"/> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="up"/> + <pin_feature name="pull_enable" value="disable"/> + <pin_feature name="passive_filter" value="disable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + </pins> + </function> + <function name="BOARD_InitBUTTONsPins"> + <description>Configures pin routing and optionally pin electrical features.</description> + <options> + <callFromInitBoot>true</callFromInitBoot> + <coreID>cm33_core0</coreID> + <enableClock>true</enableClock> + </options> + <dependencies> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Pins initialization requires the COMMON Driver in the project." problem_level="2" source="Pins:BOARD_InitBUTTONsPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.port" description="Pins initialization requires the PORT Driver in the project." problem_level="2" source="Pins:BOARD_InitBUTTONsPins"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <pins> + <pin peripheral="GPIO1" signal="GPIO, 7" pin_num="1" pin_signal="P1_7/WUU0_IN9/TRIG_OUT2/LPUART2_CTS_B/CT_INP7/ADC0_A23"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="down"/> + <pin_feature name="pull_enable" value="disable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + <pin peripheral="GPIO1" signal="GPIO, 29" pin_num="8" pin_signal="P1_29/RESET_B/SPC_LPREQ"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="enable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="up"/> + <pin_feature name="pull_enable" value="enable"/> + <pin_feature name="passive_filter" value="enable"/> + <pin_feature name="pull_value" value="low"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + <pin peripheral="GPIO3" signal="GPIO, 29" pin_num="32" pin_signal="P3_29/WUU0_IN27/ISPMODE_N/CT_INP3/ADC0_A14"> + <pin_features> + <pin_feature name="slew_rate" value="fast"/> + <pin_feature name="open_drain" value="disable"/> + <pin_feature name="drive_strength" value="low"/> + <pin_feature name="pull_select" value="up"/> + <pin_feature name="pull_enable" value="enable"/> + <pin_feature name="input_buffer" value="enable"/> + <pin_feature name="invert_input" value="normal"/> + </pin_features> + </pin> + </pins> + </function> + </functions_list> + </pins> + <clocks name="Clocks" version="18.0" enabled="true" update_project_code="true"> + <generated_project_files> + <file path="board/clock_config.c" update_enabled="true"/> + <file path="board/clock_config.h" update_enabled="true"/> + </generated_project_files> + <clocks_profile> + <processor_version>25.09.10</processor_version> + </clocks_profile> + <clock_configurations> + <clock_configuration name="BOARD_BootClockFRO12M" id_prefix="" prefix_user_defined="false"> + <description></description> + <options/> + <dependencies> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Clocks initialization requires the COMMON Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO12M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.clock" description="Clocks initialization requires the CLOCK Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO12M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.mcx_spc" description="Clocks initialization requires the MCX_SPC Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO12M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <clock_sources/> + <clock_outputs> + <clock_output id="CLK_1M_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="CPU_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_12M_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="MAIN_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="Slow_clock.outFreq" value="3 MHz" locked="false" accuracy=""/> + <clock_output id="System_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="TRACE_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="UTICK_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="WWDT0_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + </clock_outputs> + <clock_settings> + <setting id="SCGMode" value="SIRC" locked="false"/> + <setting id="MRCC.FREQMEREFCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.FREQMETARGETCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.OSTIMERCLKSEL.sel" value="VBAT.CLK16K_1" locked="false"/> + <setting id="SCG.SCSSEL.sel" value="SCG.SIRC" locked="false"/> + <setting id="SCG_FIRCCSR_FIRCEN_CFG" value="Disabled" locked="false"/> + </clock_settings> + <called_from_default_init>false</called_from_default_init> + </clock_configuration> + <clock_configuration name="BOARD_BootClockFRO24M" id_prefix="" prefix_user_defined="false"> + <description></description> + <options/> + <dependencies> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Clocks initialization requires the COMMON Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO24M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.clock" description="Clocks initialization requires the CLOCK Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO24M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.mcx_spc" description="Clocks initialization requires the MCX_SPC Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO24M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <clock_sources/> + <clock_outputs> + <clock_output id="CLK_1M_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="CLK_48M_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="CPU_clock.outFreq" value="24 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_12M_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_DIV_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="MAIN_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="Slow_clock.outFreq" value="6 MHz" locked="false" accuracy=""/> + <clock_output id="System_clock.outFreq" value="24 MHz" locked="false" accuracy=""/> + <clock_output id="TRACE_clock.outFreq" value="24 MHz" locked="false" accuracy=""/> + <clock_output id="UTICK_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="WWDT0_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + </clock_outputs> + <clock_settings> + <setting id="MRCC.FREQMEREFCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.FREQMETARGETCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.OSTIMERCLKSEL.sel" value="VBAT.CLK16K_1" locked="false"/> + <setting id="SYSCON.AHBCLKDIV.scale" value="2" locked="false"/> + </clock_settings> + <called_from_default_init>false</called_from_default_init> + </clock_configuration> + <clock_configuration name="BOARD_BootClockFRO48M" id_prefix="" prefix_user_defined="false"> + <description></description> + <options/> + <dependencies> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Clocks initialization requires the COMMON Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO48M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.clock" description="Clocks initialization requires the CLOCK Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO48M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.mcx_spc" description="Clocks initialization requires the MCX_SPC Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO48M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <clock_sources/> + <clock_outputs> + <clock_output id="CLK_1M_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="CLK_48M_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="CPU_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_12M_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_DIV_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="MAIN_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="Slow_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="System_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="TRACE_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="UTICK_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="WWDT0_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + </clock_outputs> + <clock_settings> + <setting id="MRCC.FREQMEREFCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.FREQMETARGETCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.OSTIMERCLKSEL.sel" value="VBAT.CLK16K_1" locked="false"/> + </clock_settings> + <called_from_default_init>false</called_from_default_init> + </clock_configuration> + <clock_configuration name="BOARD_BootClockFRO64M" id_prefix="" prefix_user_defined="false"> + <description></description> + <options/> + <dependencies> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Clocks initialization requires the COMMON Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO64M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.clock" description="Clocks initialization requires the CLOCK Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO64M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.mcx_spc" description="Clocks initialization requires the MCX_SPC Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO64M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <clock_sources> + <clock_source id="SCG.FIRC.outFreq" value="64 MHz" locked="false" enabled="false"/> + </clock_sources> + <clock_outputs> + <clock_output id="CLK_1M_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="CLK_48M_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="CPU_clock.outFreq" value="64 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_12M_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_DIV_clock.outFreq" value="64 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_clock.outFreq" value="64 MHz" locked="false" accuracy=""/> + <clock_output id="MAIN_clock.outFreq" value="64 MHz" locked="false" accuracy=""/> + <clock_output id="Slow_clock.outFreq" value="16 MHz" locked="false" accuracy=""/> + <clock_output id="System_clock.outFreq" value="64 MHz" locked="false" accuracy=""/> + <clock_output id="TRACE_clock.outFreq" value="64 MHz" locked="false" accuracy=""/> + <clock_output id="UTICK_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="WWDT0_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + </clock_outputs> + <clock_settings> + <setting id="VDD_CORE" value="voltage_1v1" locked="false"/> + <setting id="MRCC.FREQMEREFCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.FREQMETARGETCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.FROHFDIV.scale" value="1" locked="true"/> + <setting id="MRCC.OSTIMERCLKSEL.sel" value="VBAT.CLK16K_1" locked="false"/> + <setting id="SYSCON.AHBCLKDIV.scale" value="1" locked="true"/> + </clock_settings> + <called_from_default_init>false</called_from_default_init> + </clock_configuration> + <clock_configuration name="BOARD_BootClockFRO96M" id_prefix="" prefix_user_defined="false"> + <description></description> + <options/> + <dependencies> + <dependency resourceType="SWComponent" resourceId="platform.drivers.common" description="Clocks initialization requires the COMMON Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO96M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.clock" description="Clocks initialization requires the CLOCK Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO96M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + <dependency resourceType="SWComponent" resourceId="platform.drivers.mcx_spc" description="Clocks initialization requires the MCX_SPC Driver in the project." problem_level="2" source="Clocks:BOARD_BootClockFRO96M"> + <feature name="enabled" evaluation="equal" configuration="cm33_core0"> + <data>true</data> + </feature> + </dependency> + </dependencies> + <clock_sources> + <clock_source id="SCG.FIRC.outFreq" value="96 MHz" locked="false" enabled="false"/> + </clock_sources> + <clock_outputs> + <clock_output id="CLK_1M_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="CLK_48M_clock.outFreq" value="48 MHz" locked="false" accuracy=""/> + <clock_output id="CPU_clock.outFreq" value="96 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_12M_clock.outFreq" value="12 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_DIV_clock.outFreq" value="96 MHz" locked="false" accuracy=""/> + <clock_output id="FRO_HF_clock.outFreq" value="96 MHz" locked="false" accuracy=""/> + <clock_output id="MAIN_clock.outFreq" value="96 MHz" locked="false" accuracy=""/> + <clock_output id="Slow_clock.outFreq" value="24 MHz" locked="false" accuracy=""/> + <clock_output id="System_clock.outFreq" value="96 MHz" locked="false" accuracy=""/> + <clock_output id="TRACE_clock.outFreq" value="96 MHz" locked="false" accuracy=""/> + <clock_output id="UTICK_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + <clock_output id="WWDT0_clock.outFreq" value="1 MHz" locked="false" accuracy=""/> + </clock_outputs> + <clock_settings> + <setting id="VDD_CORE" value="voltage_1v1" locked="false"/> + <setting id="MRCC.FREQMEREFCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.FREQMETARGETCLKSEL.sel" value="MRCC.aoi0_out0" locked="false"/> + <setting id="MRCC.OSTIMERCLKSEL.sel" value="VBAT.CLK16K_1" locked="false"/> + </clock_settings> + <called_from_default_init>true</called_from_default_init> + </clock_configuration> + </clock_configurations> + </clocks> + <dcdx name="DCDx" version="3.0" enabled="false" update_project_code="true"> + <generated_project_files/> + <dcdx_profile> + <processor_version>N/A</processor_version> + </dcdx_profile> + <dcdx_configurations/> + </dcdx> + <periphs name="Peripherals" version="15.0" enabled="true" update_project_code="true"> + <generated_project_files> + <file path="board/peripherals.c" update_enabled="true"/> + <file path="board/peripherals.h" update_enabled="true"/> + </generated_project_files> + <peripherals_profile> + <processor_version>25.09.10</processor_version> + </peripherals_profile> + <functional_groups> + <functional_group name="BOARD_InitPeripherals" uuid="e7964cfd-63b7-4756-a1af-71a53c49bda7" called_from_default_init="true" id_prefix="" core="cm33_core0"> + <description></description> + <options/> + <dependencies/> + <instances> + <instance name="NVIC" uuid="6948572f-4bff-423f-8e78-3f0608580bb3" type="nvic" type_id="nvic" mode="general" peripheral="NVIC" enabled="true" comment="" custom_name_enabled="false" editing_lock="false"> + <config_set name="nvic"> + <array name="interrupt_table"/> + <array name="interrupts"/> + </config_set> + </instance> + </instances> + </functional_group> + </functional_groups> + <components> + <component name="system" uuid="3700167a-8497-4b9d-ad19-c395e5e33267" type_id="system"> + <config_set_global name="global_system_definitions"> + <setting name="user_definitions" value=""/> + <setting name="user_includes" value=""/> + <setting name="global_init" value=""/> + </config_set_global> + </component> + <component name="msg" uuid="faf79cc1-e0a0-4bf8-a803-42cf14e2a60a" type_id="msg"> + <config_set_global name="global_messages"/> + </component> + <component name="generic_can" uuid="f1cb80d2-97a1-4bdd-ab65-0d3d8493019c" type_id="generic_can"> + <config_set_global name="global_can"/> + </component> + <component name="uart_cmsis_common" uuid="a17f12aa-b188-417b-a499-c22892686ae2" type_id="uart_cmsis_common"> + <config_set_global name="global_USART_CMSIS_common" quick_selection="default"/> + </component> + <component name="generic_uart" uuid="96c6481f-affb-44c4-9d6f-ebc972fcae38" type_id="generic_uart"> + <config_set_global name="global_uart"/> + </component> + <component name="generic_enet" uuid="44df8b34-f20e-449a-8d2d-2cba12faf3f7" type_id="generic_enet"> + <config_set_global name="global_enet"/> + </component> + <component name="gpio_adapter_common" uuid="2fe36bae-ef17-4655-9cf5-91cac6de7288" type_id="gpio_adapter_common"> + <config_set_global name="global_gpio_adapter_common" quick_selection="default"/> + </component> + </components> + </periphs> + <tee name="TEE" version="10.0" enabled="false" update_project_code="true"> + <generated_project_files/> + <tee_profile> + <processor_version>N/A</processor_version> + </tee_profile> + </tee> + </tools> +</configuration> diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c deleted file mode 100644 index 47709951b..000000000 --- a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2023 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -/* clang-format off */ -/* - * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -!!GlobalInfo -product: Pins v14.0 -processor: MCXA153 -package_id: MCXA153VLH -mcu_data: ksdk2_0 -processor_version: 0.14.4 - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** - */ -/* clang-format on */ - -#include "fsl_common.h" -#include "fsl_port.h" -#include "pin_mux.h" - -/* FUNCTION ************************************************************************************************************ - * - * Function Name : BOARD_InitBootPins - * Description : Calls initialization functions. - * - * END ****************************************************************************************************************/ -void BOARD_InitBootPins(void) -{ - BOARD_InitPins(); -} - -/* clang-format off */ -/* - * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* -BOARD_InitPins: -- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} -- pin_list: - - {pin_num: '51', peripheral: LPUART0, signal: RX, pin_signal: P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/I3C0_PUR, slew_rate: fast, open_drain: disable, - drive_strength: low, pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} - - {pin_num: '52', peripheral: LPUART0, signal: TX, pin_signal: P0_3/TDI/LPUART0_TXD/LPSPI0_SDO/CT0_MAT1/UTICK_CAP1/CMP0_OUT/CMP1_IN1, slew_rate: fast, open_drain: disable, - drive_strength: low, pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} - * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** - */ -/* clang-format on */ - -/* FUNCTION ************************************************************************************************************ - * - * Function Name : BOARD_InitPins - * Description : Configures pin routing and optionally pin electrical features. - * - * END ****************************************************************************************************************/ -void BOARD_InitPins(void) -{ - CLOCK_EnableClock(kCLOCK_GateGPIO3); - /* Write to PORT3: Peripheral clock is enabled */ - CLOCK_EnableClock(kCLOCK_GatePORT3); - /* GPIO3 peripheral is released from reset */ - RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); - /* PORT3 peripheral is released from reset */ - RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); - - - /* Write to PORT0: Peripheral clock is enabled */ - CLOCK_EnableClock(kCLOCK_GatePORT0); - /* LPUART0 peripheral is released from reset */ - RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); - /* PORT0 peripheral is released from reset */ - RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); - - const port_pin_config_t port0_2_pin51_config = {/* Internal pull-up resistor is enabled */ - kPORT_PullUp, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Normal drive strength is configured */ - kPORT_NormalDriveStrength, - /* Pin is configured as LPUART0_RXD */ - kPORT_MuxAlt2, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT0_2 (pin 51) is configured as LPUART0_RXD */ - PORT_SetPinConfig(PORT0, 2U, &port0_2_pin51_config); - - const port_pin_config_t port0_3_pin52_config = {/* Internal pull-up resistor is enabled */ - kPORT_PullUp, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Normal drive strength is configured */ - kPORT_NormalDriveStrength, - /* Pin is configured as LPUART0_TXD */ - kPORT_MuxAlt2, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT0_3 (pin 52) is configured as LPUART0_TXD */ - PORT_SetPinConfig(PORT0, 3U, &port0_3_pin52_config); -} -/*********************************************************************************************************************** - * EOF - **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h deleted file mode 100644 index 2c0e617a5..000000000 --- a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2023 NXP - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -/*********************************************************************************************************************** - * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file - * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. - **********************************************************************************************************************/ - -#ifndef _PIN_MUX_H_ -#define _PIN_MUX_H_ - -/*! - * @addtogroup pin_mux - * @{ - */ - -/*********************************************************************************************************************** - * API - **********************************************************************************************************************/ - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! - * @brief Calls initialization functions. - * - */ -void BOARD_InitBootPins(void); - -/*! - * @brief Configures pin routing and optionally pin electrical features. - * - */ -void BOARD_InitPins(void); - -#if defined(__cplusplus) -} -#endif - -/*! - * @} - */ -#endif /* _PIN_MUX_H_ */ - -/*********************************************************************************************************************** - * EOF - **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/family.c b/hw/bsp/mcx/family.c index 2dfefeb92..e1accf941 100644 --- a/hw/bsp/mcx/family.c +++ b/hw/bsp/mcx/family.c @@ -61,14 +61,9 @@ void USB0_IRQHandler(void) { void board_init(void) { - BOARD_InitPins(); - + BOARD_InitBootPins(); BOARD_InitBootClocks(); - #ifdef XTAL0_CLK_HZ - CLOCK_SetupExtClocking(XTAL0_CLK_HZ); - #endif - #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index f857ed31a..d062cec16 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -23,27 +23,22 @@ endif() set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) - endif() - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) +endif() +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} # driver ${SDK_DIR}/drivers/gpio/fsl_gpio.c ${SDK_DIR}/drivers/common/fsl_common_arm.c @@ -66,76 +61,63 @@ function(add_board_target BOARD_TARGET) ) if (${FAMILY_MCUS} STREQUAL "MCXN9") - target_sources(${BOARD_TARGET} PRIVATE - ${SDK_DIR}/drivers/lpflexcomm/fsl_lpflexcomm.c - ) - + ${SDK_DIR}/drivers/lpflexcomm/fsl_lpflexcomm.c + ) target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR}/drivers/lpflexcomm - ) + ${SDK_DIR}/drivers/lpflexcomm + ) elseif(${FAMILY_MCUS} STREQUAL "MCXA15") - - endif() update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - #-nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + if (${FAMILY_MCUS} STREQUAL "MCXN9") + family_add_tinyusb(${TARGET} OPT_MCU_MCXN9) + elseif(${FAMILY_MCUS} STREQUAL "MCXA15") + family_add_tinyusb(${TARGET} OPT_MCU_MCXA15) + endif() - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/chipidea/$<IF:${PORT},ci_hs/dcd_ci_hs.c,ci_fs/dcd_ci_fs.c> + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - if (${FAMILY_MCUS} STREQUAL "MCXN9") - family_add_tinyusb(${TARGET} OPT_MCU_MCXN9) - elseif(${FAMILY_MCUS} STREQUAL "MCXA15") - family_add_tinyusb(${TARGET} OPT_MCU_MCXA15) - endif() - - target_sources(${TARGET} PUBLIC - # TinyUSB: Port0 is chipidea FS, Port1 is chipidea HS - ${TOP}/src/portable/chipidea/$<IF:${PORT},ci_hs/dcd_ci_hs.c,ci_fs/dcd_ci_fs.c> - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + #-nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/mcx/family.mk b/hw/bsp/mcx/family.mk index a16f4b6c0..4321e654a 100644 --- a/hw/bsp/mcx/family.mk +++ b/hw/bsp/mcx/family.mk @@ -11,7 +11,7 @@ CFLAGS += \ -DBOARD_TUD_RHPORT=$(PORT) \ # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration +CFLAGS += -Wno-error=unused-parameter -Wno-error=old-style-declaration -Wno-error=redundant-decls LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs @@ -56,12 +56,9 @@ INC += \ $(TOP)/$(SDK_DIR)/drivers/ \ $(TOP)/$(SDK_DIR)/drivers/lpuart \ $(TOP)/$(SDK_DIR)/drivers/lpflexcomm \ - $(TOP)/$(SDK_DIR)/drivers/common\ - $(TOP)/$(SDK_DIR)/drivers/gpio\ - $(TOP)/$(SDK_DIR)/drivers/port\ - $(TOP)/hw/bsp/mcx/drivers/spc - - - + $(TOP)/$(SDK_DIR)/drivers/common\ + $(TOP)/$(SDK_DIR)/drivers/gpio\ + $(TOP)/$(SDK_DIR)/drivers/port\ + $(TOP)/hw/bsp/mcx/drivers/spc SRC_S += $(SDK_DIR)/devices/$(MCU_VARIANT)/gcc/startup_$(MCU_CORE).S diff --git a/hw/bsp/mm32/family.cmake b/hw/bsp/mm32/family.cmake index 0561a63a0..04961d6c3 100644 --- a/hw/bsp/mm32/family.cmake +++ b/hw/bsp/mm32/family.cmake @@ -14,28 +14,23 @@ set(FAMILY_MCUS MM32F327X CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${SDK_DIR}/Source/GCC_StartAsm/startup_${MCU_VARIANT}_gcc.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${SDK_DIR}/Source/IAR_StartAsm/startup_${MCU_VARIANT}_iar.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - # set(LD_FILE_IAR ) +set(STARTUP_FILE_GNU ${SDK_DIR}/Source/GCC_StartAsm/startup_${MCU_VARIANT}_gcc.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${SDK_DIR}/Source/IAR_StartAsm/startup_${MCU_VARIANT}_iar.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +# set(LD_FILE_IAR ) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/Source/system_${MCU_VARIANT}.c ${SDK_DIR}/HAL_Lib/Src/hal_gpio.c ${SDK_DIR}/HAL_Lib/Src/hal_rcc.c ${SDK_DIR}/HAL_Lib/Src/hal_uart.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMSIS_5}/CMSIS/Core/Include @@ -44,56 +39,49 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_MM32F327X) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MM32F327X) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/msp430/family.c b/hw/bsp/msp430/family.c index a45bd5f93..390a9915e 100644 --- a/hw/bsp/msp430/family.c +++ b/hw/bsp/msp430/family.c @@ -35,8 +35,8 @@ //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void __attribute__ ((interrupt(USB_UBM_VECTOR))) USB_UBM_ISR(void) -{ +void USB_UBM_ISR(void) __attribute__ ((interrupt(USB_UBM_VECTOR))); +void USB_UBM_ISR(void) { tud_int_handler(0); } @@ -200,8 +200,9 @@ int board_uart_write(void const * buf, int len) #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void) -{ + +void TIMER0_A0_ISR (void) __attribute__ ((interrupt(TIMER0_A0_VECTOR))); +void TIMER0_A0_ISR (void) { system_ticks++; // TAxCCR0 CCIFG resets itself as soon as interrupt is invoked. } diff --git a/hw/bsp/msp430/family.cmake b/hw/bsp/msp430/family.cmake index d9b4bf770..8b0dbeff4 100644 --- a/hw/bsp/msp430/family.cmake +++ b/hw/bsp/msp430/family.cmake @@ -15,11 +15,7 @@ set(FAMILY_MCUS MSP430x5xx CACHE INTERNAL "") # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} INTERFACE) target_compile_definitions(${BOARD_TARGET} INTERFACE CFG_TUD_ENDPOINT0_SIZE=8 @@ -32,17 +28,6 @@ function(add_board_target BOARD_TARGET) ) 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() @@ -51,16 +36,14 @@ endfunction() #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) + family_add_tinyusb(${TARGET} OPT_MCU_MSP430x5xx) #---------- Port Specific ---------- # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c ) target_include_directories(${TARGET} PUBLIC # family, hw, board @@ -69,13 +52,16 @@ function(family_configure_example TARGET RTOS) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MSP430x5xx) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -L${SDK_DIR} + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () # Flashing family_add_bin_hex(${TARGET}) family_flash_msp430flasher(${TARGET}) diff --git a/hw/bsp/msp432e4/family.cmake b/hw/bsp/msp432e4/family.cmake index f6939ecfe..6725eedac 100644 --- a/hw/bsp/msp432e4/family.cmake +++ b/hw/bsp/msp432e4/family.cmake @@ -14,27 +14,23 @@ set(FAMILY_MCUS MSP432E4 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${SDK_DIR}/Source/${MCU_VARIANT}.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - - if (NOT DEFINED STARTUP_FILE_GNU) - set(STARTUP_FILE_GNU ${SDK_DIR}/Source/startup_${MCU_VARIANT}_gcc.S) - endif () - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${SDK_DIR}/Source/${MCU_VARIANT}.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED STARTUP_FILE_GNU) +set(STARTUP_FILE_GNU ${SDK_DIR}/Source/startup_${MCU_VARIANT}_gcc.S) +endif () +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/Source/system_${MCU_VARIANT}.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR}/Include @@ -42,57 +38,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(${BOARD_TARGET} PUBLIC - -mslow-flash-data - ) - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for MSP432E4") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_MSP432E4) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/mentor/musb/dcd_musb.c + ${TOP}/src/portable/mentor/musb/hcd_musb.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MSP432E4) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mentor/musb/dcd_musb.c - ${TOP}/src/portable/mentor/musb/hcd_musb.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${TARGET} PUBLIC + -mslow-flash-data + ) + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for MSP432E4") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/nrf/boards/adafruit_clue/board.mk b/hw/bsp/nrf/boards/adafruit_clue/board.mk index b80807963..e6fcdd9b0 100644 --- a/hw/bsp/nrf/boards/adafruit_clue/board.mk +++ b/hw/bsp/nrf/boards/adafruit_clue/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA # All source paths should be relative to the top level. -LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld +LD_FILE = ${FAMILY_PATH}/linker/nrf52840_s140_v6.ld $(BUILD)/$(PROJECT).zip: $(BUILD)/$(PROJECT).hex adafruit-nrfutil dfu genpkg --dev-type 0x0052 --sd-req 0xFFFE --application $^ $@ diff --git a/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.mk b/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.mk index b80807963..e6fcdd9b0 100644 --- a/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.mk +++ b/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA # All source paths should be relative to the top level. -LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld +LD_FILE = ${FAMILY_PATH}/linker/nrf52840_s140_v6.ld $(BUILD)/$(PROJECT).zip: $(BUILD)/$(PROJECT).hex adafruit-nrfutil dfu genpkg --dev-type 0x0052 --sd-req 0xFFFE --application $^ $@ diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk index 488f07b82..d33b3558a 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk @@ -5,7 +5,7 @@ CFLAGS += -DNRF52840_XXAA MAX3421_HOST = 1 # All source paths should be relative to the top level. -LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld +LD_FILE = ${FAMILY_PATH}/linker/nrf52840_s140_v6.ld $(BUILD)/$(PROJECT).zip: $(BUILD)/$(PROJECT).hex adafruit-nrfutil dfu genpkg --dev-type 0x0052 --sd-req 0xFFFE --application $^ $@ diff --git a/hw/bsp/nrf/boards/feather_nrf52840_sense/board.mk b/hw/bsp/nrf/boards/feather_nrf52840_sense/board.mk index b80807963..e6fcdd9b0 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_sense/board.mk +++ b/hw/bsp/nrf/boards/feather_nrf52840_sense/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA # All source paths should be relative to the top level. -LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld +LD_FILE = ${FAMILY_PATH}/linker/nrf52840_s140_v6.ld $(BUILD)/$(PROJECT).zip: $(BUILD)/$(PROJECT).hex adafruit-nrfutil dfu genpkg --dev-type 0x0052 --sd-req 0xFFFE --application $^ $@ diff --git a/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.mk b/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.mk index b80807963..e6fcdd9b0 100644 --- a/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.mk +++ b/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA # All source paths should be relative to the top level. -LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld +LD_FILE = ${FAMILY_PATH}/linker/nrf52840_s140_v6.ld $(BUILD)/$(PROJECT).zip: $(BUILD)/$(PROJECT).hex adafruit-nrfutil dfu genpkg --dev-type 0x0052 --sd-req 0xFFFE --application $^ $@ diff --git a/hw/bsp/nrf/boards/pca10100/board.cmake b/hw/bsp/nrf/boards/nrf52833dk/board.cmake index a925dae80..a925dae80 100644 --- a/hw/bsp/nrf/boards/pca10100/board.cmake +++ b/hw/bsp/nrf/boards/nrf52833dk/board.cmake diff --git a/hw/bsp/nrf/boards/pca10100/board.h b/hw/bsp/nrf/boards/nrf52833dk/board.h index 8aca6dce9..8aca6dce9 100644 --- a/hw/bsp/nrf/boards/pca10100/board.h +++ b/hw/bsp/nrf/boards/nrf52833dk/board.h diff --git a/hw/bsp/nrf/boards/pca10100/board.mk b/hw/bsp/nrf/boards/nrf52833dk/board.mk index 5fba269b7..7cf00cbc1 100644 --- a/hw/bsp/nrf/boards/pca10100/board.mk +++ b/hw/bsp/nrf/boards/nrf52833dk/board.mk @@ -1,7 +1,7 @@ MCU_VARIANT = nrf52833 CFLAGS += -DNRF52833_XXAA -LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf52833_xxaa.ld +LD_FILE = ${FAMILY_PATH}/linker/nrf52833_xxaa.ld # flash using jlink flash: flash-jlink diff --git a/hw/bsp/nrf/boards/pca10056/board.cmake b/hw/bsp/nrf/boards/nrf52840dk/board.cmake index 85314f3bc..85314f3bc 100644 --- a/hw/bsp/nrf/boards/pca10056/board.cmake +++ b/hw/bsp/nrf/boards/nrf52840dk/board.cmake diff --git a/hw/bsp/nrf/boards/pca10056/board.h b/hw/bsp/nrf/boards/nrf52840dk/board.h index ec632e769..ec632e769 100644 --- a/hw/bsp/nrf/boards/pca10056/board.h +++ b/hw/bsp/nrf/boards/nrf52840dk/board.h diff --git a/hw/bsp/nrf/boards/pca10056/board.mk b/hw/bsp/nrf/boards/nrf52840dk/board.mk index be2ed3314..d8bbd41f8 100644 --- a/hw/bsp/nrf/boards/pca10056/board.mk +++ b/hw/bsp/nrf/boards/nrf52840dk/board.mk @@ -1,7 +1,5 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA -LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf52840_xxaa.ld - # flash using jlink flash: flash-jlink diff --git a/hw/bsp/nrf/boards/pca10056/ozone/nrf52840.jdebug b/hw/bsp/nrf/boards/nrf52840dk/ozone/nrf52840.jdebug index fa7ab9e23..fa7ab9e23 100644 --- a/hw/bsp/nrf/boards/pca10056/ozone/nrf52840.jdebug +++ b/hw/bsp/nrf/boards/nrf52840dk/ozone/nrf52840.jdebug diff --git a/hw/bsp/nrf/boards/pca10059/board.cmake b/hw/bsp/nrf/boards/nrf52840dongle/board.cmake index c79eb5964..5ec769192 100644 --- a/hw/bsp/nrf/boards/pca10059/board.cmake +++ b/hw/bsp/nrf/boards/nrf52840dongle/board.cmake @@ -1,5 +1,5 @@ set(MCU_VARIANT nrf52840) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/pca10059.ld) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) function(update_board TARGET) endfunction() diff --git a/hw/bsp/nrf/boards/pca10059/board.h b/hw/bsp/nrf/boards/nrf52840dongle/board.h index 3b95481ad..3b95481ad 100644 --- a/hw/bsp/nrf/boards/pca10059/board.h +++ b/hw/bsp/nrf/boards/nrf52840dongle/board.h diff --git a/hw/bsp/nrf/boards/pca10059/board.mk b/hw/bsp/nrf/boards/nrf52840dongle/board.mk index 0b82ecdbb..0b82ecdbb 100644 --- a/hw/bsp/nrf/boards/pca10059/board.mk +++ b/hw/bsp/nrf/boards/nrf52840dongle/board.mk diff --git a/hw/bsp/nrf/boards/pca10059/pca10059.ld b/hw/bsp/nrf/boards/nrf52840dongle/nrf52840dongle.ld index adc80f3c4..32cc6eada 100644 --- a/hw/bsp/nrf/boards/pca10059/pca10059.ld +++ b/hw/bsp/nrf/boards/nrf52840dongle/nrf52840dongle.ld @@ -11,9 +11,3 @@ MEMORY INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/boards/nrf5340dk/board.cmake b/hw/bsp/nrf/boards/nrf5340dk/board.cmake new file mode 100644 index 000000000..fe766dd78 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf5340dk/board.cmake @@ -0,0 +1,4 @@ +set(MCU_VARIANT nrf5340) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/pca10095/board.h b/hw/bsp/nrf/boards/nrf5340dk/board.h index 1c7981049..1c7981049 100644 --- a/hw/bsp/nrf/boards/pca10095/board.h +++ b/hw/bsp/nrf/boards/nrf5340dk/board.h diff --git a/hw/bsp/nrf/boards/pca10095/board.mk b/hw/bsp/nrf/boards/nrf5340dk/board.mk index 20580d619..972168fcd 100644 --- a/hw/bsp/nrf/boards/pca10095/board.mk +++ b/hw/bsp/nrf/boards/nrf5340dk/board.mk @@ -1,14 +1,9 @@ -CPU_CORE = cortex-m33 -MCU_VARIANT = nrf5340_application +MCU_VARIANT = nrf5340 CFLAGS += -DNRF5340_XXAA -DNRF5340_XXAA_APPLICATION # enable max3421 host driver for this board MAX3421_HOST = 1 -LD_FILE = hw/mcu/nordic/nrfx/mdk/nrf5340_xxaa_application.ld - -SRC_C += hw/mcu/nordic/nrfx/drivers/src/nrfx_usbreg.c - # caused by void SystemStoreFICRNS() (without void) in system_nrf5340_application.c CFLAGS += -Wno-error=strict-prototypes diff --git a/hw/bsp/nrf/boards/pca10095/ozone/nrf5340.jdebug b/hw/bsp/nrf/boards/nrf5340dk/ozone/nrf5340.jdebug index 4ad0376a4..4ad0376a4 100644 --- a/hw/bsp/nrf/boards/pca10095/ozone/nrf5340.jdebug +++ b/hw/bsp/nrf/boards/nrf5340dk/ozone/nrf5340.jdebug diff --git a/hw/bsp/nrf/boards/nrf54h20dk/board.cmake b/hw/bsp/nrf/boards/nrf54h20dk/board.cmake new file mode 100644 index 000000000..fca7a56d2 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54h20dk/board.cmake @@ -0,0 +1,11 @@ +set(MCU_VARIANT nrf54h20) + +function(update_board TARGET) + # temporarily, 54h20 has multiple sram sections + target_compile_definitions(${TARGET} PUBLIC + CFG_EXAMPLE_VIDEO_READONLY + ) + target_sources(${TARGET} PRIVATE +# ${NRFX_PATH}/drivers/src/nrfx_usbreg.c + ) +endfunction() diff --git a/hw/bsp/nrf/boards/nrf54h20dk/board.h b/hw/bsp/nrf/boards/nrf54h20dk/board.h new file mode 100644 index 000000000..c8ed5779f --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54h20dk/board.h @@ -0,0 +1,65 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + */ + +/* metadata: + name: Nordic nRF54H20 DK + url: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF5340-DK +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define _PINNUM(port, pin) ((port)*32 + (pin)) + +// LED +#define LED_PIN 28 +#define LED_STATE_ON 0 + +// Button +#define BUTTON_PIN 23 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_RX_PIN 22 +#define UART_TX_PIN 20 + +// SPI for USB host shield +// Pin is correct but not working probably due to signal incompatible (1.8V 3v3) with MAC3421E !? +//#define MAX3421_SCK_PIN _PINNUM(1, 15) +//#define MAX3421_MOSI_PIN _PINNUM(1, 13) +//#define MAX3421_MISO_PIN _PINNUM(1, 14) +//#define MAX3421_CS_PIN _PINNUM(1, 12) +//#define MAX3421_INTR_PIN _PINNUM(1, 11) + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/nrf/boards/nrf54h20dk/board.mk b/hw/bsp/nrf/boards/nrf54h20dk/board.mk new file mode 100644 index 000000000..c49b605e8 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf54h20dk/board.mk @@ -0,0 +1,12 @@ +MCU_VARIANT = nrf54h20 +CFLAGS += -DNRF54H20_XXAA + +# enable max3421 host driver for this board +MAX3421_HOST = 1 + +# caused by void SystemStoreFICRNS() (without void) in system_nrf5340_application.c +CFLAGS += -Wno-error=strict-prototypes + +# flash using jlink +JLINK_DEVICE = nrf5340_xxaa_app +flash: flash-jlink diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake deleted file mode 100644 index 6d183dde6..000000000 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ /dev/null @@ -1,7 +0,0 @@ -set(MCU_VARIANT nrf5340_application) - -function(update_board TARGET) - target_sources(${TARGET} PRIVATE - ${NRFX_PATH}/drivers/src/nrfx_usbreg.c - ) -endfunction() diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 298ca2302..25062b18f 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -45,7 +45,9 @@ #include "nrfx.h" #include "hal/nrf_gpio.h" #include "nrfx_gpiote.h" +#if !defined(NRF54H20_XXAA) #include "nrfx_power.h" +#endif #include "nrfx_uarte.h" #include "nrfx_spim.h" @@ -58,21 +60,12 @@ #pragma GCC diagnostic pop #endif - -// There is API changes between nrfx v2 and v3 -#if 85301 >= (10000*MDK_MAJOR_VERSION + 100*MDK_MINOR_VERSION + MDK_MICRO_VERSION) - // note MDK 8.53.1 is also used by nrfx v3.0.0, just skip this version and use later 3.x - #define NRFX_VER 2 -#else - #define NRFX_VER 3 +// example only supports nrfx v3 for code simplicity +#if !(defined(NRFX_CONFIG_API_VER_MAJOR) && NRFX_CONFIG_API_VER_MAJOR >= 3) && \ + !(85301 >= (10000*MDK_MAJOR_VERSION + 100*MDK_MINOR_VERSION + MDK_MICRO_VERSION)) + #error "Example requires nrfx v3.0.0 or later" #endif -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USBD_IRQHandler(void) { - tud_int_handler(0); -} /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM @@ -85,50 +78,67 @@ enum { USB_EVT_READY = 2 }; +// Forward USB interrupt events to TinyUSB IRQ Handler +#if defined(NRF54H20_XXAA) +#define USBD_IRQn USBHS_IRQn +void USBHS_IRQHandler(void) { + tusb_int_handler(0, true); +} + +static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(120); + +#else + #ifdef NRF5340_XXAA - #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC - #define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk - #define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk - #define GPIOTE_IRQn GPIOTE1_IRQn +#define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC +#define VBUSDETECT_Msk USBREG_USBREGSTATUS_VBUSDETECT_Msk +#define OUTPUTRDY_Msk USBREG_USBREGSTATUS_OUTPUTRDY_Msk +#define GPIOTE_IRQn GPIOTE1_IRQn #else - #define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC - #define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk - #define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk +#define LFCLK_SRC_RC CLOCK_LFCLKSRC_SRC_RC +#define VBUSDETECT_Msk POWER_USBREGSTATUS_VBUSDETECT_Msk +#define OUTPUTRDY_Msk POWER_USBREGSTATUS_OUTPUTRDY_Msk #endif static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); +void USBD_IRQHandler(void) { + tud_int_handler(0); +} +#endif + + // tinyusb function that handles power event (detected, ready, removed) // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. extern void tusb_hal_nrf_power_event(uint32_t event); +#if !defined(NRF54H20_XXAA) // nrf power callback, could be unused if SD is enabled or usb is disabled (board_test example) TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); } +#endif //------------- Host using MAX2341E -------------// #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static void max3421_init(void); static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); - -#if NRFX_VER > 2 static nrfx_gpiote_t _gpiote = NRFX_GPIOTE_INSTANCE(0); #endif -#endif - //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ void board_init(void) { +#if !defined(NRF54H20_XXAA) // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; // Use Internal OSC to compatible with all boards NRF_CLOCK->LFCLKSRC = LFCLK_SRC_RC; NRF_CLOCK->TASKS_LFCLKSTART = 1UL; +#endif // LED nrf_gpio_cfg_output(LED_PIN); @@ -140,6 +150,7 @@ void board_init(void) { #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer SysTick_Config(SystemCoreClock / 1000); + #elif CFG_TUSB_OS == OPT_OS_ZEPHYR #ifdef CONFIG_HAS_HW_NRF_USBREG // IRQ_CONNECT(USBREGULATOR_IRQn, DT_IRQ(DT_INST(0, nordic_nrf_clock), priority), nrfx_isr, nrfx_usbreg_irq_handler, 0); @@ -153,21 +164,6 @@ void board_init(void) { #endif // UART - #if NRFX_VER <= 2 - nrfx_uarte_config_t uart_cfg = { - .pseltxd = UART_TX_PIN, - .pselrxd = UART_RX_PIN, - .pselcts = NRF_UARTE_PSEL_DISCONNECTED, - .pselrts = NRF_UARTE_PSEL_DISCONNECTED, - .p_context = NULL, - .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE - .interrupt_priority = 7, - .hal_cfg = { - .hwfc = NRF_UARTE_HWFC_DISABLED, - .parity = NRF_UARTE_PARITY_EXCLUDED, - } - }; - #else nrfx_uarte_config_t uart_cfg = { .txd_pin = UART_TX_PIN, .rxd_pin = UART_RX_PIN, @@ -181,7 +177,6 @@ void board_init(void) { .parity = NRF_UARTE_PARITY_EXCLUDED, } }; - #endif nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); @@ -191,6 +186,7 @@ void board_init(void) { // 2 is highest for application NVIC_SetPriority(USBD_IRQn, 2); +#if !defined(NRF54H20_XXAA) // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially uint32_t usb_reg; @@ -234,6 +230,7 @@ void board_init(void) { tusb_hal_nrf_power_event(USB_EVT_READY); } #endif +#endif #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 max3421_init(); @@ -255,7 +252,9 @@ uint32_t board_button_read(void) { size_t board_get_unique_id(uint8_t id[], size_t max_len) { (void) max_len; -#ifdef NRF5340_XXAA +#if defined(NRF54H20_XXAA) + uintptr_t did_addr = (uintptr_t) NRF_FICR->BLE.ADDR; +#elif defined(NRF5340_XXAA) uintptr_t did_addr = (uintptr_t) NRF_FICR->INFO.DEVICEID; #else uintptr_t did_addr = (uintptr_t) NRF_FICR->DEVICEID; @@ -277,11 +276,7 @@ int board_uart_read(uint8_t* buf, int len) { } int board_uart_write(void const* buf, int len) { - nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len - #if NRFX_VER > 2 - ,0 - #endif - ); + nrfx_err_t err = nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len ,0); return (NRFX_SUCCESS == err) ? len : 0; } @@ -352,18 +347,16 @@ void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { // API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 - -#if NRFX_VER <= 2 -void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action ) { - if (action != NRF_GPIOTE_POLARITY_HITOLO) return; -#else void max3421_int_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t action, void* p_context) { (void) p_context; - if (action != NRFX_GPIOTE_TRIGGER_HITOLO) return; -#endif + if (action != NRFX_GPIOTE_TRIGGER_HITOLO) { + return; + } + if (pin != MAX3421_INTR_PIN) { + return; + } - if (pin != MAX3421_INTR_PIN) return; - tuh_int_handler(1, true); + tusb_int_handler(1, true); } static void max3421_init(void) { @@ -378,13 +371,8 @@ static void max3421_init(void) { .sck_pin = MAX3421_SCK_PIN, .mosi_pin = MAX3421_MOSI_PIN, .miso_pin = MAX3421_MISO_PIN, - #if NRFX_VER <= 2 - .ss_pin = NRFX_SPIM_PIN_NOT_USED, - .frequency = NRF_SPIM_FREQ_4M, - #else .ss_pin = NRF_SPIM_PIN_NOT_CONNECTED, .frequency = 4000000u, - #endif .ss_active_high = false, .irq_priority = 3, .orc = 0xFF, @@ -398,14 +386,6 @@ static void max3421_init(void) { TU_ASSERT(NRFX_SUCCESS == nrfx_spim_init(&_spi, &cfg, NULL, NULL), ); // max3421e interrupt pin - #if NRFX_VER <= 2 - nrfx_gpiote_init(1); - nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); - in_config.pull = NRF_GPIO_PIN_PULLUP; - NVIC_SetPriority(GPIOTE_IRQn, 2); - nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler); - nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); - #else nrf_gpio_pin_pull_t intr_pull = NRF_GPIO_PIN_PULLUP; nrfx_gpiote_trigger_config_t intr_trigger = { .trigger = NRFX_GPIOTE_TRIGGER_HITOLO, @@ -426,7 +406,6 @@ static void max3421_init(void) { nrfx_gpiote_input_configure(&_gpiote, MAX3421_INTR_PIN, &intr_config); nrfx_gpiote_trigger_enable(&_gpiote, MAX3421_INTR_PIN, true); - #endif } // API to enable/disable MAX3421 INTR pin interrupt diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 7d0a9f6de..4e999b636 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -10,57 +10,76 @@ if (NOT board_cmake_included) endif () # toolchain set up -if (MCU_VARIANT STREQUAL "nrf5340_application") +if (MCU_VARIANT STREQUAL nrf5340 OR MCU_VARIANT STREQUAL nrf54h20) set(CMAKE_SYSTEM_CPU cortex-m33 CACHE INTERNAL "System Processor") - set(JLINK_DEVICE nrf5340_xxaa_app) + set(JLINK_DEVICE ${MCU_VARIANT}_xxaa_app) else () set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") set(JLINK_DEVICE ${MCU_VARIANT}_xxaa) endif () -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +if (MCU_VARIANT STREQUAL "nrf54h20") + set(FAMILY_MCUS NRF54 CACHE INTERNAL "") +else () + set(FAMILY_MCUS NRF5X CACHE INTERNAL "") +endif () -set(FAMILY_MCUS NRF5X CACHE INTERNAL "") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - if (MCU_VARIANT STREQUAL "nrf5340_application") - set(MCU_VARIANT_XXAA "nrf5340_xxaa_application") - else () - set(MCU_VARIANT_XXAA "${MCU_VARIANT}_xxaa") - endif () - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT_XXAA}.ld) - endif () +if (MCU_VARIANT STREQUAL nrf54h20) + set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_xxaa_application.ld) + set(STARTUP_FILE_GNU ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}_application.S) +elseif (MCU_VARIANT STREQUAL nrf5340) + set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_xxaa_application.ld) + set(STARTUP_FILE_GNU ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}_application.S) +else() + set(LD_FILE_GNU_DEFAULT ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_xxaa.ld) + set(STARTUP_FILE_GNU ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}.S) +endif () - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${NRFX_PATH}/mdk/gcc_startup_${MCU_VARIANT}.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - endif () +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${LD_FILE_GNU_DEFAULT}) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${NRFX_PATH}/helpers/nrfx_flag32_allocator.c ${NRFX_PATH}/drivers/src/nrfx_gpiote.c ${NRFX_PATH}/drivers/src/nrfx_power.c ${NRFX_PATH}/drivers/src/nrfx_spim.c ${NRFX_PATH}/drivers/src/nrfx_uarte.c - ${NRFX_PATH}/mdk/system_${MCU_VARIANT}.c ${NRFX_PATH}/soc/nrfx_atomic.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) - string(TOUPPER "${MCU_VARIANT_XXAA}" MCU_VARIANT_XXAA_UPPER) + + if (MCU_VARIANT STREQUAL nrf54h20) + target_sources(${BOARD_TARGET} PRIVATE + ${NRFX_PATH}/mdk/system_nrf54h.c + ) + elseif (MCU_VARIANT STREQUAL nrf5340) + target_sources(${BOARD_TARGET} PRIVATE + ${NRFX_PATH}/mdk/system_${MCU_VARIANT}_application.c + ${NRFX_PATH}/drivers/src/nrfx_usbreg.c + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF5340_XXAA_APPLICATION) + else() + target_sources(${BOARD_TARGET} PRIVATE + ${NRFX_PATH}/mdk/system_${MCU_VARIANT}.c + ) + endif () + + string(TOUPPER ${MCU_VARIANT} MCU_VARIANT_UPPER) target_compile_definitions(${BOARD_TARGET} PUBLIC __STARTUP_CLEAR_BSS CONFIG_GPIO_AS_PINRESET - ${MCU_VARIANT_XXAA_UPPER} + ${MCU_VARIANT_UPPER}_XXAA + NRF_APPLICATION ) if (TRACE_ETM STREQUAL "1") @@ -77,27 +96,8 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -L${NRFX_PATH}/mdk - --specs=nosys.specs --specs=nano.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -L${NRFX_PATH}/mdk - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ @@ -109,41 +109,55 @@ endfunction() # ) #endfunction() - function(family_configure_example TARGET RTOS) - # Board target - if (NOT RTOS STREQUAL zephyr) - add_board_target(board_${BOARD}) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - endif () - family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${FAMILY_MCUS}) - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PRIVATE - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nordic/nrf5x/dcd_nrf5x.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - if (RTOS STREQUAL zephyr AND DEFINED BOARD_ALIAS AND NOT BOARD STREQUAL BOARD_ALIAS) - target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD_ALIAS}) + + if (NOT RTOS STREQUAL zephyr) + target_sources(${TARGET} PRIVATE ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -L${NRFX_PATH}/mdk + --specs=nosys.specs --specs=nano.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -L${NRFX_PATH}/mdk + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () endif () - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_NRF5X) - target_sources(${TARGET} PRIVATE - ${TOP}/src/portable/nordic/nrf5x/dcd_nrf5x.c - ) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing -# family_add_bin_hex(${TARGET}) + # family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) -# family_flash_adafruit_nrfutil(${TARGET}) + # family_flash_adafruit_nrfutil(${TARGET}) endfunction() diff --git a/hw/bsp/nrf/family.mk b/hw/bsp/nrf/family.mk index a8acb1624..2cead99db 100644 --- a/hw/bsp/nrf/family.mk +++ b/hw/bsp/nrf/family.mk @@ -4,11 +4,37 @@ NRFX_PATH = hw/mcu/nordic/nrfx include $(TOP)/$(BOARD_PATH)/board.mk -# nRF52 is cortex-m4, nRF53 is cortex-m33 -CPU_CORE ?= cortex-m4 +ifeq (${MCU_VARIANT},nrf54h20) + CPU_CORE = cortex-m33 + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF54 + LD_FILE_DEFAULT = ${FAMILY_PATH}/linker/${MCU_VARIANT}_xxaa_application.ld + SRC_C += ${NRFX_PATH}/mdk/system_nrf54h.c + SRC_S += ${NRFX_PATH}/mdk/gcc_startup_$(MCU_VARIANT)_application.S + JLINK_DEVICE ?= $(MCU_VARIANT)_xxaa_app + +else +ifeq (${MCU_VARIANT},nrf5340) + CPU_CORE = cortex-m33 + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X + LD_FILE_DEFAULT = ${FAMILY_PATH}/linker/${MCU_VARIANT}_xxaa_application.ld + SRC_C += ${NRFX_PATH}/mdk/system_$(MCU_VARIANT)_application.c \ + ${NRFX_PATH}/drivers/src/nrfx_usbreg.c + SRC_S += ${NRFX_PATH}/mdk/gcc_startup_$(MCU_VARIANT)_application.S + JLINK_DEVICE ?= $(MCU_VARIANT)_xxaa_app + +else + + CPU_CORE = cortex-m4 + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X + LD_FILE_DEFAULT = ${FAMILY_PATH}/linker/${MCU_VARIANT}_xxaa.ld + SRC_C += ${NRFX_PATH}/mdk/system_$(MCU_VARIANT).c + SRC_S += ${NRFX_PATH}/mdk/gcc_startup_$(MCU_VARIANT).S + JLINK_DEVICE ?= $(MCU_VARIANT)_xxaa +endif +endif CFLAGS += \ - -DCFG_TUSB_MCU=OPT_MCU_NRF5X \ + -DNRF_APPLICATION \ -DCONFIG_GPIO_AS_PINRESET \ -D__STARTUP_CLEAR_BSS @@ -33,14 +59,20 @@ LDFLAGS_GCC += \ LDFLAGS_CLANG += \ -L$(TOP)/${NRFX_PATH}/mdk \ +ifndef LD_FILE +LD_FILE = ${LD_FILE_DEFAULT} +endif + SRC_C += \ src/portable/nordic/nrf5x/dcd_nrf5x.c \ + src/portable/synopsys/dwc2/dwc2_common.c \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ + src/portable/synopsys/dwc2/hcd_dwc2.c \ ${NRFX_PATH}/helpers/nrfx_flag32_allocator.c \ ${NRFX_PATH}/drivers/src/nrfx_gpiote.c \ ${NRFX_PATH}/drivers/src/nrfx_power.c \ ${NRFX_PATH}/drivers/src/nrfx_spim.c \ ${NRFX_PATH}/drivers/src/nrfx_uarte.c \ - ${NRFX_PATH}/mdk/system_$(MCU_VARIANT).c \ ${NRFX_PATH}/soc/nrfx_atomic.c INC += \ @@ -53,9 +85,4 @@ INC += \ $(TOP)/${NRFX_PATH}/drivers/include \ $(TOP)/${NRFX_PATH}/drivers/src \ -SRC_S += ${NRFX_PATH}/mdk/gcc_startup_$(MCU_VARIANT).S - ASFLAGS += -D__HEAP_SIZE=0 - -# For flash-jlink target -JLINK_DEVICE ?= $(MCU_VARIANT)_xxaa diff --git a/hw/bsp/nrf/linker/nrf52833_xxaa.ld b/hw/bsp/nrf/linker/nrf52833_xxaa.ld index ae4d0e5b3..f4c46a3f1 100644 --- a/hw/bsp/nrf/linker/nrf52833_xxaa.ld +++ b/hw/bsp/nrf/linker/nrf52833_xxaa.ld @@ -12,9 +12,3 @@ MEMORY INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf52840_s140_v6.ld b/hw/bsp/nrf/linker/nrf52840_s140_v6.ld index 037a14196..1a2292269 100644 --- a/hw/bsp/nrf/linker/nrf52840_s140_v6.ld +++ b/hw/bsp/nrf/linker/nrf52840_s140_v6.ld @@ -36,9 +36,3 @@ SECTIONS } INSERT AFTER .data; INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf52840_xxaa.ld b/hw/bsp/nrf/linker/nrf52840_xxaa.ld index 2d20ba7ac..fcfe08a60 100644 --- a/hw/bsp/nrf/linker/nrf52840_xxaa.ld +++ b/hw/bsp/nrf/linker/nrf52840_xxaa.ld @@ -12,9 +12,3 @@ MEMORY } INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld b/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld index 31762d0b2..7fd682a40 100644 --- a/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld +++ b/hw/bsp/nrf/linker/nrf5340_xxaa_application.ld @@ -13,9 +13,3 @@ MEMORY INCLUDE "nrf_common.ld" - -/* nrfx v2 linker does not define __tbss_start/end__ __sbss_start/end__*/ -__tbss_start__ = __tbss_start; -__tbss_end__ = __tbss_end; -__sbss_start__ = __sbss_start; -__sbss_end__ = __sbss_end; diff --git a/hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld b/hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld new file mode 100644 index 000000000..0c8d7127a --- /dev/null +++ b/hw/bsp/nrf/linker/nrf54h20_xxaa_application.ld @@ -0,0 +1,21 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +/*GROUP(-lgcc -lc) not compatible with clang*/ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0xE0A0000, LENGTH = 0x40000 /* Inside global MRAM0 */ + FLASH1 (rx) : ORIGIN = 0x2F840000, LENGTH = 0x4000 /* OTP0 */ + EXTFLASH (rx) : ORIGIN = 0x70000000, LENGTH = 0x20000000 + RAM (rwx) : ORIGIN = 0x22000000, LENGTH = 0x8000 + RAM1 (rwx) : ORIGIN = 0x2F000000, LENGTH = 0x80000 /* RAM00 */ + RAM2 (rwx) : ORIGIN = 0x2F080000, LENGTH = 0x60000 /* RAM01 */ + RAM3 (rwx) : ORIGIN = 0x2F880000, LENGTH = 0x10000 /* RAM20 */ + RAM4 (rwx) : ORIGIN = 0x2F890000, LENGTH = 0x8000 /* RAM21 */ + RAM5 (rwx) : ORIGIN = 0x2FC00000, LENGTH = 0x4000 /* RAM30 (low-speed) */ + RAM6 (rwx) : ORIGIN = 0x2FC04000, LENGTH = 0x4000 /* RAM31 (low-speed) */ +} + + +INCLUDE "nrf_common.ld" diff --git a/hw/bsp/nrf/nrfx_config/nrfx_config.h b/hw/bsp/nrf/nrfx_config/nrfx_config.h index fbec4192b..88431e42c 100644 --- a/hw/bsp/nrf/nrfx_config/nrfx_config.h +++ b/hw/bsp/nrf/nrfx_config/nrfx_config.h @@ -1,46 +1,111 @@ +/* + * Copyright (c) 2019 - 2025, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef NRFX_CONFIG_H__ #define NRFX_CONFIG_H__ -#define NRFX_POWER_ENABLED 1 -#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7 - -#define NRFX_CLOCK_ENABLED 0 -#define NRFX_GPIOTE_ENABLED 1 -#define NRFX_GPIOTE0_ENABLED 1 - -#define NRFX_UARTE_ENABLED 1 -#define NRFX_UARTE0_ENABLED 1 - -#define NRFX_SPIM_ENABLED 1 -#define NRFX_SPIM1_ENABLED 1 // use SPI1 since nrf5340 share uart with spi - -#define NRFX_PRS_ENABLED 0 -#define NRFX_USBREG_ENABLED 1 +#include "nrfx_config_common.h" #if defined(NRF51) -#include <templates/nrfx_config_nrf51.h> + #include <templates/nrfx_config_nrf51.h> #elif defined(NRF52805_XXAA) -#include <templates/nrfx_config_nrf52805.h> + #include <templates/nrfx_config_nrf52805.h> #elif defined(NRF52810_XXAA) -#include <templates/nrfx_config_nrf52810.h> + #include <templates/nrfx_config_nrf52810.h> #elif defined(NRF52811_XXAA) -#include <templates/nrfx_config_nrf52811.h> + #include <templates/nrfx_config_nrf52811.h> #elif defined(NRF52820_XXAA) -#include <templates/nrfx_config_nrf52820.h> + #include <templates/nrfx_config_nrf52820.h> #elif defined(NRF52832_XXAA) || defined (NRF52832_XXAB) -#include <templates/nrfx_config_nrf52832.h> + #include <templates/nrfx_config_nrf52832.h> #elif defined(NRF52833_XXAA) -#include <templates/nrfx_config_nrf52833.h> + #include <templates/nrfx_config_nrf52833.h> #elif defined(NRF52840_XXAA) -#include <templates/nrfx_config_nrf52840.h> + #include <templates/nrfx_config_nrf52840.h> #elif defined(NRF5340_XXAA_APPLICATION) -#include <templates/nrfx_config_nrf5340_application.h> + #include <templates/nrfx_config_nrf5340_application.h> #elif defined(NRF5340_XXAA_NETWORK) #include <templates/nrfx_config_nrf5340_network.h> +#elif defined(NRF54H20_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf54h20_application.h> +#elif defined(NRF54H20_XXAA) && defined(NRF_RADIOCORE) + #include <templates/nrfx_config_nrf54h20_radiocore.h> +#elif defined(NRF54H20_XXAA) && defined(NRF_PPR) + #include <templates/nrfx_config_nrf54h20_ppr.h> +#elif defined(NRF54H20_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf54h20_flpr.h> +#elif defined(NRF54L05_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf54l05_application.h> +#elif defined(NRF54L05_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf54l05_flpr.h> +#elif defined(NRF54L10_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf54l10_application.h> +#elif defined(NRF54L10_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf54l10_flpr.h> +#elif defined(NRF54L15_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf54l15_application.h> +#elif defined(NRF54L15_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf54l15_flpr.h> +#elif defined(NRF54LM20A_ENGA_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf54lm20a_enga_application.h> +#elif defined(NRF54LM20A_ENGA_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf54lm20a_enga_flpr.h> +#elif defined(NRF54LS05B_ENGA_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf54ls05b_application.h> +#elif defined(NRF54LV10A_ENGA_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf54lv10a_enga_application.h> +#elif defined(NRF54LV10A_ENGA_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf54lv10a_enga_flpr.h> +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf7120_application.h> +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf7120_flpr.h> +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_LMAC) + #include <templates/nrfx_config_nrf7120_lmac.h> +#elif defined(NRF7120_ENGA_XXAA) && defined(NRF_UMAC) + #include <templates/nrfx_config_nrf7120_umac.h> #elif defined(NRF9120_XXAA) || defined(NRF9160_XXAA) #include <templates/nrfx_config_nrf91.h> +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_APPLICATION) + #include <templates/nrfx_config_nrf9230_engb_application.h> +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_RADIOCORE) + #include <templates/nrfx_config_nrf9230_engb_radiocore.h> +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_PPR) + #include <templates/nrfx_config_nrf9230_engb_ppr.h> +#elif defined(NRF9230_ENGB_XXAA) && defined(NRF_FLPR) + #include <templates/nrfx_config_nrf9230_engb_flpr.h> #else - #error "Unknown device." + #include "nrfx_config_ext.h" #endif #endif // NRFX_CONFIG_H__ diff --git a/hw/bsp/nrf/nrfx_config/nrfx_config_common.h b/hw/bsp/nrf/nrfx_config/nrfx_config_common.h new file mode 100644 index 000000000..a5a29bb8e --- /dev/null +++ b/hw/bsp/nrf/nrfx_config/nrfx_config_common.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2022 - 2025, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NRFX_CONFIG_COMMON_H__ +#define NRFX_CONFIG_COMMON_H__ + +#ifndef NRFX_CONFIG_H__ +#error "This file should not be included directly. Include nrfx_config.h instead." +#endif + +/** @brief Symbol specifying major version of the nrfx API to be used. */ +#ifndef NRFX_CONFIG_API_VER_MAJOR +#define NRFX_CONFIG_API_VER_MAJOR 3 +#endif + +/** @brief Symbol specifying minor version of the nrfx API to be used. */ +#ifndef NRFX_CONFIG_API_VER_MINOR +#define NRFX_CONFIG_API_VER_MINOR 12 +#endif + +/** @brief Symbol specifying micro version of the nrfx API to be used. */ +#ifndef NRFX_CONFIG_API_VER_MICRO +#define NRFX_CONFIG_API_VER_MICRO 0 +#endif + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +#define NRFX_CLOCK_ENABLED 0 +#define NRFX_UARTE_ENABLED 1 + +#if defined(NRF54H20_XXAA) +#define NRFX_UARTE120_ENABLED 1 + +#else + +#define NRFX_POWER_ENABLED 1 +#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7 + +#define NRFX_UARTE0_ENABLED 1 + +#define NRFX_GPIOTE_ENABLED 1 +#define NRFX_GPIOTE0_ENABLED 1 + +#define NRFX_SPIM_ENABLED 1 +#define NRFX_SPIM1_ENABLED 1 // use SPI1 since nrf5340 share uart with spi +#endif + +#define NRFX_PRS_ENABLED 0 +#define NRFX_USBREG_ENABLED 1 + +#define NRF_STATIC_INLINE static inline + +#endif /* NRFX_CONFIG_COMMON_H__ */ diff --git a/hw/bsp/nrf/nrfx_config/nrfx_config_ext.h b/hw/bsp/nrf/nrfx_config/nrfx_config_ext.h new file mode 100644 index 000000000..e503e1399 --- /dev/null +++ b/hw/bsp/nrf/nrfx_config/nrfx_config_ext.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 - 2025, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NRFX_CONFIG_EXT_H__ +#define NRFX_CONFIG_EXT_H__ + +#error "Unknown device." + +#endif // NRFX_CONFIG_EXT_H__ diff --git a/hw/bsp/saml2x/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h index 6c9ecae2d..dfac55a91 100644 --- a/hw/bsp/saml2x/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/nuc100_120/FreeRTOSConfig/FreeRTOSConfig.h @@ -44,16 +44,12 @@ // skip if included from IAR assembler #ifndef __IASMARM__ - #include "sam.h" +#include "NUC100Series.h" #endif -/* Cortex M23/M33 port configuration. */ +/* Cortex-M0 port configuration. */ #define configENABLE_MPU 0 -#if defined(__ARM_FP) && __ARM_FP >= 4 - #define configENABLE_FPU 1 -#else - #define configENABLE_FPU 0 -#endif +#define configENABLE_FPU 0 #define configENABLE_TRUSTZONE 0 #define configMINIMAL_SECURE_STACK_SIZE (1024) @@ -131,6 +127,7 @@ //--------------------------------------------------------------------+ // For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +// NUC121/125 has 2 priority bits #define configPRIO_BITS 2 /* The lowest interrupt priority that can be used in a call to a "set priority" function. */ diff --git a/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.cmake b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.cmake new file mode 100644 index 000000000..02198d4c3 --- /dev/null +++ b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.cmake @@ -0,0 +1,5 @@ +set(JLINK_DEVICE NUC120LE3) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/nuc120_flash.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.h b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.h new file mode 100644 index 000000000..b6f1adf30 --- /dev/null +++ b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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_PORT PB +#define LED_PIN 0 +#define LED_PIN_IO PB0 +#define LED_STATE_ON 0 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.mk b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.mk new file mode 100644 index 000000000..5f8fa6d0b --- /dev/null +++ b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/board.mk @@ -0,0 +1,2 @@ +JLINK_DEVICE = NUC120LE3 +LD_FILE = $(BOARD_PATH)/nuc120_flash.ld diff --git a/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/nuc120_flash.ld index cab12c8b9..cab12c8b9 100644 --- a/hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld +++ b/hw/bsp/nuc100_120/boards/nutiny_sdk_nuc120/nuc120_flash.ld diff --git a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c b/hw/bsp/nuc100_120/family.c index 18a189d8c..d04dc6657 100644 --- a/hw/bsp/nutiny_sdk_nuc120/nutiny_sdk_nuc120.c +++ b/hw/bsp/nuc100_120/family.c @@ -25,6 +25,8 @@ */ #include "bsp/board_api.h" +#include "board.h" + #include "NUC100Series.h" #include "clk.h" #include "sys.h" @@ -37,14 +39,6 @@ void USBD_IRQHandler(void) tud_int_handler(0); } -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -#define LED_PORT PB -#define LED_PIN 0 -#define LED_PIN_IO PB0 -#define LED_STATE_ON 0 - void board_init(void) { SYS_UnlockReg(); diff --git a/hw/bsp/nuc100_120/family.cmake b/hw/bsp/nuc100_120/family.cmake new file mode 100644 index 000000000..b8f36bb9b --- /dev/null +++ b/hw/bsp/nuc100_120/family.cmake @@ -0,0 +1,89 @@ +include_guard() + +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/nuvoton/nuc100_120) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +set(CMAKE_SYSTEM_CPU cortex-m0 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(OPENOCD_OPTION "-f interface/nulink.cfg -f target/numicroM0.cfg") + +set(FAMILY_MCUS NUC100 NUC120 CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/Device/Nuvoton/NUC100Series/Source/GCC/startup_NUC100Series.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Device/Nuvoton/NUC100Series/Source/system_NUC100Series.c + ${SDK_DIR}/StdDriver/src/clk.c + ${SDK_DIR}/StdDriver/src/gpio.c + ${SDK_DIR}/StdDriver/src/sys.c + ${SDK_DIR}/StdDriver/src/timer.c + ${SDK_DIR}/StdDriver/src/uart.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Device/Nuvoton/NUC100Series/Include + ${SDK_DIR}/StdDriver/inc + ${SDK_DIR}/CMSIS/Include + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_EXAMPLE_MSC_READONLY + CFG_EXAMPLE_VIDEO_READONLY + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_NUC120) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nuvoton/nuc120/dcd_nuc120.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + family_flash_openocd_nuvoton(${TARGET}) +endfunction() diff --git a/hw/bsp/nutiny_sdk_nuc120/board.mk b/hw/bsp/nuc100_120/family.mk index d982bdc06..f9afb4f72 100644 --- a/hw/bsp/nutiny_sdk_nuc120/board.mk +++ b/hw/bsp/nuc100_120/family.mk @@ -1,16 +1,16 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m0 \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_EXAMPLE_VIDEO_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_NUC120 +CPU_CORE ?= cortex-m0 + LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/nutiny_sdk_nuc120/nuc120_flash.ld +# LD_FILE is defined in board.mk SRC_C += \ src/portable/nuvoton/nuc120/dcd_nuc120.c \ @@ -27,15 +27,13 @@ SRC_S += \ INC += \ $(TOP)/hw/mcu/nuvoton/nuc100_120/Device/Nuvoton/NUC100Series/Include \ $(TOP)/hw/mcu/nuvoton/nuc100_120/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc100_120/CMSIS/Include + $(TOP)/hw/mcu/nuvoton/nuc100_120/CMSIS/Include \ + $(TOP)/$(BOARD_PATH) -# For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 -# For flash-jlink target -JLINK_DEVICE = NUC120LE3 - # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source +OPENOCD_NUVOTON_PATH ?= $(HOME)/app/OpenOCD-Nuvoton flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" + $(OPENOCD_NUVOTON_PATH)/src/openocd -s $(OPENOCD_NUVOTON_PATH)/tcl -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..e8f120553 --- /dev/null +++ b/hw/bsp/nuc121_125/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "NuMicro.h" +#endif + +/* Cortex-M0 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +// NUC121/125 has 2 priority bits +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif diff --git a/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.cmake b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.cmake new file mode 100644 index 000000000..bffeffc37 --- /dev/null +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.cmake @@ -0,0 +1,6 @@ +set(NUC_SERIES nuc121) +set(JLINK_DEVICE NUC121SC2AE) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/nuc121_flash.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.h b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.h new file mode 100644 index 000000000..73e73d5b3 --- /dev/null +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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_PORT PB +#define LED_PIN 4 +#define LED_PIN_IO PB4 +#define LED_STATE_ON 0 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.mk b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.mk new file mode 100644 index 000000000..8c8b4aa11 --- /dev/null +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/board.mk @@ -0,0 +1,3 @@ +NUC_SERIES = nuc121 +JLINK_DEVICE = NUC121SC2AE +LD_FILE = $(BOARD_PATH)/nuc121_flash.ld diff --git a/hw/bsp/nutiny_nuc121s/nuc121_flash.ld b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/nuc121_flash.ld index 0c599a561..0c599a561 100644 --- a/hw/bsp/nutiny_nuc121s/nuc121_flash.ld +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc121/nuc121_flash.ld diff --git a/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.cmake b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.cmake new file mode 100644 index 000000000..7909c0a46 --- /dev/null +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.cmake @@ -0,0 +1,6 @@ +set(NUC_SERIES nuc125) +set(JLINK_DEVICE NUC125SC2AE) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/nuc125_flash.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.h b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.h new file mode 100644 index 000000000..73e73d5b3 --- /dev/null +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.h @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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_PORT PB +#define LED_PIN 4 +#define LED_PIN_IO PB4 +#define LED_STATE_ON 0 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.mk b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.mk new file mode 100644 index 000000000..7f61b94f3 --- /dev/null +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/board.mk @@ -0,0 +1,3 @@ +NUC_SERIES = nuc125 +JLINK_DEVICE = NUC125SC2AE +LD_FILE = $(BOARD_PATH)/nuc125_flash.ld diff --git a/hw/bsp/nutiny_nuc125s/nuc125_flash.ld b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/nuc125_flash.ld index 0c599a561..0c599a561 100644 --- a/hw/bsp/nutiny_nuc125s/nuc125_flash.ld +++ b/hw/bsp/nuc121_125/boards/nutiny_sdk_nuc125/nuc125_flash.ld diff --git a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c b/hw/bsp/nuc121_125/family.c index 7cb9b2e69..089855207 100644 --- a/hw/bsp/nutiny_nuc121s/nutiny_nuc121.c +++ b/hw/bsp/nuc121_125/family.c @@ -25,6 +25,8 @@ */ #include "bsp/board_api.h" +#include "board.h" + #include "NuMicro.h" #include "clk.h" #include "sys.h" @@ -38,12 +40,8 @@ void USBD_IRQHandler(void) } //--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM +// Board Initialization //--------------------------------------------------------------------+ -#define LED_PORT PB -#define LED_PIN 4 -#define LED_PIN_IO PB4 -#define LED_STATE_ON 0 void board_init(void) { diff --git a/hw/bsp/nuc121_125/family.cmake b/hw/bsp/nuc121_125/family.cmake new file mode 100644 index 000000000..ee52e9ce4 --- /dev/null +++ b/hw/bsp/nuc121_125/family.cmake @@ -0,0 +1,94 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/nuvoton/nuc121_125) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m0 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(OPENOCD_OPTION "-f interface/nulink.cfg -f target/numicroM0.cfg") + +set(FAMILY_MCUS NUC121 CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/Device/Nuvoton/NUC121/Source/GCC/startup_NUC121.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + # Common sources for all NUC12x + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Device/Nuvoton/NUC121/Source/system_NUC121.c + ${SDK_DIR}/StdDriver/src/clk.c + ${SDK_DIR}/StdDriver/src/gpio.c + ${SDK_DIR}/StdDriver/src/fmc.c + ${SDK_DIR}/StdDriver/src/sys.c + ${SDK_DIR}/StdDriver/src/timer.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Device/Nuvoton/NUC121/Include + ${SDK_DIR}/StdDriver/inc + ${SDK_DIR}/CMSIS/Include + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + __ARM_FEATURE_DSP=0 + USE_ASSERT=0 + CFG_EXAMPLE_MSC_READONLY + ) + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_NUC121) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nuvoton/nuc121/dcd_nuc121.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + family_flash_openocd_nuvoton(${TARGET}) +endfunction() diff --git a/hw/bsp/nutiny_nuc121s/board.mk b/hw/bsp/nuc121_125/family.mk index 06c47d544..f46dac6e4 100644 --- a/hw/bsp/nutiny_nuc121s/board.mk +++ b/hw/bsp/nuc121_125/family.mk @@ -1,30 +1,34 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m0 \ -D__ARM_FEATURE_DSP=0 \ -DUSE_ASSERT=0 \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_NUC121 +CPU_CORE ?= cortex-m0 + # mcu driver cause following warnings CFLAGS += -Wno-error=redundant-decls -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs +LDFLAGS_GCC += \ + --specs=nosys.specs --specs=nano.specs # All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/nuc121_flash.ld +# LD_FILE is defined in board.mk +# Common sources for all NUC12x variants SRC_C += \ src/portable/nuvoton/nuc121/dcd_nuc121.c \ hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Source/system_NUC121.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/clk.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/fmc.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/gpio.c \ + hw/mcu/nuvoton/nuc121_125/StdDriver/src/fmc.c \ hw/mcu/nuvoton/nuc121_125/StdDriver/src/sys.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/timer.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/uart.c + hw/mcu/nuvoton/nuc121_125/StdDriver/src/timer.c + +# Additional sources are added in board.mk if needed (e.g., fmc, sys, timer, uart for NUC121) SRC_S += \ hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Source/GCC/startup_NUC121.S @@ -32,15 +36,14 @@ SRC_S += \ INC += \ $(TOP)/hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Include \ $(TOP)/hw/mcu/nuvoton/nuc121_125/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc121_125/CMSIS/Include + $(TOP)/hw/mcu/nuvoton/nuc121_125/CMSIS/Include \ + $(TOP)/$(BOARD_PATH) # For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 -# For flash-jlink target -JLINK_DEVICE = NUC121SC2AE - # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source +OPENOCD_NUVOTON_PATH ?= $(HOME)/app/OpenOCD-Nuvoton flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" + $(OPENOCD_NUVOTON_PATH)/src/openocd -s $(OPENOCD_NUVOTON_PATH)/tcl -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..e8f120553 --- /dev/null +++ b/hw/bsp/nuc126/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "NuMicro.h" +#endif + +/* Cortex-M0 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +// NUC121/125 has 2 priority bits +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif diff --git a/hw/bsp/nuc126/boards/nutiny_nuc126v/board.cmake b/hw/bsp/nuc126/boards/nutiny_nuc126v/board.cmake new file mode 100644 index 000000000..8d5c73e02 --- /dev/null +++ b/hw/bsp/nuc126/boards/nutiny_nuc126v/board.cmake @@ -0,0 +1,5 @@ +set(JLINK_DEVICE NUC126VG4AE) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/nuc126_flash.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nuc126/boards/nutiny_nuc126v/board.h b/hw/bsp/nuc126/boards/nutiny_nuc126v/board.h new file mode 100644 index 000000000..82b2c1bd5 --- /dev/null +++ b/hw/bsp/nuc126/boards/nutiny_nuc126v/board.h @@ -0,0 +1,46 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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_PORT PC +#define LED_PIN 9 +#define LED_PIN_IO PC9 +#define LED_STATE_ON 0 + +#define CRYSTAL_LESS /* system will be 48MHz when defined, otherwise, system is 72MHz */ +#define HIRC48_AUTO_TRIM SYS_IRCTCTL1_REFCKSEL_Msk | (1UL << SYS_IRCTCTL1_LOOPSEL_Pos) | (2UL << SYS_IRCTCTL1_FREQSEL_Pos) + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/nuc126/boards/nutiny_nuc126v/board.mk b/hw/bsp/nuc126/boards/nutiny_nuc126v/board.mk new file mode 100644 index 000000000..3050ea162 --- /dev/null +++ b/hw/bsp/nuc126/boards/nutiny_nuc126v/board.mk @@ -0,0 +1,2 @@ +JLINK_DEVICE = NUC126VG4AE +LD_FILE = $(BOARD_PATH)/nuc126_flash.ld diff --git a/hw/bsp/nutiny_nuc126v/nuc126_flash.ld b/hw/bsp/nuc126/boards/nutiny_nuc126v/nuc126_flash.ld index b23890b4b..b23890b4b 100644 --- a/hw/bsp/nutiny_nuc126v/nuc126_flash.ld +++ b/hw/bsp/nuc126/boards/nutiny_nuc126v/nuc126_flash.ld diff --git a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c b/hw/bsp/nuc126/family.c index 9974127a8..f992fcab4 100644 --- a/hw/bsp/nutiny_nuc126v/nutiny_nuc126.c +++ b/hw/bsp/nuc126/family.c @@ -25,6 +25,8 @@ */ #include "bsp/board_api.h" +#include "board.h" + #include "NuMicro.h" #include "clk.h" #include "sys.h" @@ -37,17 +39,6 @@ void USBD_IRQHandler(void) { tud_int_handler(0); } - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -#define LED_PORT PC -#define LED_PIN 9 -#define LED_PIN_IO PC9 -#define LED_STATE_ON 0 - -#define CRYSTAL_LESS /* system will be 48MHz when defined, otherwise, system is 72MHz */ -#define HIRC48_AUTO_TRIM SYS_IRCTCTL1_REFCKSEL_Msk | (1UL << SYS_IRCTCTL1_LOOPSEL_Pos) | (2UL << SYS_IRCTCTL1_FREQSEL_Pos) #define TRIM_INIT (SYS_BASE+0x118) void board_init(void) diff --git a/hw/bsp/nuc126/family.cmake b/hw/bsp/nuc126/family.cmake new file mode 100644 index 000000000..d0f99ba1a --- /dev/null +++ b/hw/bsp/nuc126/family.cmake @@ -0,0 +1,97 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/nuvoton/nuc126) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m0 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(OPENOCD_OPTION "-f interface/nulink.cfg -f target/numicroM0.cfg") + +set(FAMILY_MCUS NUC126 CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/Device/Nuvoton/NUC126/Source/GCC/startup_NUC126.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Device/Nuvoton/NUC126/Source/system_NUC126.c + ${SDK_DIR}/StdDriver/src/clk.c + ${SDK_DIR}/StdDriver/src/crc.c + ${SDK_DIR}/StdDriver/src/gpio.c + ${SDK_DIR}/StdDriver/src/rtc.c + ${SDK_DIR}/StdDriver/src/sys.c + ${SDK_DIR}/StdDriver/src/timer.c + ${SDK_DIR}/StdDriver/src/uart.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Device/Nuvoton/NUC126/Include + ${SDK_DIR}/StdDriver/inc + ${SDK_DIR}/CMSIS/Include + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + __ARM_FEATURE_DSP=0 + USE_ASSERT=0 + CFG_EXAMPLE_VIDEO_READONLY + __CORTEX_SC=0 + ) + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_NUC126) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nuvoton/nuc121/dcd_nuc121.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + family_flash_openocd_nuvoton(${TARGET}) +endfunction() diff --git a/hw/bsp/nutiny_nuc126v/board.mk b/hw/bsp/nuc126/family.mk index e87d1aad0..37df7aaab 100644 --- a/hw/bsp/nutiny_nuc126v/board.mk +++ b/hw/bsp/nuc126/family.mk @@ -1,21 +1,22 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m0 \ -D__ARM_FEATURE_DSP=0 \ -DUSE_ASSERT=0 \ -DCFG_EXAMPLE_VIDEO_READONLY \ -D__CORTEX_SC=0 \ -DCFG_TUSB_MCU=OPT_MCU_NUC126 +CPU_CORE ?= cortex-m0 + # mcu driver cause following warnings CFLAGS += -Wno-error=redundant-decls LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs # All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/nuc126_flash.ld +# LD_FILE is defined in board.mk SRC_C += \ src/portable/nuvoton/nuc121/dcd_nuc121.c \ @@ -34,15 +35,14 @@ SRC_S += \ INC += \ $(TOP)/hw/mcu/nuvoton/nuc126/Device/Nuvoton/NUC126/Include \ $(TOP)/hw/mcu/nuvoton/nuc126/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc126/CMSIS/Include + $(TOP)/hw/mcu/nuvoton/nuc126/CMSIS/Include \ + $(TOP)/$(BOARD_PATH) # For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 -# For flash-jlink target -JLINK_DEVICE = NUC126VG4AE - # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source +OPENOCD_NUVOTON_PATH ?= $(HOME)/app/OpenOCD-Nuvoton flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" + $(OPENOCD_NUVOTON_PATH)/src/openocd -s $(OPENOCD_NUVOTON_PATH)/tcl -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..a44beb767 --- /dev/null +++ b/hw/bsp/nuc505/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,150 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ +#include "NUC505Series.h" +#endif + +/* Cortex-M4F port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +// NUC505 has 3 priority bits +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif diff --git a/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.cmake b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.cmake new file mode 100644 index 000000000..2ece10e33 --- /dev/null +++ b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.cmake @@ -0,0 +1,5 @@ +set(JLINK_DEVICE NUC505YO13Y) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/nuc505_flashtoram.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.h b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.h new file mode 100644 index 000000000..ec3c15f46 --- /dev/null +++ b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.h @@ -0,0 +1,42 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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_PORT PC +#define LED_PIN 3 +#define LED_STATE_ON 0 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.mk b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.mk new file mode 100644 index 000000000..f189de163 --- /dev/null +++ b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/board.mk @@ -0,0 +1,2 @@ +JLINK_DEVICE = NUC505YO13Y +LD_FILE = $(BOARD_PATH)/nuc505_flashtoram.ld diff --git a/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/nuc505_flashtoram.ld index 53d385cd0..53d385cd0 100644 --- a/hw/bsp/nutiny_sdk_nuc505/nuc505_flashtoram.ld +++ b/hw/bsp/nuc505/boards/nutiny_sdk_nuc505/nuc505_flashtoram.ld diff --git a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c b/hw/bsp/nuc505/family.c index 3ec0066a3..00ed92310 100644 --- a/hw/bsp/nutiny_sdk_nuc505/nutiny_sdk_nuc505.c +++ b/hw/bsp/nuc505/family.c @@ -25,6 +25,7 @@ */ #include "bsp/board_api.h" +#include "board.h" #include "NUC505Series.h" //--------------------------------------------------------------------+ @@ -38,9 +39,6 @@ void USBD_IRQHandler(void) //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -#define LED_PORT PC -#define LED_PIN 3 -#define LED_STATE_ON 0 void board_init(void) { diff --git a/hw/bsp/nuc505/family.cmake b/hw/bsp/nuc505/family.cmake new file mode 100644 index 000000000..581cad4d0 --- /dev/null +++ b/hw/bsp/nuc505/family.cmake @@ -0,0 +1,93 @@ +include_guard() + +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/nuvoton/nuc505) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) +set(OPENOCD_OPTION "-f interface/nulink.cfg -f target/numicroM4.cfg") + +set(FAMILY_MCUS NUC505 CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/Device/Nuvoton/NUC505Series/Source/GCC/startup_NUC505Series.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/Device/Nuvoton/NUC505Series/Source/system_NUC505Series.c + ${SDK_DIR}/StdDriver/src/adc.c + ${SDK_DIR}/StdDriver/src/clk.c + ${SDK_DIR}/StdDriver/src/gpio.c + ${SDK_DIR}/StdDriver/src/i2c.c + ${SDK_DIR}/StdDriver/src/i2s.c + ${SDK_DIR}/StdDriver/src/pwm.c + ${SDK_DIR}/StdDriver/src/rtc.c + ${SDK_DIR}/StdDriver/src/spi.c + ${SDK_DIR}/StdDriver/src/spim.c + ${SDK_DIR}/StdDriver/src/sys.c + ${SDK_DIR}/StdDriver/src/timer.c + ${SDK_DIR}/StdDriver/src/uart.c + ${SDK_DIR}/StdDriver/src/wdt.c + ${SDK_DIR}/StdDriver/src/wwdt.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/Device/Nuvoton/NUC505Series/Include + ${SDK_DIR}/StdDriver/inc + ${SDK_DIR}/CMSIS/Include + ) + + update_board(${BOARD_TARGET}) +endfunction() + + +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_NUC505) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/nuvoton/nuc505/dcd_nuc505.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_Clang}") + target_compile_options(${TARGET} PRIVATE -Wno-redundant-decls) + + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES + COMPILE_FLAGS "-Wno-missing-prototypes -Wno-redundant-decls") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + family_flash_openocd_nuvoton(${TARGET}) +endfunction() diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nuc505/family.mk index 1dc8b244e..e1f25e2db 100644 --- a/hw/bsp/nutiny_sdk_nuc505/board.mk +++ b/hw/bsp/nuc505/family.mk @@ -1,19 +1,17 @@ +include $(TOP)/$(BOARD_PATH)/board.mk + CFLAGS += \ -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m4 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ -DCFG_TUSB_MCU=OPT_MCU_NUC505 +CPU_CORE ?= cortex-m4 + # mcu driver cause following warnings CFLAGS += -Wno-error=redundant-decls LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/nuc505_flashtoram.ld +# LD_FILE is defined in board.mk SRC_C += \ src/portable/nuvoton/nuc505/dcd_nuc505.c \ @@ -39,25 +37,19 @@ SRC_S += \ INC += \ $(TOP)/hw/mcu/nuvoton/nuc505/Device/Nuvoton/NUC505Series/Include \ $(TOP)/hw/mcu/nuvoton/nuc505/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc505/CMSIS/Include + $(TOP)/hw/mcu/nuvoton/nuc505/CMSIS/Include \ + $(TOP)/$(BOARD_PATH) -# For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F -# For flash-jlink target -JLINK_DEVICE = NUC505YO13Y - # Note # To be able to program the SPI flash, it need to boot with ICP mode "1011". # However, in ICP mode, opencod cannot establish connection to the mcu. # Therefore, there is no easy command line flash for NUC505 # It is probably better to just use Nuvoton NuMicro ICP programming on windows to program the board -# - 1111 "SPI" (run from internal flash) -# - 1110 "USB" (mass storage emulator that accepts a .bin file) -# - 0111 "ICE-SPI" (allow external debugger access, but may not be programmable) -# - 1011 ICP mode (programmable via NuMicro ICP programming tool) # Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton # Please compile and install it from github source +OPENOCD_NUVOTON_PATH ?= $(HOME)/app/OpenOCD-Nuvoton flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM4.cfg -c "program $< reset exit" + $(OPENOCD_NUVOTON_PATH)/src/openocd -s $(OPENOCD_NUVOTON_PATH)/tcl -f interface/nulink.cfg -f target/numicroM4.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_nuc125s/board.mk b/hw/bsp/nutiny_nuc125s/board.mk deleted file mode 100644 index 50b9d866a..000000000 --- a/hw/bsp/nutiny_nuc125s/board.mk +++ /dev/null @@ -1,42 +0,0 @@ -CFLAGS += \ - -flto \ - -mthumb \ - -mabi=aapcs-linux \ - -mcpu=cortex-m0 \ - -D__ARM_FEATURE_DSP=0 \ - -DUSE_ASSERT=0 \ - -DCFG_EXAMPLE_MSC_READONLY \ - -DCFG_TUSB_MCU=OPT_MCU_NUC121 - -# mcu driver cause following warnings -CFLAGS += -Wno-error=redundant-decls - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -# All source paths should be relative to the top level. -LD_FILE = hw/bsp/$(BOARD)/nuc125_flash.ld - -SRC_C += \ - src/portable/nuvoton/nuc121/dcd_nuc121.c \ - hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Source/system_NUC121.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/clk.c \ - hw/mcu/nuvoton/nuc121_125/StdDriver/src/gpio.c - -SRC_S += \ - hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Source/GCC/startup_NUC121.S - -INC += \ - $(TOP)/hw/mcu/nuvoton/nuc121_125/Device/Nuvoton/NUC121/Include \ - $(TOP)/hw/mcu/nuvoton/nuc121_125/StdDriver/inc \ - $(TOP)/hw/mcu/nuvoton/nuc121_125/CMSIS/Include - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM0 - -# For flash-jlink target -JLINK_DEVICE = NUC125SC2AE - -# Flash using Nuvoton's openocd fork at https://github.com/OpenNuvoton/OpenOCD-Nuvoton -# Please compile and install it from github source -flash: $(BUILD)/$(PROJECT).elf - openocd -f interface/nulink.cfg -f target/numicroM0.cfg -c "program $< reset exit" diff --git a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c b/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c deleted file mode 100644 index 7cb9b2e69..000000000 --- a/hw/bsp/nutiny_nuc125s/nutiny_nuc125.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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 "bsp/board_api.h" -#include "NuMicro.h" -#include "clk.h" -#include "sys.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USBD_IRQHandler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -#define LED_PORT PB -#define LED_PIN 4 -#define LED_PIN_IO PB4 -#define LED_STATE_ON 0 - -void board_init(void) -{ - /* Unlock protected registers */ - SYS_UnlockReg(); - - /*---------------------------------------------------------------------------------------------------------*/ - /* Init System Clock */ - /*---------------------------------------------------------------------------------------------------------*/ - - /* Enable Internal HIRC 48 MHz clock */ - CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN); - - /* Waiting for Internal RC clock ready */ - CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk); - - /* Switch HCLK clock source to Internal HIRC and HCLK source divide 1 */ - CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1)); - - /* Enable module clock */ - CLK_EnableModuleClock(USBD_MODULE); - - /* Select module clock source */ - CLK_SetModuleClock(USBD_MODULE, CLK_CLKSEL3_USBDSEL_HIRC, CLK_CLKDIV0_USB(1)); - - /* Enable module clock */ - CLK_EnableModuleClock(USBD_MODULE); - -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(48000000 / 1000); -#endif - - // LED - GPIO_SetMode(LED_PORT, 1 << LED_PIN, GPIO_MODE_OUTPUT); -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ - system_ticks++; -} - -uint32_t board_millis(void) -{ - return system_ticks; -} -#endif - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) -{ - LED_PIN_IO = (state ? LED_STATE_ON : (1-LED_STATE_ON)); -} - -uint32_t board_button_read(void) -{ - return 0; -} - -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; - return 0; -} diff --git a/hw/bsp/ra/family.cmake b/hw/bsp/ra/family.cmake index 42a32631c..c5b1d1a1a 100644 --- a/hw/bsp/ra/family.cmake +++ b/hw/bsp/ra/family.cmake @@ -38,124 +38,100 @@ endif () cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (NOT TARGET ${BOARD_TARGET}) - add_library(${BOARD_TARGET} STATIC - ${FSP_RA}/src/bsp/cmsis/Device/RENESAS/Source/startup.c - ${FSP_RA}/src/bsp/cmsis/Device/RENESAS/Source/system.c - ${FSP_RA}/src/bsp/mcu/all/bsp_clocks.c - ${FSP_RA}/src/bsp/mcu/all/bsp_common.c - ${FSP_RA}/src/bsp/mcu/all/bsp_delay.c - ${FSP_RA}/src/bsp/mcu/all/bsp_group_irq.c - ${FSP_RA}/src/bsp/mcu/all/bsp_guard.c - ${FSP_RA}/src/bsp/mcu/all/bsp_io.c - ${FSP_RA}/src/bsp/mcu/all/bsp_irq.c - ${FSP_RA}/src/bsp/mcu/all/bsp_register_protection.c - ${FSP_RA}/src/bsp/mcu/all/bsp_sbrk.c - ${FSP_RA}/src/bsp/mcu/all/bsp_security.c - ${FSP_RA}/src/r_ioport/r_ioport.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_gen/common_data.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_gen/pin_data.c - ) - - target_compile_options(${BOARD_TARGET} PUBLIC - -ffreestanding - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_cfg/fsp_cfg - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_cfg/fsp_cfg/bsp - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_gen - ${CMSIS_DIR}/CMSIS/Core/Include - ${FSP_RA}/inc - ${FSP_RA}/inc/api - ${FSP_RA}/inc/instances - ${FSP_RA}/src/bsp/cmsis/Device/RENESAS/Include - ${FSP_RA}/src/bsp/mcu/all - ${FSP_RA}/src/bsp/mcu/${MCU_VARIANT} - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_RHPORT=${RHPORT_DEVICE} - BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} - BOARD_TUH_RHPORT=${RHPORT_HOST} - BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} - ) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/script/fsp.ld) +endif () - update_board(${BOARD_TARGET}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${FSP_RA}/src/bsp/cmsis/Device/RENESAS/Source/startup.c + ${FSP_RA}/src/bsp/cmsis/Device/RENESAS/Source/system.c + ${FSP_RA}/src/bsp/mcu/all/bsp_clocks.c + ${FSP_RA}/src/bsp/mcu/all/bsp_common.c + ${FSP_RA}/src/bsp/mcu/all/bsp_delay.c + ${FSP_RA}/src/bsp/mcu/all/bsp_group_irq.c + ${FSP_RA}/src/bsp/mcu/all/bsp_guard.c + ${FSP_RA}/src/bsp/mcu/all/bsp_io.c + ${FSP_RA}/src/bsp/mcu/all/bsp_irq.c + ${FSP_RA}/src/bsp/mcu/all/bsp_register_protection.c + ${FSP_RA}/src/bsp/mcu/all/bsp_sbrk.c + ${FSP_RA}/src/bsp/mcu/all/bsp_security.c + ${FSP_RA}/src/r_ioport/r_ioport.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_gen/common_data.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_gen/pin_data.c + ) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/script/fsp.ld) - endif () + target_compile_options(${BOARD_TARGET} PUBLIC + -ffreestanding + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_cfg/fsp_cfg + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_cfg/fsp_cfg/bsp + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/ra_gen + ${CMSIS_DIR}/CMSIS/Core/Include + ${FSP_RA}/inc + ${FSP_RA}/inc/api + ${FSP_RA}/inc/instances + ${FSP_RA}/src/bsp/cmsis/Device/RENESAS/Include + ${FSP_RA}/src/bsp/mcu/all + ${FSP_RA}/src/bsp/mcu/${MCU_VARIANT} + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} + BOARD_TUH_RHPORT=${RHPORT_HOST} + BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} + ) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - # linker file - "LINKER:--script=${LD_FILE_GNU}" - -L${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/script - -Wl,--defsym=end=__bss_end__ - -nostartfiles - --specs=nano.specs --specs=nosys.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () - endif () + update_board(${BOARD_TARGET}) endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_RAXXX) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - # Explicitly added bsp_rom_registers here, otherwise MCU can be bricked if g_bsp_rom_registers is dropped by linker ${FSP_RA}/src/bsp/mcu/all/bsp_rom_registers.c + ${TOP}/src/portable/renesas/rusb2/dcd_rusb2.c + ${TOP}/src/portable/renesas/rusb2/hcd_rusb2.c + ${TOP}/src/portable/renesas/rusb2/rusb2_common.c ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ) - target_compile_options(${TARGET} PUBLIC - -Wno-error=undef - -Wno-error=strict-prototypes - ) - -# # RA has custom freertos port -# if (NOT TARGET freertos_kernel_port) -# add_library(freertos_kernel_port STATIC) -# target_sources(freertos_kernel_port PUBLIC ${FSP_RA}/src/rm_freertos_port/port.c) -# target_include_directories(freertos_kernel_port PUBLIC ${FSP_RA}/src/rm_freertos_port) -# -# target_link_libraries(freertos_kernel_port PUBLIC freertos_kernel) -# endif () - - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_RAXXX) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/renesas/rusb2/dcd_rusb2.c - ${TOP}/src/portable/renesas/rusb2/hcd_rusb2.c - ${TOP}/src/portable/renesas/rusb2/rusb2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + # linker file + "LINKER:--script=${LD_FILE_GNU}" + -L${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}/script + -Wl,--defsym=end=__bss_end__ + -nostartfiles + --specs=nano.specs --specs=nosys.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${FSP_RA}/src/bsp/mcu/all/bsp_rom_registers.c PROPERTIES COMPILE_FLAGS "-Wno-undef") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () # Flashing family_flash_jlink(${TARGET}) diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index 989140e02..a51b3f758 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -92,7 +92,7 @@ static uart_inst_t *uart_inst; // // 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)(void) { +static bool __no_inline_not_in_flash_func(get_bootsel_button)(void) { const uint CS_PIN_INDEX = 1; // Must disable interrupts, as interrupt handlers may be in flash, and we @@ -105,7 +105,9 @@ bool __no_inline_not_in_flash_func(get_bootsel_button)(void) { 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) {} + for (volatile int i = 0; i < 1000; ++i) { + __nop(); + } // The HI GPIO registers in SIO can observe and control the 6 QSPI pins. // Note the button pulls the pin *low* when pressed. diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 2182e9ad1..5d6d8b40e 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -95,6 +95,7 @@ target_sources(tinyusb_device_base INTERFACE ${TOP}/src/class/hid/hid_device.c ${TOP}/src/class/midi/midi_device.c ${TOP}/src/class/msc/msc_device.c + ${TOP}/src/class/mtp/mtp_device.c ${TOP}/src/class/net/ecm_rndis_device.c ${TOP}/src/class/net/ncm_device.c ${TOP}/src/class/usbtmc/usbtmc_device.c @@ -183,6 +184,43 @@ endif() #------------------------------------ # Functions #------------------------------------ +function(family_add_default_example_warnings TARGET) + # Apply warnings to all TinyUSB interface library sources as well as examples sources + # we cannot set compile options for target since it will not propagate to INTERFACE sources then picosdk files + foreach(TINYUSB_TARGET IN ITEMS tinyusb_common_base tinyusb_device_base tinyusb_host_base tinyusb_host_max3421 tinyusb_bsp) + get_target_property(TINYUSB_SOURCES ${TINYUSB_TARGET} INTERFACE_SOURCES) + set_source_files_properties(${TINYUSB_SOURCES} PROPERTIES COMPILE_OPTIONS "${WARN_FLAGS_${CMAKE_C_COMPILER_ID}}") + endforeach() + + # Also apply to example sources, but filter out any source files from lib/ (e.g. fatfs) + get_target_property(EXAMPLE_SOURCES ${TARGET} SOURCES) + set(FILTERED_SOURCES "") + foreach(SOURCE_FILE IN LISTS EXAMPLE_SOURCES) + string(FIND "${SOURCE_FILE}" "${TOP}/lib" FOUND_POS) + if(FOUND_POS EQUAL -1) + list(APPEND FILTERED_SOURCES ${SOURCE_FILE}) + endif() + endforeach() + set_source_files_properties(${FILTERED_SOURCES} PROPERTIES COMPILE_OPTIONS "${WARN_FLAGS_${CMAKE_C_COMPILER_ID}}") + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND NO_WARN_RWX_SEGMENTS_SUPPORTED) + target_link_options(${TARGET} PRIVATE "LINKER:--no-warn-rwx-segments") + endif() + + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0) + target_compile_options(${TARGET} PRIVATE -Wconversion) + endif() + + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) + target_compile_options(${TARGET} PRIVATE -Wcast-function-type -Wstrict-overflow) + endif() + + if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) + target_compile_options(${TARGET} PRIVATE -Wno-strict-aliasing) + endif() + endif() +endfunction() function(family_configure_target TARGET RTOS) if (RTOS STREQUAL noos OR RTOS STREQUAL "") @@ -203,7 +241,7 @@ function(family_configure_target TARGET RTOS) pico_enable_stdio_uart(${TARGET} 1) target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_board${RTOS_SUFFIX} tinyusb_additions) - family_flash_openocd(${TARGET}) + family_flash_openocd(${TARGET}) family_flash_jlink(${TARGET}) endfunction() @@ -358,34 +396,9 @@ function(suppress_tinyusb_warnings) ${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/hcd_rp2040.c ) foreach(SOURCE_FILE IN LISTS CONVERSION_WARNING_FILES) - set_source_files_properties( - ${SOURCE_FILE} - PROPERTIES - COMPILE_FLAGS "-Wno-conversion") + set_source_files_properties(${SOURCE_FILE} PROPERTIES COMPILE_FLAGS "-Wno-conversion") endforeach() endif() - if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/fatfs/source/ff.c - COMPILE_FLAGS "-Wno-stringop-overflow -Wno-array-bounds") - endif() - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/fatfs/source/ff.c - PROPERTIES - COMPILE_FLAGS "-Wno-conversion -Wno-cast-qual") - - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/lwip/src/core/tcp_in.c - ${PICO_TINYUSB_PATH}/lib/lwip/src/core/tcp_out.c - PROPERTIES - COMPILE_FLAGS "-Wno-conversion") - - set_source_files_properties( - ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c - ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c - ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c - PROPERTIES - COMPILE_FLAGS "-Wno-conversion -Wno-sign-conversion") if (TARGET tinyusb_pico_pio_usb) set_source_files_properties( diff --git a/hw/bsp/samd11/family.c b/hw/bsp/samd11/family.c index 79ca9de02..62e060c8e 100644 --- a/hw/bsp/samd11/family.c +++ b/hw/bsp/samd11/family.c @@ -155,12 +155,11 @@ uint32_t board_millis(void) return system_ticks; } -void _init(void) -{ +void _init(void); +void _init(void) { // This _init() standin makes certain GCC environments happier. // They expect the main binary to have a constructor called _init; but don't provide a weak default. // Providing an empty constructor satisfies this odd case, and doesn't harm anything. } - #endif diff --git a/hw/bsp/samd11/family.cmake b/hw/bsp/samd11/family.cmake index 965b1cfb5..982cef792 100644 --- a/hw/bsp/samd11/family.cmake +++ b/hw/bsp/samd11/family.cmake @@ -14,29 +14,22 @@ set(FAMILY_MCUS SAMD11 CACHE INTERNAL "") set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f target/at91samdXX.cfg") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/gcc/system_${SAM_FAMILY}.c ${SDK_DIR}/hal/src/hal_atomic.c ${SDK_DIR}/hpl/gclk/hpl_gclk.c ${SDK_DIR}/hpl/pm/hpl_pm.c ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR} @@ -54,59 +47,49 @@ function(add_board_target BOARD_TARGET) OSC32K_OVERWRITE_CALIBRATION=0 CFG_EXAMPLE_MSC_READONLY CFG_EXAMPLE_VIDEO_READONLY + CFG_EXAMPLE_MTP_READONLY ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_SAMD11) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/microchip/samd/dcd_samd.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_SAMD11) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/microchip/samd/dcd_samd.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/samd11/family.mk b/hw/bsp/samd11/family.mk index c41a0dd37..6f89a2d66 100644 --- a/hw/bsp/samd11/family.mk +++ b/hw/bsp/samd11/family.mk @@ -8,6 +8,7 @@ CFLAGS += \ -DOSC32K_OVERWRITE_CALIBRATION=0 \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_EXAMPLE_VIDEO_READONLY \ + -DCFG_EXAMPLE_MTP_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_SAMD11 # suppress warning caused by vendor mcu driver diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/board.cmake b/hw/bsp/samd21/boards/seeeduino_xiao/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/seeeduino_xiao/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.cmake b/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.cmake deleted file mode 100644 index c1a612936..000000000 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - __SAMD21G18A__ - CFG_EXAMPLE_VIDEO_READONLY - ) -endfunction() diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.mk b/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.mk deleted file mode 100644 index d6c9150b3..000000000 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.mk +++ /dev/null @@ -1,9 +0,0 @@ -CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY - -# All source paths should be relative to the top level. -LD_FILE = $(BOARD_PATH)/$(BOARD).ld - -# For flash-jlink target -JLINK_DEVICE = ATSAMD21G18 - -flash: flash-bossac diff --git a/hw/bsp/samd21/family.cmake b/hw/bsp/samd21/family.cmake deleted file mode 100644 index 3c600318e..000000000 --- a/hw/bsp/samd21/family.cmake +++ /dev/null @@ -1,110 +0,0 @@ -include_guard() - -set(SDK_DIR ${TOP}/hw/mcu/microchip/samd21) - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) - -set(FAMILY_MCUS SAMD21 CACHE INTERNAL "") -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f target/at91samdXX.cfg") - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_samd21.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - add_library(${BOARD_TARGET} STATIC - ${SDK_DIR}/gcc/system_samd21.c - ${SDK_DIR}/hpl/gclk/hpl_gclk.c - ${SDK_DIR}/hpl/pm/hpl_pm.c - ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c - ${SDK_DIR}/hal/src/hal_atomic.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR} - ${SDK_DIR}/config - ${SDK_DIR}/include - ${SDK_DIR}/hal/include - ${SDK_DIR}/hal/utils/include - ${SDK_DIR}/hpl/pm - ${SDK_DIR}/hpl/port - ${SDK_DIR}/hri - ${SDK_DIR}/CMSIS/Include - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CONF_DFLL_OVERWRITE_CALIBRATION=0 - ) - - update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () -endfunction() - - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_SAMD21) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/microchip/samd/dcd_samd.c - ${TOP}/src/portable/microchip/samd/hcd_samd.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - #family_flash_openocd(${TARGET}) -endfunction() diff --git a/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/samd2x_l2x/FreeRTOSConfig/FreeRTOSConfig.h index 6c9ecae2d..6c9ecae2d 100644 --- a/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/samd2x_l2x/FreeRTOSConfig/FreeRTOSConfig.h diff --git a/hw/bsp/samd21/boards/atsamd21_xpro/board.cmake b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.cmake index 46a3880ed..1f6dd9e4f 100644 --- a/hw/bsp/samd21/boards/atsamd21_xpro/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21J18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21j18a_flash.ld) diff --git a/hw/bsp/samd21/boards/atsamd21_xpro/board.h b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.h index 82ab321cf..82ab321cf 100644 --- a/hw/bsp/samd21/boards/atsamd21_xpro/board.h +++ b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.h diff --git a/hw/bsp/samd21/boards/atsamd21_xpro/board.mk b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.mk index 4be547a1b..9127a79e7 100644 --- a/hw/bsp/samd21/boards/atsamd21_xpro/board.mk +++ b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21J18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. diff --git a/hw/bsp/samd21/boards/atsamd21_xpro/samd21j18a_flash.ld b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/samd21j18a_flash.ld index d9b086f9c..d9b086f9c 100644 --- a/hw/bsp/samd21/boards/atsamd21_xpro/samd21j18a_flash.ld +++ b/hw/bsp/samd2x_l2x/boards/atsamd21_xpro/samd21j18a_flash.ld diff --git a/hw/bsp/saml2x/boards/atsaml21_xpro/board.cmake b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.cmake index 874b741cc..874b741cc 100644 --- a/hw/bsp/saml2x/boards/atsaml21_xpro/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.cmake diff --git a/hw/bsp/saml2x/boards/atsaml21_xpro/board.h b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.h index b93b4e591..b93b4e591 100644 --- a/hw/bsp/saml2x/boards/atsaml21_xpro/board.h +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.h diff --git a/hw/bsp/saml2x/boards/atsaml21_xpro/board.mk b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.mk index 4ebfa7e71..4ebfa7e71 100644 --- a/hw/bsp/saml2x/boards/atsaml21_xpro/board.mk +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/board.mk diff --git a/hw/bsp/saml2x/boards/atsaml21_xpro/saml21j18b_flash.ld b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/saml21j18b_flash.ld index f9523451b..f9523451b 100644 --- a/hw/bsp/saml2x/boards/atsaml21_xpro/saml21j18b_flash.ld +++ b/hw/bsp/samd2x_l2x/boards/atsaml21_xpro/saml21j18b_flash.ld diff --git a/hw/bsp/samd21/boards/circuitplayground_express/board.cmake b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.cmake index c1a612936..dedc07594 100644 --- a/hw/bsp/samd21/boards/circuitplayground_express/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21G18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) diff --git a/hw/bsp/samd21/boards/circuitplayground_express/board.h b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.h index bfe2d9951..bfe2d9951 100644 --- a/hw/bsp/samd21/boards/circuitplayground_express/board.h +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.h diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.mk b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.mk index d6c9150b3..f4211e6c8 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/board.mk +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. diff --git a/hw/bsp/samd21/boards/circuitplayground_express/circuitplayground_express.ld b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/circuitplayground_express.ld index ce7aff80b..ce7aff80b 100644 --- a/hw/bsp/samd21/boards/circuitplayground_express/circuitplayground_express.ld +++ b/hw/bsp/samd2x_l2x/boards/circuitplayground_express/circuitplayground_express.ld diff --git a/hw/bsp/samd21/boards/curiosity_nano/board.cmake b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.cmake index ff779c0fd..be744a130 100644 --- a/hw/bsp/samd21/boards/curiosity_nano/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE atsamd21g17a) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21g17a_flash.ld) diff --git a/hw/bsp/samd21/boards/curiosity_nano/board.h b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.h index a2a7385a4..a2a7385a4 100644 --- a/hw/bsp/samd21/boards/curiosity_nano/board.h +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.h diff --git a/hw/bsp/samd21/boards/curiosity_nano/board.mk b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.mk index 112fb6946..b7ebc867e 100644 --- a/hw/bsp/samd21/boards/curiosity_nano/board.mk +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21G17A__ -DCFG_EXAMPLE_MSC_READONLY -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. diff --git a/hw/bsp/samd21/boards/curiosity_nano/samd21g17a_flash.ld b/hw/bsp/samd2x_l2x/boards/curiosity_nano/samd21g17a_flash.ld index e03a4ce60..e03a4ce60 100644 --- a/hw/bsp/samd21/boards/curiosity_nano/samd21g17a_flash.ld +++ b/hw/bsp/samd2x_l2x/boards/curiosity_nano/samd21g17a_flash.ld diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.cmake b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.cmake index fb54b7561..ae739b215 100644 --- a/hw/bsp/samd21/boards/cynthion_d21/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21G18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21g18a_flash.ld) diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.h b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.h index 83782bc65..83782bc65 100644 --- a/hw/bsp/samd21/boards/cynthion_d21/board.h +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.h diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.mk b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.mk index 52c9d60cb..05ca9cb5d 100644 --- a/hw/bsp/samd21/boards/cynthion_d21/board.mk +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/samd21g18a_flash.ld diff --git a/hw/bsp/samd21/boards/cynthion_d21/samd21g18a_flash.ld b/hw/bsp/samd2x_l2x/boards/cynthion_d21/samd21g18a_flash.ld index 95d71b9e3..95d71b9e3 100644 --- a/hw/bsp/samd21/boards/cynthion_d21/samd21g18a_flash.ld +++ b/hw/bsp/samd2x_l2x/boards/cynthion_d21/samd21g18a_flash.ld diff --git a/hw/bsp/samd21/boards/feather_m0_express/board.cmake b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.cmake index c1a612936..dedc07594 100644 --- a/hw/bsp/samd21/boards/feather_m0_express/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21G18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) diff --git a/hw/bsp/samd21/boards/feather_m0_express/board.h b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.h index 6fe13eb30..6fe13eb30 100644 --- a/hw/bsp/samd21/boards/feather_m0_express/board.h +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.h diff --git a/hw/bsp/samd21/boards/feather_m0_express/board.mk b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.mk index d6c9150b3..f4211e6c8 100644 --- a/hw/bsp/samd21/boards/feather_m0_express/board.mk +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. diff --git a/hw/bsp/samd21/boards/feather_m0_express/feather_m0_express.ld b/hw/bsp/samd2x_l2x/boards/feather_m0_express/feather_m0_express.ld index ce7aff80b..ce7aff80b 100644 --- a/hw/bsp/samd21/boards/feather_m0_express/feather_m0_express.ld +++ b/hw/bsp/samd2x_l2x/boards/feather_m0_express/feather_m0_express.ld diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/board.cmake b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.cmake index c1a612936..dedc07594 100644 --- a/hw/bsp/samd21/boards/itsybitsy_m0/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21G18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/board.h b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.h index d901b2ea4..d901b2ea4 100644 --- a/hw/bsp/samd21/boards/itsybitsy_m0/board.h +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.h diff --git a/hw/bsp/samd21/boards/circuitplayground_express/board.mk b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.mk index d6c9150b3..f4211e6c8 100644 --- a/hw/bsp/samd21/boards/circuitplayground_express/board.mk +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/itsybitsy_m0.ld b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/itsybitsy_m0.ld index ce7aff80b..ce7aff80b 100644 --- a/hw/bsp/samd21/boards/itsybitsy_m0/itsybitsy_m0.ld +++ b/hw/bsp/samd2x_l2x/boards/itsybitsy_m0/itsybitsy_m0.ld diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.cmake b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.cmake index c1a612936..dedc07594 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21G18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.h b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.h index 726de3259..726de3259 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/board.h +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.h diff --git a/hw/bsp/samd21/boards/itsybitsy_m0/board.mk b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.mk index d6c9150b3..f4211e6c8 100644 --- a/hw/bsp/samd21/boards/itsybitsy_m0/board.mk +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. diff --git a/hw/bsp/samd21/boards/metro_m0_express/metro_m0_express.ld b/hw/bsp/samd2x_l2x/boards/metro_m0_express/metro_m0_express.ld index ce7aff80b..ce7aff80b 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/metro_m0_express.ld +++ b/hw/bsp/samd2x_l2x/boards/metro_m0_express/metro_m0_express.ld diff --git a/hw/bsp/samd21/boards/qtpy/board.cmake b/hw/bsp/samd2x_l2x/boards/qtpy/board.cmake index f6cd446dd..958944620 100644 --- a/hw/bsp/samd21/boards/qtpy/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/qtpy/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21E18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) diff --git a/hw/bsp/samd21/boards/qtpy/board.h b/hw/bsp/samd2x_l2x/boards/qtpy/board.h index b1cf338e4..b1cf338e4 100644 --- a/hw/bsp/samd21/boards/qtpy/board.h +++ b/hw/bsp/samd2x_l2x/boards/qtpy/board.h diff --git a/hw/bsp/samd21/boards/qtpy/board.mk b/hw/bsp/samd2x_l2x/boards/qtpy/board.mk index 6cefa84c3..4009c8a38 100644 --- a/hw/bsp/samd21/boards/qtpy/board.mk +++ b/hw/bsp/samd2x_l2x/boards/qtpy/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + # For Adafruit QT Py board CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY diff --git a/hw/bsp/samd21/boards/qtpy/qtpy.ld b/hw/bsp/samd2x_l2x/boards/qtpy/qtpy.ld index ce7aff80b..ce7aff80b 100644 --- a/hw/bsp/samd21/boards/qtpy/qtpy.ld +++ b/hw/bsp/samd2x_l2x/boards/qtpy/qtpy.ld diff --git a/hw/bsp/saml2x/boards/saml22_feather/board.cmake b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.cmake index 7fd79d2ce..7fd79d2ce 100644 --- a/hw/bsp/saml2x/boards/saml22_feather/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.cmake diff --git a/hw/bsp/saml2x/boards/saml22_feather/board.h b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.h index f8660c3f8..f8660c3f8 100644 --- a/hw/bsp/saml2x/boards/saml22_feather/board.h +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.h diff --git a/hw/bsp/saml2x/boards/saml22_feather/board.mk b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.mk index c7817ff70..c7817ff70 100644 --- a/hw/bsp/saml2x/boards/saml22_feather/board.mk +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/board.mk diff --git a/hw/bsp/saml2x/boards/saml22_feather/saml22_feather.ld b/hw/bsp/samd2x_l2x/boards/saml22_feather/saml22_feather.ld index a04305be7..a04305be7 100644 --- a/hw/bsp/saml2x/boards/saml22_feather/saml22_feather.ld +++ b/hw/bsp/samd2x_l2x/boards/saml22_feather/saml22_feather.ld diff --git a/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.cmake b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/board.h b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.h index 1c434c68c..1c434c68c 100644 --- a/hw/bsp/samd21/boards/seeeduino_xiao/board.h +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.h diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/board.mk b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.mk index 1c888da3a..0afe37f12 100644 --- a/hw/bsp/samd21/boards/seeeduino_xiao/board.mk +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY LD_FILE = $(BOARD_PATH)/$(BOARD).ld diff --git a/hw/bsp/samd21/boards/seeeduino_xiao/seeeduino_xiao.ld b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/seeeduino_xiao.ld index 0d0c4e6c4..0d0c4e6c4 100644 --- a/hw/bsp/samd21/boards/seeeduino_xiao/seeeduino_xiao.ld +++ b/hw/bsp/samd2x_l2x/boards/seeeduino_xiao/seeeduino_xiao.ld diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/board.cmake b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.cmake index 67d26475f..67d26475f 100644 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.cmake diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/board.h b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.h index 502c799db..502c799db 100644 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/board.h +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.h diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.mk index c7817ff70..c7817ff70 100644 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/board.mk +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/board.mk diff --git a/hw/bsp/saml2x/boards/sensorwatch_m0/sensorwatch_m0.ld b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/sensorwatch_m0.ld index a04305be7..a04305be7 100644 --- a/hw/bsp/saml2x/boards/sensorwatch_m0/sensorwatch_m0.ld +++ b/hw/bsp/samd2x_l2x/boards/sensorwatch_m0/sensorwatch_m0.ld diff --git a/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.cmake b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.cmake new file mode 100644 index 000000000..dedc07594 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.cmake @@ -0,0 +1,10 @@ +set(SAM_FAMILY samd21) +set(JLINK_DEVICE ATSAMD21G18) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAMD21G18A__ + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.h b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.h index a05cf5e4e..a05cf5e4e 100644 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/board.h +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.h diff --git a/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.mk b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.mk new file mode 100644 index 000000000..f4211e6c8 --- /dev/null +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/board.mk @@ -0,0 +1,11 @@ +SAM_FAMILY = samd21 + +CFLAGS += -D__SAMD21G18A__ -DCFG_EXAMPLE_VIDEO_READONLY + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/$(BOARD).ld + +# For flash-jlink target +JLINK_DEVICE = ATSAMD21G18 + +flash: flash-bossac diff --git a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld index 0754a8e9c..0754a8e9c 100644 --- a/hw/bsp/samd21/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld +++ b/hw/bsp/samd2x_l2x/boards/sparkfun_samd21_mini_usb/sparkfun_samd21_mini_usb.ld diff --git a/hw/bsp/samd21/boards/trinket_m0/board.cmake b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.cmake index f6cd446dd..958944620 100644 --- a/hw/bsp/samd21/boards/trinket_m0/board.cmake +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.cmake @@ -1,3 +1,4 @@ +set(SAM_FAMILY samd21) set(JLINK_DEVICE ATSAMD21E18) set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) diff --git a/hw/bsp/samd21/boards/trinket_m0/board.h b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.h index 01ad83089..01ad83089 100644 --- a/hw/bsp/samd21/boards/trinket_m0/board.h +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.h diff --git a/hw/bsp/samd21/boards/trinket_m0/board.mk b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.mk index 6addf13b7..201259288 100644 --- a/hw/bsp/samd21/boards/trinket_m0/board.mk +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/board.mk @@ -1,3 +1,5 @@ +SAM_FAMILY = samd21 + CFLAGS += -D__SAMD21E18A__ -DCFG_EXAMPLE_VIDEO_READONLY # All source paths should be relative to the top level. diff --git a/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld b/hw/bsp/samd2x_l2x/boards/trinket_m0/trinket_m0.ld index ce7aff80b..ce7aff80b 100644 --- a/hw/bsp/samd21/boards/trinket_m0/trinket_m0.ld +++ b/hw/bsp/samd2x_l2x/boards/trinket_m0/trinket_m0.ld diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd2x_l2x/family.c index 14e60e917..67da1294e 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd2x_l2x/family.c @@ -39,28 +39,57 @@ #include "hal/include/hal_gpio.h" #include "hal/include/hal_init.h" -#include "hri/hri_nvmctrl_d21.h" - #include "hpl/gclk/hpl_gclk_base.h" -#include "hpl_pm_config.h" -#include "hpl/pm/hpl_pm_base.h" + +// SAMD21 specific includes +#if defined(__SAMD21E15A__) || defined(__SAMD21E16A__) || defined(__SAMD21E17A__) || defined(__SAMD21E18A__) || \ + defined(__SAMD21G15A__) || defined(__SAMD21G16A__) || defined(__SAMD21G17A__) || defined(__SAMD21G18A__) || \ + defined(__SAMD21J15A__) || defined(__SAMD21J16A__) || defined(__SAMD21J17A__) || defined(__SAMD21J18A__) + #define SAMD21_FAMILY + #include "hri/hri_nvmctrl_d21.h" + #include "hpl_pm_config.h" + #include "hpl/pm/hpl_pm_base.h" +#endif + +// SAML21/22 specific includes +#if defined(__SAML21E15B__) || defined(__SAML21E16B__) || defined(__SAML21E17B__) || defined(__SAML21E18B__) || \ + defined(__SAML21G16B__) || defined(__SAML21G17B__) || defined(__SAML21G18B__) || \ + defined(__SAML21J16B__) || defined(__SAML21J17B__) || defined(__SAML21J18B__) || \ + defined(__SAML22G16A__) || defined(__SAML22G17A__) || defined(__SAML22G18A__) || \ + defined(__SAML22J16A__) || defined(__SAML22J17A__) || defined(__SAML22J18A__) || \ + defined(__SAML22N16A__) || defined(__SAML22N17A__) || defined(__SAML22N18A__) + #define SAML2X_FAMILY + #include "hpl_mclk_config.h" +#endif #ifdef __GNUC__ #pragma GCC diagnostic pop #endif -static inline void board_vbus_set(uint8_t rhport, bool state) TU_ATTR_UNUSED; #include "board.h" +// board_vbus_set is defined in board.h for boards that support it +#if !defined(board_vbus_set) + #define board_vbus_set(rhport, state) do { (void)(rhport); (void)(state); } while(0) +#endif + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +#ifdef SAMD21_FAMILY /* Referenced GCLKs, should be initialized firstly */ #define _GCLK_INIT_1ST (1 << 0 | 1 << 1) - /* Not referenced GCLKs, initialized last */ #define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) +#endif + +#ifdef SAML2X_FAMILY +/* Referenced GCLKs (out of 0~4), should be initialized firstly */ +#define _GCLK_INIT_1ST 0x00000000 +/* Not referenced GCLKs, initialized last */ +#define _GCLK_INIT_LAST 0x0000001F +#endif //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler @@ -86,7 +115,8 @@ static void max3421_init(void); #endif void board_init(void) { - // Clock init ( follow hpl_init.c ) +#ifdef SAMD21_FAMILY + // Clock init for SAMD21 ( follow hpl_init.c ) hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2); _pm_init(); @@ -96,6 +126,28 @@ void board_init(void) { #endif _sysctrl_init_referenced_generators(); _gclk_init_generators_by_fref(_GCLK_INIT_LAST); +#endif + +#ifdef SAML2X_FAMILY + // Clock init for SAML2x ( follow hpl_init.c ) + hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE); + + _set_performance_level(2); + + _osc32kctrl_init_sources(); + _oscctrl_init_sources(); + _mclk_init(); +#if _GCLK_INIT_1ST + _gclk_init_generators_by_fref(_GCLK_INIT_1ST); +#endif + _oscctrl_init_referenced_generators(); + _gclk_init_generators_by_fref(_GCLK_INIT_LAST); + +#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3) + hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL); + hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL); +#endif +#endif // Update SystemCoreClock since it is hard coded with asf4 and not correct // Init 1ms tick timer (samd SystemCoreClock may not correct) @@ -126,9 +178,17 @@ void board_init(void) { /* USB Clock init * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock * for low speed and full speed operation. */ +#ifdef SAMD21_FAMILY _pm_enable_bus_clock(PM_BUS_APBB, USB); _pm_enable_bus_clock(PM_BUS_AHB, USB); _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); +#endif + +#ifdef SAML2X_FAMILY + hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_AHBMASK_USB_bit(MCLK); + hri_mclk_set_APBBMASK_USB_bit(MCLK); +#endif // USB Pin Init gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); @@ -141,6 +201,7 @@ void board_init(void) { gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); +#ifdef SAMD21_FAMILY // Output 500hz PWM on D12 (PA19 - TCC0 WO[3]) so we can validate the GCLK0 clock speed with a Saleae. _pm_enable_bus_clock(PM_BUS_APBC, TCC0); TCC0->PER.bit.PER = 48000000 / 1000; @@ -149,6 +210,7 @@ void board_init(void) { gpio_set_pin_function(PIN_PA19, PINMUX_PA19F_TCC0_WO3); _gclk_enable_channel(TCC0_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); +#endif #if CFG_TUH_ENABLED #if CFG_TUH_MAX3421 @@ -203,9 +265,17 @@ static void uart_init(void) #error "UART_RX_PIN not supported" #endif +#ifdef SAMD21_FAMILY // setup clock (48MHz) _pm_enable_bus_clock(PM_BUS_APBC, SERCOM0); _gclk_enable_channel(SERCOM0_GCLK_ID_CORE, GCLK_CLKCTRL_GEN_GCLK0_Val); +#endif + +#ifdef SAML2X_FAMILY + // setup clock (48MHz) + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_CORE, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_APBCMASK_SERCOM0_bit(MCLK); +#endif SERCOM0->USART.CTRLA.bit.SWRST = 1; /* reset SERCOM & enable config */ while(SERCOM0->USART.SYNCBUSY.bit.SWRST); @@ -304,14 +374,24 @@ static void max3421_init(void) { // MAX3421E max SPI clock is 26MHz however SAMD can only work reliably at 12 Mhz uint32_t const baudrate = 12000000u; +#ifdef SAMD21_FAMILY // Enable the APB clock for SERCOM PM->APBCMASK.reg |= 1u << (PM_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID); // Configure GCLK for SERCOM -// GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val + MAX3421_SERCOM_ID) | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; while (GCLK->STATUS.bit.SYNCBUSY); +#endif + +#ifdef SAML2X_FAMILY + // Enable the APB clock for SERCOM + hri_mclk_set_APBCMASK_reg(MCLK, 1u << (MCLK_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID)); + + // Configure GCLK for SERCOM + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_CORE + MAX3421_SERCOM_ID, + GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); +#endif Sercom* sercom = MAX3421_SERCOM; @@ -332,7 +412,7 @@ static void max3421_init(void) { // Set the baud rate sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); - // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) + // Configure SPI pins gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); gpio_set_pin_function(MAX3421_SCK_PIN, MAX3421_SERCOM_FUNCTION); @@ -355,14 +435,24 @@ static void max3421_init(void) { //------------- External Interrupt -------------// +#ifdef SAMD21_FAMILY // Enable the APB clock for EIC (External Interrupt Controller) PM->APBAMASK.reg |= PM_APBAMASK_EIC; // Configure GCLK for EIC GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EIC | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; while (GCLK->STATUS.bit.SYNCBUSY); +#endif + +#ifdef SAML2X_FAMILY + // Enable the APB clock for EIC + hri_mclk_set_APBAMASK_EIC_bit(MCLK); - // Configure PA20 as an input with function A (external interrupt) + // Configure GCLK for EIC + hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); +#endif + + // Configure interrupt pin as an input with function A (external interrupt) gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); gpio_set_pin_function(MAX3421_INTR_PIN, 0); @@ -451,3 +541,10 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx } #endif + +// Stub for libc init array (required by SAML21/SAML22) +#ifdef SAML2X_FAMILY +void _init(void); +void _init(void) { +} +#endif diff --git a/hw/bsp/samd2x_l2x/family.cmake b/hw/bsp/samd2x_l2x/family.cmake new file mode 100644 index 000000000..76371ccdc --- /dev/null +++ b/hw/bsp/samd2x_l2x/family.cmake @@ -0,0 +1,148 @@ +include_guard() + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# Determine which SAM family based on board configuration +# SAM_FAMILY should be set by board.cmake (samd21, saml21, or saml22) +if(NOT DEFINED SAM_FAMILY) + # Default to samd21 if not specified for backward compatibility + set(SAM_FAMILY samd21) +endif() + +set(SDK_DIR ${TOP}/hw/mcu/microchip/${SAM_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS SAMD21 SAML2X CACHE INTERNAL "") +set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f target/at91samdXX.cfg") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + # Common sources for all SAM families + set(COMMON_SOURCES + ${SDK_DIR}/gcc/system_${SAM_FAMILY}.c + ${SDK_DIR}/hal/src/hal_atomic.c + ${SDK_DIR}/hpl/gclk/hpl_gclk.c + ) + + # Family-specific sources + if(SAM_FAMILY STREQUAL "samd21") + list(APPEND COMMON_SOURCES + ${SDK_DIR}/hpl/pm/hpl_pm.c + ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c + ) + else() + # SAML21/SAML22 + list(APPEND COMMON_SOURCES + ${SDK_DIR}/hpl/mclk/hpl_mclk.c + ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c + ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c + ${SDK_DIR}/hpl/pm/hpl_pm.c + ) + endif() + + add_library(${BOARD_TARGET} STATIC ${COMMON_SOURCES}) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR} + ${SDK_DIR}/config + ${SDK_DIR}/include + ${SDK_DIR}/hal/include + ${SDK_DIR}/hal/utils/include + ${SDK_DIR}/hpl/pm + ${SDK_DIR}/hpl/port + ${SDK_DIR}/hri + ${CMSIS_5}/CMSIS/Core/Include + ) + + # Family-specific compile definitions + if(SAM_FAMILY STREQUAL "samd21") + target_compile_definitions(${BOARD_TARGET} PUBLIC + CONF_DFLL_OVERWRITE_CALIBRATION=0 + ) + else() + # SAML21/SAML22 + target_compile_definitions(${BOARD_TARGET} PUBLIC + CONF_OSC32K_CALIB_ENABLE=0 + CFG_EXAMPLE_VIDEO_READONLY + ) + endif() + + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Determine MCU option based on SAM_FAMILY + if(SAM_FAMILY STREQUAL "samd21") + set(MCU_OPTION OPT_MCU_SAMD21) + elseif(SAM_FAMILY STREQUAL "saml21") + set(MCU_OPTION OPT_MCU_SAML21) + elseif(SAM_FAMILY STREQUAL "saml22") + set(MCU_OPTION OPT_MCU_SAML22) + else() + message(FATAL_ERROR "Unknown SAM_FAMILY: ${SAM_FAMILY}") + endif() + family_add_tinyusb(${TARGET} ${MCU_OPTION}) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/microchip/samd/dcd_samd.c + ${TOP}/src/portable/microchip/samd/hcd_samd.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + # Add HCD support for SAMD21 (has host capability) + if(SAM_FAMILY STREQUAL "samd21") + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/microchip/samd/hcd_samd.c + ) + endif() + + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) + #family_flash_openocd(${TARGET}) +endfunction() diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd2x_l2x/family.mk index a2c37b2b6..dca440ddd 100644 --- a/hw/bsp/samd21/family.mk +++ b/hw/bsp/samd2x_l2x/family.mk @@ -1,13 +1,37 @@ UF2_FAMILY_ID = 0x68ed2b88 -SDK_DIR = hw/mcu/microchip/samd21 include $(TOP)/$(BOARD_PATH)/board.mk + +# SAM_FAMILY should be set by board.mk (samd21, saml21, or saml22) +ifeq ($(SAM_FAMILY),) + # Default to samd21 if not specified for backward compatibility + SAM_FAMILY = samd21 +endif + +SDK_DIR = hw/mcu/microchip/$(SAM_FAMILY) CPU_CORE ?= cortex-m0plus +# Common CFLAGS CFLAGS += \ -flto \ - -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ - -DCFG_TUSB_MCU=OPT_MCU_SAMD21 + +# Family-specific CFLAGS +ifeq ($(SAM_FAMILY),samd21) + CFLAGS += \ + -DCONF_DFLL_OVERWRITE_CALIBRATION=0 \ + -DCFG_TUSB_MCU=OPT_MCU_SAMD21 +else + # SAML21/SAML22 + CFLAGS += \ + -DCONF_OSC32K_CALIB_ENABLE=0 \ + -DCFG_EXAMPLE_VIDEO_READONLY \ + + ifeq ($(SAM_FAMILY),saml21) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAML21 + else ifeq ($(SAM_FAMILY),saml22) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAML22 + endif +endif # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=redundant-decls @@ -21,15 +45,30 @@ LDFLAGS_GCC += \ LDFLAGS_CLANG += +# Common source files SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ - src/portable/microchip/samd/hcd_samd.c \ - ${SDK_DIR}/gcc/gcc/startup_samd21.c \ - ${SDK_DIR}/gcc/system_samd21.c \ + ${SDK_DIR}/gcc/gcc/startup_$(SAM_FAMILY).c \ + ${SDK_DIR}/gcc/system_$(SAM_FAMILY).c \ ${SDK_DIR}/hal/src/hal_atomic.c \ ${SDK_DIR}/hpl/gclk/hpl_gclk.c \ - ${SDK_DIR}/hpl/pm/hpl_pm.c \ - ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c \ + +# Family-specific source files +ifeq ($(SAM_FAMILY),samd21) + SRC_C += \ + src/portable/microchip/samd/hcd_samd.c \ + ${SDK_DIR}/hpl/pm/hpl_pm.c \ + ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c \ + +else + # SAML21/SAML22 + SRC_C += \ + ${SDK_DIR}/hpl/mclk/hpl_mclk.c \ + ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c \ + ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c \ + ${SDK_DIR}/hpl/pm/hpl_pm.c \ + +endif INC += \ $(TOP)/$(BOARD_PATH) \ diff --git a/hw/bsp/samd5x_e5x/family.c b/hw/bsp/samd5x_e5x/family.c index d53aa00d6..df6f19d0f 100644 --- a/hw/bsp/samd5x_e5x/family.c +++ b/hw/bsp/samd5x_e5x/family.c @@ -179,7 +179,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { for (int i = 0; i < 4; i++) { uint32_t did = *((uint32_t const*) did_addr[i]); did = TU_BSWAP32(did); // swap endian to match samd51 uf2 bootloader - memcpy(id + i * 4, &did, 4); + memcpy(id + i * 4, &did, sizeof(uint32_t)); } return 16; diff --git a/hw/bsp/samd5x_e5x/family.cmake b/hw/bsp/samd5x_e5x/family.cmake index 516290593..bb022ab76 100644 --- a/hw/bsp/samd5x_e5x/family.cmake +++ b/hw/bsp/samd5x_e5x/family.cmake @@ -13,22 +13,16 @@ set(FAMILY_MCUS SAMD51 SAME54 CACHE INTERNAL "") set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -c \"set CHIPNAME samd51\" -f target/atsame5x.cfg") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/gcc/system_${SAM_FAMILY}.c ${SDK_DIR}/hal/src/hal_atomic.c @@ -36,7 +30,6 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/hpl/mclk/hpl_mclk.c ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR} @@ -50,55 +43,46 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_SAMD51) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/microchip/samd/dcd_samd.c + ${TOP}/src/portable/microchip/samd/hcd_samd.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_SAMD51) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/microchip/samd/dcd_samd.c - ${TOP}/src/portable/microchip/samd/hcd_samd.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/same70_qmtech/board.mk b/hw/bsp/same70_qmtech/board.mk deleted file mode 100644 index 7e949e135..000000000 --- a/hw/bsp/same70_qmtech/board.mk +++ /dev/null @@ -1,59 +0,0 @@ -ASF_DIR = hw/mcu/microchip/same70 - -CFLAGS += \ - -mthumb \ - -mabi=aapcs \ - -mcpu=cortex-m7 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ - -nostdlib -nostartfiles \ - -D__SAME70N19B__ \ - -DCFG_TUSB_MCU=OPT_MCU_SAMX7X - -# suppress following warnings from mcu driver -CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=redundant-decls - -# SAM driver is flooded with -Wcast-qual which slow down complication significantly -CFLAGS_SKIP += -Wcast-qual - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -# All source paths should be relative to the top level. -LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld - -SRC_C += \ - src/portable/microchip/samx7x/dcd_samx7x.c \ - $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ - $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ - $(ASF_DIR)/hpl/core/hpl_init.c \ - $(ASF_DIR)/hpl/usart/hpl_usart.c \ - $(ASF_DIR)/hpl/pmc/hpl_pmc.c \ - $(ASF_DIR)/hal/src/hal_usart_async.c \ - $(ASF_DIR)/hal/src/hal_io.c \ - $(ASF_DIR)/hal/src/hal_atomic.c \ - $(ASF_DIR)/hal/utils/src/utils_ringbuffer.c - -INC += \ - $(TOP)/hw/bsp/$(BOARD) \ - $(TOP)/$(ASF_DIR) \ - $(TOP)/$(ASF_DIR)/config \ - $(TOP)/$(ASF_DIR)/same70b/include \ - $(TOP)/$(ASF_DIR)/hal/include \ - $(TOP)/$(ASF_DIR)/hal/utils/include \ - $(TOP)/$(ASF_DIR)/hpl/core \ - $(TOP)/$(ASF_DIR)/hpl/pio \ - $(TOP)/$(ASF_DIR)/hpl/pmc \ - $(TOP)/$(ASF_DIR)/hri \ - $(TOP)/$(ASF_DIR)/CMSIS/Core/Include - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM7 - -# For flash-jlink target -JLINK_DEVICE = SAME70N19B - -# flash using edbg from https://github.com/ataradov/edbg -# Note: SAME70's GPNVM1 must be set to 1 to boot from flash with -# edbg -t same70 -F w0,1,1 -flash: $(BUILD)/$(PROJECT).bin - edbg --verbose -t same70 -pv -f $< diff --git a/hw/bsp/same70_qmtech/same70_qmtech.c b/hw/bsp/same70_qmtech/same70_qmtech.c deleted file mode 100644 index e5f0da198..000000000 --- a/hw/bsp/same70_qmtech/same70_qmtech.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019, hathach (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. - * - */ - -#include "sam.h" -#include "bsp/board_api.h" - -#include "peripheral_clk_config.h" -#include "hpl/usart/hpl_usart_base.h" -#include "hpl/pmc/hpl_pmc.h" -#include "hal/include/hal_init.h" -#include "hal/include/hal_usart_async.h" -#include "hal/include/hal_gpio.h" - - -// You can get the board here: -// https://www.aliexpress.com/item/1005003173783268.html - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -#define LED_PIN GPIO(GPIO_PORTA, 15) - -#define BUTTON_PIN GPIO(GPIO_PORTA, 21) -#define BUTTON_STATE_ACTIVE 0 - -#define UART_TX_PIN GPIO(GPIO_PORTB, 1) -#define UART_RX_PIN GPIO(GPIO_PORTB, 0) - -static struct usart_async_descriptor edbg_com; -static uint8_t edbg_com_buffer[64]; -static volatile bool uart_busy = false; - -static void tx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr) -{ - (void) io_descr; - uart_busy = false; -} - -//------------- IMPLEMENTATION -------------// -void board_init(void) -{ - init_mcu(); - - /* Disable Watchdog */ - hri_wdt_set_MR_WDDIS_bit(WDT); - - // LED - _pmc_enable_periph_clock(ID_PIOB); - gpio_set_pin_level(LED_PIN, false); - gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_function(LED_PIN, GPIO_PIN_FUNCTION_OFF); - - // Button - _pmc_enable_periph_clock(ID_PIOA); - gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP); - gpio_set_pin_function(BUTTON_PIN, GPIO_PIN_FUNCTION_OFF); - - // Uart via EDBG Com - _pmc_enable_periph_clock(ID_USART1); - gpio_set_pin_function(UART_RX_PIN, MUX_PA21A_USART1_RXD1); - gpio_set_pin_function(UART_TX_PIN, MUX_PB4D_USART1_TXD1); - - usart_async_init(&edbg_com, USART1, edbg_com_buffer, sizeof(edbg_com_buffer), _usart_get_usart_async()); - usart_async_set_baud_rate(&edbg_com, CFG_BOARD_UART_BAUDRATE); - usart_async_register_callback(&edbg_com, USART_ASYNC_TXC_CB, tx_cb_EDBG_COM); - usart_async_enable(&edbg_com); - -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer (samd SystemCoreClock may not correct) - SysTick_Config(CONF_CPU_FREQUENCY / 1000); -#endif - - // Enable USB clock - _pmc_enable_periph_clock(ID_USBHS); - -} - -//--------------------------------------------------------------------+ -// USB Interrupt Handler -//--------------------------------------------------------------------+ -void USBHS_Handler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) -{ - gpio_set_pin_level(LED_PIN, state); -} - -uint32_t board_button_read(void) -{ - return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); -} - -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - // while until previous transfer is complete - while(uart_busy) {} - uart_busy = true; - - io_write(&edbg_com.io, buf, len); - return len; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; - -void SysTick_Handler (void) -{ - system_ticks++; -} - -uint32_t board_millis(void) -{ - return system_ticks; -} -#endif - -// Required by __libc_init_array in startup code if we are compiling using -// -nostdlib/-nostartfiles. -void _init(void) -{ - -} diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk deleted file mode 100644 index 2d97ecdc1..000000000 --- a/hw/bsp/same70_xplained/board.mk +++ /dev/null @@ -1,67 +0,0 @@ -ASF_DIR = hw/mcu/microchip/same70 - -CFLAGS += \ - -mthumb \ - -mabi=aapcs \ - -mcpu=cortex-m7 \ - -mfloat-abi=hard \ - -mfpu=fpv4-sp-d16 \ - -nostdlib -nostartfiles \ - -D__SAME70Q21B__ \ - -DCFG_TUSB_MCU=OPT_MCU_SAMX7X - -# suppress following warnings from mcu driver -CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=redundant-decls - -SPEED ?= high - -ifeq ($(SPEED), high) - CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED -else - CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED -endif - -# SAM driver is flooded with -Wcast-qual which slow down complication significantly -CFLAGS_SKIP += -Wcast-qual - -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs - -# All source paths should be relative to the top level. -LD_FILE = $(ASF_DIR)/same70b/gcc/gcc/same70q21b_flash.ld - -SRC_C += \ - src/portable/microchip/samx7x/dcd_samx7x.c \ - $(ASF_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ - $(ASF_DIR)/same70b/gcc/system_same70q21b.c \ - $(ASF_DIR)/hpl/core/hpl_init.c \ - $(ASF_DIR)/hpl/usart/hpl_usart.c \ - $(ASF_DIR)/hpl/pmc/hpl_pmc.c \ - $(ASF_DIR)/hal/src/hal_usart_async.c \ - $(ASF_DIR)/hal/src/hal_io.c \ - $(ASF_DIR)/hal/src/hal_atomic.c \ - $(ASF_DIR)/hal/utils/src/utils_ringbuffer.c - -INC += \ - $(TOP)/hw/bsp/$(BOARD) \ - $(TOP)/$(ASF_DIR) \ - $(TOP)/$(ASF_DIR)/config \ - $(TOP)/$(ASF_DIR)/same70b/include \ - $(TOP)/$(ASF_DIR)/hal/include \ - $(TOP)/$(ASF_DIR)/hal/utils/include \ - $(TOP)/$(ASF_DIR)/hpl/core \ - $(TOP)/$(ASF_DIR)/hpl/pio \ - $(TOP)/$(ASF_DIR)/hpl/pmc \ - $(TOP)/$(ASF_DIR)/hri \ - $(TOP)/$(ASF_DIR)/CMSIS/Core/Include - -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM7 - -# For flash-jlink target -JLINK_DEVICE = SAME70Q21B - -# flash using edbg from https://github.com/ataradov/edbg -# Note: SAME70's GPNVM1 must be set to 1 to boot from flash with -# edbg -t same70 -F w0,1,1 -flash: $(BUILD)/$(PROJECT).bin - edbg --verbose -t same70 -pv -f $< diff --git a/hw/bsp/same70_xplained/same70_xplained.c b/hw/bsp/same70_xplained/same70_xplained.c deleted file mode 100644 index f532c6927..000000000 --- a/hw/bsp/same70_xplained/same70_xplained.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019, hathach (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. - * - */ - -#include "sam.h" -#include "bsp/board_api.h" - -#include "peripheral_clk_config.h" -#include "hpl/usart/hpl_usart_base.h" -#include "hpl/pmc/hpl_pmc.h" -#include "hal/include/hal_init.h" -#include "hal/include/hal_usart_async.h" -#include "hal/include/hal_gpio.h" - - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -#define LED_PIN GPIO(GPIO_PORTC, 8) - -#define BUTTON_PIN GPIO(GPIO_PORTA, 11) -#define BUTTON_STATE_ACTIVE 0 - -#define UART_TX_PIN GPIO(GPIO_PORTB, 4) -#define UART_RX_PIN GPIO(GPIO_PORTA, 21) - -static struct usart_async_descriptor edbg_com; -static uint8_t edbg_com_buffer[64]; -static volatile bool uart_busy = false; - -static void tx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr) -{ - (void) io_descr; - uart_busy = false; -} - -//------------- IMPLEMENTATION -------------// -void board_init(void) -{ - init_mcu(); - - /* Disable Watchdog */ - hri_wdt_set_MR_WDDIS_bit(WDT); - - // LED - _pmc_enable_periph_clock(ID_PIOC); - gpio_set_pin_level(LED_PIN, false); - gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_function(LED_PIN, GPIO_PIN_FUNCTION_OFF); - - // Button - _pmc_enable_periph_clock(ID_PIOA); - gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP); - gpio_set_pin_function(BUTTON_PIN, GPIO_PIN_FUNCTION_OFF); - - // Uart via EDBG Com - _pmc_enable_periph_clock(ID_USART1); - gpio_set_pin_function(UART_RX_PIN, MUX_PA21A_USART1_RXD1); - gpio_set_pin_function(UART_TX_PIN, MUX_PB4D_USART1_TXD1); - - usart_async_init(&edbg_com, USART1, edbg_com_buffer, sizeof(edbg_com_buffer), _usart_get_usart_async()); - usart_async_set_baud_rate(&edbg_com, CFG_BOARD_UART_BAUDRATE); - usart_async_register_callback(&edbg_com, USART_ASYNC_TXC_CB, tx_cb_EDBG_COM); - usart_async_enable(&edbg_com); - -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer (samd SystemCoreClock may not correct) - SysTick_Config(CONF_CPU_FREQUENCY / 1000); -#endif - - // Enable USB clock - _pmc_enable_periph_clock(ID_USBHS); - -} - -//--------------------------------------------------------------------+ -// USB Interrupt Handler -//--------------------------------------------------------------------+ -void USBHS_Handler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) -{ - gpio_set_pin_level(LED_PIN, state); -} - -uint32_t board_button_read(void) -{ - return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); -} - -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; - return 0; -} - -int board_uart_write(void const * buf, int len) -{ - // while until previous transfer is complete - while(uart_busy) {} - uart_busy = true; - - io_write(&edbg_com.io, buf, len); - return len; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; - -void SysTick_Handler (void) -{ - system_ticks++; -} - -uint32_t board_millis(void) -{ - return system_ticks; -} -#endif - -// Required by __libc_init_array in startup code if we are compiling using -// -nostdlib/-nostartfiles. -void _init(void) -{ - -} diff --git a/hw/bsp/same7x/boards/same70_qmtech/board.cmake b/hw/bsp/same7x/boards/same70_qmtech/board.cmake new file mode 100644 index 000000000..cde4c3da6 --- /dev/null +++ b/hw/bsp/same7x/boards/same70_qmtech/board.cmake @@ -0,0 +1,8 @@ +set(JLINK_DEVICE SAME70N19B) +set(LD_FILE_GNU ${TOP}/hw/mcu/microchip/same70/same70b/gcc/gcc/same70q21b_flash.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAME70N19B__ + ) +endfunction() diff --git a/hw/bsp/same7x/boards/same70_qmtech/board.h b/hw/bsp/same7x/boards/same70_qmtech/board.h new file mode 100644 index 000000000..09c2c93a9 --- /dev/null +++ b/hw/bsp/same7x/boards/same70_qmtech/board.h @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019, 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. + */ + +/* metadata: + name: SAME70 QMTech + manufacturer: Microchip + url: https://www.aliexpress.com/item/1005003173783268.html +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LED_PIN GPIO(GPIO_PORTA, 15) +#define LED_STATE_ON 1 +#define LED_PORT_CLOCK ID_PIOB + +#define BUTTON_PIN GPIO(GPIO_PORTA, 21) +#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_PORT_CLOCK ID_PIOA + +#define UART_TX_PIN GPIO(GPIO_PORTB, 1) +#define UART_TX_FUNCTION MUX_PB4D_USART1_TXD1 +#define UART_RX_PIN GPIO(GPIO_PORTB, 0) +#define UART_RX_FUNCTION MUX_PA21A_USART1_RXD1 +#define UART_PORT_CLOCK ID_USART1 +#define BOARD_USART USART1 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; + (void) state; +} + +#ifdef __cplusplus +} +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/same7x/boards/same70_qmtech/board.mk b/hw/bsp/same7x/boards/same70_qmtech/board.mk new file mode 100644 index 000000000..09ae98860 --- /dev/null +++ b/hw/bsp/same7x/boards/same70_qmtech/board.mk @@ -0,0 +1,3 @@ +CFLAGS += -D__SAME70N19B__ + +JLINK_DEVICE = SAME70N19B diff --git a/hw/bsp/same70_qmtech/hpl_pmc_config.h b/hw/bsp/same7x/boards/same70_qmtech/hpl_pmc_config.h index 387aaa5df..387aaa5df 100644 --- a/hw/bsp/same70_qmtech/hpl_pmc_config.h +++ b/hw/bsp/same7x/boards/same70_qmtech/hpl_pmc_config.h diff --git a/hw/bsp/same70_qmtech/hpl_usart_config.h b/hw/bsp/same7x/boards/same70_qmtech/hpl_usart_config.h index 50ca3f15c..50ca3f15c 100644 --- a/hw/bsp/same70_qmtech/hpl_usart_config.h +++ b/hw/bsp/same7x/boards/same70_qmtech/hpl_usart_config.h diff --git a/hw/bsp/same70_qmtech/hpl_xdmac_config.h b/hw/bsp/same7x/boards/same70_qmtech/hpl_xdmac_config.h index a3d62c6fc..a3d62c6fc 100644 --- a/hw/bsp/same70_qmtech/hpl_xdmac_config.h +++ b/hw/bsp/same7x/boards/same70_qmtech/hpl_xdmac_config.h diff --git a/hw/bsp/same70_qmtech/peripheral_clk_config.h b/hw/bsp/same7x/boards/same70_qmtech/peripheral_clk_config.h index 84756f5ac..84756f5ac 100644 --- a/hw/bsp/same70_qmtech/peripheral_clk_config.h +++ b/hw/bsp/same7x/boards/same70_qmtech/peripheral_clk_config.h diff --git a/hw/bsp/same7x/boards/same70_xplained/board.cmake b/hw/bsp/same7x/boards/same70_xplained/board.cmake new file mode 100644 index 000000000..b226b6c4f --- /dev/null +++ b/hw/bsp/same7x/boards/same70_xplained/board.cmake @@ -0,0 +1,8 @@ +set(JLINK_DEVICE SAME70Q21B) +set(LD_FILE_GNU ${TOP}/hw/mcu/microchip/same70/same70b/gcc/gcc/same70q21b_flash.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + __SAME70Q21B__ + ) +endfunction() diff --git a/hw/bsp/same7x/boards/same70_xplained/board.h b/hw/bsp/same7x/boards/same70_xplained/board.h new file mode 100644 index 000000000..85e23deb8 --- /dev/null +++ b/hw/bsp/same7x/boards/same70_xplained/board.h @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019, 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 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. + */ + +/* metadata: + name: SAME70 Xplained + manufacturer: Microchip + url: https://www.microchip.com/en-us/development-tool/atsame70-xpld +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LED_PIN GPIO(GPIO_PORTC, 8) +#define LED_STATE_ON 1 +#define LED_PORT_CLOCK ID_PIOC + +#define BUTTON_PIN GPIO(GPIO_PORTA, 11) +#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_PORT_CLOCK ID_PIOA + +#define UART_TX_PIN GPIO(GPIO_PORTB, 4) +#define UART_TX_FUNCTION MUX_PB4D_USART1_TXD1 +#define UART_RX_PIN GPIO(GPIO_PORTA, 21) +#define UART_RX_FUNCTION MUX_PA21A_USART1_RXD1 +#define UART_PORT_CLOCK ID_USART1 +#define BOARD_USART USART1 + +static inline void board_vbus_set(uint8_t rhport, bool state) { + (void) rhport; + (void) state; +} + +#ifdef __cplusplus +} +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/same7x/boards/same70_xplained/board.mk b/hw/bsp/same7x/boards/same70_xplained/board.mk new file mode 100644 index 000000000..ca23a9be5 --- /dev/null +++ b/hw/bsp/same7x/boards/same70_xplained/board.mk @@ -0,0 +1,3 @@ +CFLAGS += -D__SAME70Q21B__ + +JLINK_DEVICE = SAME70Q21B diff --git a/hw/bsp/same70_xplained/hpl_pmc_config.h b/hw/bsp/same7x/boards/same70_xplained/hpl_pmc_config.h index 387aaa5df..387aaa5df 100644 --- a/hw/bsp/same70_xplained/hpl_pmc_config.h +++ b/hw/bsp/same7x/boards/same70_xplained/hpl_pmc_config.h diff --git a/hw/bsp/same70_xplained/hpl_usart_config.h b/hw/bsp/same7x/boards/same70_xplained/hpl_usart_config.h index 50ca3f15c..50ca3f15c 100644 --- a/hw/bsp/same70_xplained/hpl_usart_config.h +++ b/hw/bsp/same7x/boards/same70_xplained/hpl_usart_config.h diff --git a/hw/bsp/same70_xplained/hpl_xdmac_config.h b/hw/bsp/same7x/boards/same70_xplained/hpl_xdmac_config.h index a3d62c6fc..a3d62c6fc 100644 --- a/hw/bsp/same70_xplained/hpl_xdmac_config.h +++ b/hw/bsp/same7x/boards/same70_xplained/hpl_xdmac_config.h diff --git a/hw/bsp/same70_xplained/peripheral_clk_config.h b/hw/bsp/same7x/boards/same70_xplained/peripheral_clk_config.h index 84756f5ac..84756f5ac 100644 --- a/hw/bsp/same70_xplained/peripheral_clk_config.h +++ b/hw/bsp/same7x/boards/same70_xplained/peripheral_clk_config.h diff --git a/hw/bsp/same7x/family.c b/hw/bsp/same7x/family.c new file mode 100644 index 000000000..572c83588 --- /dev/null +++ b/hw/bsp/same7x/family.c @@ -0,0 +1,196 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019, 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 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. + */ + +/* metadata: + manufacturer: Microchip +*/ + +#include "bsp/board_api.h" +#include "sam.h" + +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_init.h" +#include "hal/include/hal_usart_async.h" +#include "hpl/pmc/hpl_pmc.h" +#include "hpl/usart/hpl_usart_base.h" +#include "peripheral_clk_config.h" + +static inline void board_vbus_set(uint8_t rhport, bool state); +void _init(void); +#include "board.h" + +#ifndef LED_STATE_ON + #define LED_STATE_ON 1 +#endif + +#ifndef LED_PORT_CLOCK + #define LED_PORT_CLOCK ID_PIOA +#endif + +#ifndef BUTTON_PORT_CLOCK + #define BUTTON_PORT_CLOCK ID_PIOA +#endif + +#ifndef UART_PORT_CLOCK + #define UART_PORT_CLOCK ID_USART1 +#endif + +#ifndef BOARD_USART + #define BOARD_USART USART1 +#endif + +#ifndef BOARD_UART_DESCRIPTOR + #define BOARD_UART_DESCRIPTOR edbg_com +#endif + +#ifndef BOARD_UART_BUFFER + #define BOARD_UART_BUFFER edbg_com_buffer +#endif + +#ifndef BUTTON_STATE_ACTIVE + #define BUTTON_STATE_ACTIVE 0 +#endif + +#ifndef UART_TX_FUNCTION + #define UART_TX_FUNCTION MUX_PB4D_USART1_TXD1 +#endif + +#ifndef UART_RX_FUNCTION + #define UART_RX_FUNCTION MUX_PA21A_USART1_RXD1 +#endif + +#ifndef UART_BUFFER_SIZE + #define UART_BUFFER_SIZE 64 +#endif + +#define LED_STATE_OFF (1 - LED_STATE_ON) + +static struct usart_async_descriptor BOARD_UART_DESCRIPTOR; +static uint8_t BOARD_UART_BUFFER[UART_BUFFER_SIZE]; +static volatile bool uart_busy = false; + +static void tx_complete_cb(const struct usart_async_descriptor *const io_descr) { + (void) io_descr; + uart_busy = false; +} + +void board_init(void) { + init_mcu(); + + /* Disable Watchdog */ + hri_wdt_set_MR_WDDIS_bit(WDT); + +#ifdef LED_PIN + _pmc_enable_periph_clock(LED_PORT_CLOCK); + gpio_set_pin_level(LED_PIN, LED_STATE_OFF); + gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_function(LED_PIN, GPIO_PIN_FUNCTION_OFF); +#endif + +#ifdef BUTTON_PIN + _pmc_enable_periph_clock(BUTTON_PORT_CLOCK); + gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); + gpio_set_pin_function(BUTTON_PIN, GPIO_PIN_FUNCTION_OFF); +#endif + + _pmc_enable_periph_clock(UART_PORT_CLOCK); + gpio_set_pin_function(UART_RX_PIN, UART_RX_FUNCTION); + gpio_set_pin_function(UART_TX_PIN, UART_TX_FUNCTION); + + usart_async_init(&BOARD_UART_DESCRIPTOR, BOARD_USART, BOARD_UART_BUFFER, sizeof(BOARD_UART_BUFFER), _usart_get_usart_async()); + usart_async_set_baud_rate(&BOARD_UART_DESCRIPTOR, CFG_BOARD_UART_BAUDRATE); + usart_async_register_callback(&BOARD_UART_DESCRIPTOR, USART_ASYNC_TXC_CB, tx_complete_cb); + usart_async_enable(&BOARD_UART_DESCRIPTOR); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer (SystemCoreClock may not be correct after init) + SysTick_Config(CONF_CPU_FREQUENCY / 1000); +#endif + + // Enable USB clock + _pmc_enable_periph_clock(ID_USBHS); + +#if CFG_TUH_ENABLED + board_vbus_set(0, true); +#endif +} + +//--------------------------------------------------------------------+ +// USB Interrupt Handler +//--------------------------------------------------------------------+ +void USBHS_Handler(void) { + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { +#ifdef LED_PIN + gpio_set_pin_level(LED_PIN, state ? LED_STATE_ON : LED_STATE_OFF); +#else + (void) state; +#endif +} + +uint32_t board_button_read(void) { +#ifdef BUTTON_PIN + return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); +#else + return 0; +#endif +} + +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; + return 0; +} + +int board_uart_write(void const *buf, int len) { + while (uart_busy) {} + uart_busy = true; + + io_write(&BOARD_UART_DESCRIPTOR.io, buf, len); + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void SysTick_Handler(void) { + system_ticks++; +} + +uint32_t board_millis(void) { + return system_ticks; +} +#endif + +void _init(void) { +} diff --git a/hw/bsp/same7x/family.cmake b/hw/bsp/same7x/family.cmake new file mode 100644 index 000000000..a9c9de413 --- /dev/null +++ b/hw/bsp/same7x/family.cmake @@ -0,0 +1,98 @@ +include_guard() + +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +set(SDK_DIR ${TOP}/hw/mcu/microchip/same70) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m7 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS SAMX7X CACHE INTERNAL "") + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +set(STARTUP_FILE_GNU ${SDK_DIR}/same70b/gcc/gcc/startup_same70q21b.c) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) + +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/same70b/gcc/system_same70q21b.c + ${SDK_DIR}/hpl/core/hpl_init.c + ${SDK_DIR}/hpl/usart/hpl_usart.c + ${SDK_DIR}/hpl/pmc/hpl_pmc.c + ${SDK_DIR}/hal/src/hal_usart_async.c + ${SDK_DIR}/hal/src/hal_io.c + ${SDK_DIR}/hal/src/hal_atomic.c + ${SDK_DIR}/hal/utils/src/utils_ringbuffer.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR} + ${SDK_DIR}/config + ${SDK_DIR}/same70b/include + ${SDK_DIR}/hal/include + ${SDK_DIR}/hal/utils/include + ${SDK_DIR}/hpl/core + ${SDK_DIR}/hpl/pio + ${SDK_DIR}/hpl/pmc + ${SDK_DIR}/hri + ${SDK_DIR}/CMSIS/Core/Include + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + update_board(${BOARD_TARGET}) + + target_compile_options(${BOARD_TARGET} PUBLIC + -Wno-error=unused-parameter + -Wno-error=cast-align + -Wno-error=redundant-decls + -Wno-error=cast-qual + ) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_SAMX7X) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/microchip/samx7x/dcd_samx7x.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/same7x/family.mk b/hw/bsp/same7x/family.mk new file mode 100644 index 000000000..c8fa74d71 --- /dev/null +++ b/hw/bsp/same7x/family.mk @@ -0,0 +1,56 @@ +SDK_DIR = hw/mcu/microchip/same70 + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= cortex-m7 + +CFLAGS += \ + -mthumb \ + -mabi=aapcs \ + -mcpu=cortex-m7 \ + -mfloat-abi=hard \ + -mfpu=fpv4-sp-d16 \ + -nostdlib -nostartfiles \ + -DCFG_TUSB_MCU=OPT_MCU_SAMX7X + +# suppress following warnings from mcu driver +CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=redundant-decls + +# SAM driver is flooded with -Wcast-qual which slows down compilation significantly +CFLAGS_SKIP += -Wcast-qual + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs + +# All source paths should be relative to the top level. +LD_FILE = $(SDK_DIR)/same70b/gcc/gcc/same70q21b_flash.ld + +SRC_C += \ + src/portable/microchip/samx7x/dcd_samx7x.c \ + $(SDK_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ + $(SDK_DIR)/same70b/gcc/system_same70q21b.c \ + $(SDK_DIR)/hpl/core/hpl_init.c \ + $(SDK_DIR)/hpl/usart/hpl_usart.c \ + $(SDK_DIR)/hpl/pmc/hpl_pmc.c \ + $(SDK_DIR)/hal/src/hal_usart_async.c \ + $(SDK_DIR)/hal/src/hal_io.c \ + $(SDK_DIR)/hal/src/hal_atomic.c \ + $(SDK_DIR)/hal/utils/src/utils_ringbuffer.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(SDK_DIR) \ + $(TOP)/$(SDK_DIR)/config \ + $(TOP)/$(SDK_DIR)/same70b/include \ + $(TOP)/$(SDK_DIR)/hal/include \ + $(TOP)/$(SDK_DIR)/hal/utils/include \ + $(TOP)/$(SDK_DIR)/hpl/core \ + $(TOP)/$(SDK_DIR)/hpl/pio \ + $(TOP)/$(SDK_DIR)/hpl/pmc \ + $(TOP)/$(SDK_DIR)/hri \ + $(TOP)/$(SDK_DIR)/CMSIS/Core/Include + +# For freeRTOS port source +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM7 + +# For flash-jlink target +flash: $(BUILD)/$(PROJECT).bin + edbg --verbose -t same70 -pv -f $< diff --git a/hw/bsp/samg/family.c b/hw/bsp/samg/family.c index 8db429e79..234dc0ec0 100644 --- a/hw/bsp/samg/family.c +++ b/hw/bsp/samg/family.c @@ -154,6 +154,7 @@ uint32_t board_millis(void) { // Required by __libc_init_array in startup code if we are compiling using // -nostdlib/-nostartfiles. +void _init(void); void _init(void) { } diff --git a/hw/bsp/samg/family.cmake b/hw/bsp/samg/family.cmake index eb00c8c52..c07e20b90 100644 --- a/hw/bsp/samg/family.cmake +++ b/hw/bsp/samg/family.cmake @@ -14,29 +14,22 @@ set(FAMILY_MCUS SAMG CACHE INTERNAL "") set(OPENOCD_OPTION "-f board/atmel_samg55_xplained_pro.cfg") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - set(STARTUP_FILE_GNU ${SDK_DIR}/${SAM_FAMILY}/gcc/gcc/startup_${SAM_FAMILY}.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/${SAM_FAMILY}/gcc/gcc/startup_${SAM_FAMILY}.c) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/${SAM_FAMILY}/gcc/system_${SAM_FAMILY}.c ${SDK_DIR}/hal/src/hal_atomic.c ${SDK_DIR}/hpl/core/hpl_init.c ${SDK_DIR}/hpl/usart/hpl_usart.c ${SDK_DIR}/hpl/pmc/hpl_pmc.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -51,59 +44,47 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/hri ${SDK_DIR}/CMSIS/Core/Include ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_SAMG) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/microchip/samg/dcd_samg.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_SAMG) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/microchip/samg/dcd_samg.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/saml2x/family.c b/hw/bsp/saml2x/family.c deleted file mode 100644 index cdc65baf1..000000000 --- a/hw/bsp/saml2x/family.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 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. - */ - -/* metadata: - manufacturer: Microchip -*/ - -#include "sam.h" - -// Suppress warning caused by mcu driver -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - -#include "hal/include/hal_gpio.h" -#include "hal/include/hal_init.h" -#include "hpl/gclk/hpl_gclk_base.h" -#include "hpl_mclk_config.h" - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -#include "bsp/board_api.h" -#include "board.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USB_Handler(void) { - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -/* Referenced GCLKs (out of 0~4), should be initialized firstly */ -#define _GCLK_INIT_1ST 0x00000000 -/* Not referenced GCLKs, initialized last */ -#define _GCLK_INIT_LAST 0x0000001F - -void board_init(void) { - // Clock init ( follow hpl_init.c ) - hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE); - - _set_performance_level(2); - - _osc32kctrl_init_sources(); - _oscctrl_init_sources(); - _mclk_init(); -#if _GCLK_INIT_1ST - _gclk_init_generators_by_fref(_GCLK_INIT_1ST); -#endif - _oscctrl_init_referenced_generators(); - _gclk_init_generators_by_fref(_GCLK_INIT_LAST); - -#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3) - hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL); - hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL); -#endif - - // Update SystemCoreClock since it is hard coded with asf4 and not correct - // Init 1ms tick timer (samd SystemCoreClock may not correct) - SystemCoreClock = CONF_CPU_FREQUENCY; - SysTick_Config(CONF_CPU_FREQUENCY / 1000); - - // Led init - gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_level(LED_PIN, !LED_STATE_ON); - - // Button init - gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP); - -#if CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); -#endif - - /* USB Clock init - * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock - * for low speed and full speed operation. */ - hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); - hri_mclk_set_AHBMASK_USB_bit(MCLK); - hri_mclk_set_APBBMASK_USB_bit(MCLK); - - // USB Pin Init - gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA24, false); - gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); - gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA25, false); - gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); - - gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); - gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); - - // Output 500hz PWM on PB23 (TCC0 WO[3]) so we can validate the GCLK1 clock speed -// hri_mclk_set_APBCMASK_TCC0_bit(MCLK); -// TCC0->PER.bit.PER = 48000000 / 1000; -// TCC0->CC[3].bit.CC = 48000000 / 2000; -// TCC0->CTRLA.bit.ENABLE = true; -// -// gpio_set_pin_function(PIN_PB23, PINMUX_PB23F_TCC0_WO3); -// hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { - gpio_set_pin_level(LED_PIN, state); -} - -uint32_t board_button_read(void) { - // button is active low - return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; -} - -int board_uart_read(uint8_t* buf, int len) { - (void) buf; - (void) len; - return 0; -} - -int board_uart_write(void const* buf, int len) { - (void) buf; - (void) len; - return 0; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; -void SysTick_Handler(void) { - system_ticks++; -} - -uint32_t board_millis(void) { - return system_ticks; -} - -#endif - -void _init(void) { - -} diff --git a/hw/bsp/saml2x/family.cmake b/hw/bsp/saml2x/family.cmake deleted file mode 100644 index 49f2e3e75..000000000 --- a/hw/bsp/saml2x/family.cmake +++ /dev/null @@ -1,115 +0,0 @@ -include_guard() - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -set(SDK_DIR ${TOP}/hw/mcu/microchip/${SAM_FAMILY}) -set(CMSIS_5 ${TOP}/lib/CMSIS_5) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) - -set(FAMILY_MCUS SAML21 SAML22 CACHE INTERNAL "") -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -c \"transport select swd\" -f target/at91samdXX.cfg") - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - message(FATAL_ERROR "LD_FILE_${CMAKE_C_COMPILER_ID} not defined") - endif () - - set(STARTUP_FILE_GNU ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - add_library(${BOARD_TARGET} STATIC - ${SDK_DIR}/gcc/system_${SAM_FAMILY}.c - ${SDK_DIR}/hal/src/hal_atomic.c - ${SDK_DIR}/hpl/gclk/hpl_gclk.c - ${SDK_DIR}/hpl/mclk/hpl_mclk.c - ${SDK_DIR}/hpl/osc32kctrl/hpl_osc32kctrl.c - ${SDK_DIR}/hpl/oscctrl/hpl_oscctrl.c - ${SDK_DIR}/hpl/pm/hpl_pm.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${SDK_DIR} - ${SDK_DIR}/config - ${SDK_DIR}/include - ${SDK_DIR}/hal/include - ${SDK_DIR}/hal/utils/include - ${SDK_DIR}/hpl/pm - ${SDK_DIR}/hpl/port - ${SDK_DIR}/hri - ${CMSIS_5}/CMSIS/Core/Include - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CONF_OSC32K_CALIB_ENABLE=0 - CFG_EXAMPLE_VIDEO_READONLY - ) - - update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () -endfunction() - - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_SAML22) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/microchip/samd/dcd_samd.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - #family_flash_openocd(${TARGET}) -endfunction() diff --git a/hw/bsp/saml2x/family.mk b/hw/bsp/saml2x/family.mk deleted file mode 100644 index 65dfe5032..000000000 --- a/hw/bsp/saml2x/family.mk +++ /dev/null @@ -1,53 +0,0 @@ -UF2_FAMILY_ID = 0x68ed2b88 -SDK_DIR = hw/mcu/microchip/$(SAM_FAMILY) - -include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= cortex-m0plus - -CFLAGS += \ - -flto \ - -DCONF_OSC32K_CALIB_ENABLE=0 \ - -DCFG_TUSB_MCU=OPT_MCU_SAML22 \ - -DCFG_EXAMPLE_VIDEO_READONLY \ - -# suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=redundant-decls - -# SAM driver is flooded with -Wcast-qual which slow down complication significantly -CFLAGS_SKIP += -Wcast-qual - -LDFLAGS_GCC += \ - -nostdlib -nostartfiles \ - --specs=nosys.specs --specs=nano.specs \ - -SRC_C += \ - src/portable/microchip/samd/dcd_samd.c \ - $(SDK_DIR)/gcc/gcc/startup_$(SAM_FAMILY).c \ - $(SDK_DIR)/gcc/system_$(SAM_FAMILY).c \ - $(SDK_DIR)/hal/src/hal_atomic.c \ - $(SDK_DIR)/hpl/gclk/hpl_gclk.c \ - $(SDK_DIR)/hpl/mclk/hpl_mclk.c \ - $(SDK_DIR)/hpl/osc32kctrl/hpl_osc32kctrl.c \ - $(SDK_DIR)/hpl/oscctrl/hpl_oscctrl.c \ - $(SDK_DIR)/hpl/pm/hpl_pm.c \ - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/${SDK_DIR} \ - $(TOP)/${SDK_DIR}/config \ - $(TOP)/${SDK_DIR}/include \ - $(TOP)/${SDK_DIR}/hal/include \ - $(TOP)/${SDK_DIR}/hal/utils/include \ - $(TOP)/${SDK_DIR}/hpl/pm/ \ - $(TOP)/${SDK_DIR}/hpl/port \ - $(TOP)/${SDK_DIR}/hri \ - $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ - -# flash using bossac at least version 1.8 -# can be found in arduino15/packages/arduino/tools/bossac/ -# Add it to your PATH or change BOSSAC variable to match your installation -BOSSAC = bossac - -flash-bossac: $(BUILD)/$(PROJECT).bin - @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) - $(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R diff --git a/hw/bsp/stm32c0/family.cmake b/hw/bsp/stm32c0/family.cmake index c6a90fff6..90d5322b7 100644 --- a/hw/bsp/stm32c0/family.cmake +++ b/hw/bsp/stm32c0/family.cmake @@ -18,22 +18,18 @@ set(FAMILY_MCUS STM32C0 CACHE INTERNAL "") set(OPENOCD_OPTION "-f interface/stlink.cfg -f target/stm32c0x.cfg") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -46,7 +42,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_dma.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -59,56 +54,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32C0) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/typec/typec_stm32.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32C0) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ${TOP}/src/portable/st/typec/typec_stm32.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32f0/family.cmake b/hw/bsp/stm32f0/family.cmake index 12c7b592c..ee73ae872 100644 --- a/hw/bsp/stm32f0/family.cmake +++ b/hw/bsp/stm32f0/family.cmake @@ -18,22 +18,18 @@ set(FAMILY_MCUS STM32F0 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -43,7 +39,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -57,55 +52,49 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32F0) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32F0) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32f1/family.cmake b/hw/bsp/stm32f1/family.cmake index cbb9c3568..064f32096 100644 --- a/hw/bsp/stm32f1/family.cmake +++ b/hw/bsp/stm32f1/family.cmake @@ -18,24 +18,20 @@ set(FAMILY_MCUS STM32F1 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_IAR) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) - endif () +#------------------------------------ +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED LD_FILE_IAR) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +endif () +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -44,7 +40,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -52,59 +47,51 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) - #target_compile_options(${BOARD_TARGET} PUBLIC) - #target_compile_definitions(${BOARD_TARGET} PUBLIC) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32F1) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32F1) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32f2/family.cmake b/hw/bsp/stm32f2/family.cmake index dc6bc2885..7152a0679 100644 --- a/hw/bsp/stm32f2/family.cmake +++ b/hw/bsp/stm32f2/family.cmake @@ -18,24 +18,20 @@ set(FAMILY_MCUS STM32F2 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if (NOT DEFINED LD_FILE_IAR) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) - endif () +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED LD_FILE_IAR) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +endif () +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -44,7 +40,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -52,61 +47,53 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) - #target_compile_options(${BOARD_TARGET} PUBLIC) - #target_compile_definitions(${BOARD_TARGET} PUBLIC) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32F2) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32F2) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32f3/family.cmake b/hw/bsp/stm32f3/family.cmake index 0ba2920d5..7c9e97e62 100644 --- a/hw/bsp/stm32f3/family.cmake +++ b/hw/bsp/stm32f3/family.cmake @@ -18,22 +18,18 @@ set(FAMILY_MCUS STM32F3 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -42,7 +38,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -54,55 +49,49 @@ function(add_board_target BOARD_TARGET) #target_compile_definitions(${BOARD_TARGET} PUBLIC) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32F3) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32F3) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index 260927903..6e02b0575 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -54,7 +54,7 @@ void OTG_HS_IRQHandler(void) { // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32f4/family.cmake b/hw/bsp/stm32f4/family.cmake index db5736192..0d3d9ec93 100644 --- a/hw/bsp/stm32f4/family.cmake +++ b/hw/bsp/stm32f4/family.cmake @@ -40,22 +40,18 @@ endif () cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -66,7 +62,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -82,57 +77,51 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32F4) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32F4) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index bf2d28e42..38dfaa3bc 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -46,7 +46,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32f7/family.cmake b/hw/bsp/stm32f7/family.cmake index 1a3365332..d405753d4 100644 --- a/hw/bsp/stm32f7/family.cmake +++ b/hw/bsp/stm32f7/family.cmake @@ -40,22 +40,18 @@ endif () cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -68,7 +64,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -84,57 +79,51 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32F7) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32F7) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index 4da26f27e..572f0e644 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -18,22 +18,18 @@ set(FAMILY_MCUS STM32G0 CACHE INTERNAL "") set(OPENOCD_OPTION "-f interface/stlink.cfg -f target/stm32g0x.cfg") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -46,7 +42,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_dma.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -54,60 +49,52 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) -# target_compile_options(${BOARD_TARGET} PUBLIC) -# target_compile_definitions(${BOARD_TARGET} PUBLIC) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32G0) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/typec/typec_stm32.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32G0) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ${TOP}/src/portable/st/typec/typec_stm32.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 5ec9926fe..7e8b319b8 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -18,22 +18,18 @@ set(FAMILY_MCUS STM32G4 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -44,7 +40,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -54,56 +49,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32G4) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/typec/typec_stm32.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32G4) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ${TOP}/src/portable/st/typec/typec_stm32.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32h5/family.cmake b/hw/bsp/stm32h5/family.cmake index 1df6bcb90..6e63c4072 100644 --- a/hw/bsp/stm32h5/family.cmake +++ b/hw/bsp/stm32h5/family.cmake @@ -18,24 +18,20 @@ set(FAMILY_MCUS STM32H5 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - string(REPLACE "stm32h" "STM32H" MCU_VARIANT_UPPER ${MCU_VARIANT}) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT_UPPER}_FLASH.ld) - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +string(REPLACE "stm32h" "STM32H" MCU_VARIANT_UPPER ${MCU_VARIANT}) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT_UPPER}_FLASH.ld) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -48,7 +44,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_dma.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -58,56 +53,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32H5) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/st/typec/typec_stm32.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32H5) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ${TOP}/src/portable/st/typec/typec_stm32.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/board.cmake b/hw/bsp/stm32h7/boards/stm32h743eval/board.cmake index 02c6bf5fa..78a821298 100644 --- a/hw/bsp/stm32h7/boards/stm32h743eval/board.cmake +++ b/hw/bsp/stm32h7/boards/stm32h743eval/board.cmake @@ -15,7 +15,7 @@ if (NOT DEFINED RHPORT_HOST) endif() function(update_board TARGET) - target_sources(${TARGET} PUBLIC + target_sources(${TARGET} PRIVATE ${ST_MFXSTM32L152}/mfxstm32l152.c ${ST_MFXSTM32L152}/mfxstm32l152_reg.c ) diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/board.h b/hw/bsp/stm32h7/boards/stm32h743eval/board.h index 7c3f6414a..96bfc24e1 100644 --- a/hw/bsp/stm32h7/boards/stm32h743eval/board.h +++ b/hw/bsp/stm32h7/boards/stm32h743eval/board.h @@ -61,7 +61,7 @@ static board_pindef_t board_pindef[] = { { // LED .port = GPIOA, .pin_init = { .Pin = GPIO_PIN_4, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_HIGH, .Alternate = 0 }, - .active_state = 1 + .active_state = 0 }, { // Button .port = GPIOC, @@ -214,6 +214,10 @@ static int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint return 0; } +static int32_t i2c_get_tick(void) { + return (int32_t) HAL_GetTick(); +} + static inline void board_init2(void) { // IO control via MFX MFXSTM32L152_IO_t io_ctx; @@ -221,7 +225,7 @@ static inline void board_init2(void) { io_ctx.DeInit = board_i2c_deinit; io_ctx.ReadReg = i2c_readreg; io_ctx.WriteReg = i2c_writereg; - io_ctx.GetTick = (MFXSTM32L152_GetTick_Func) HAL_GetTick; + io_ctx.GetTick = i2c_get_tick; uint16_t i2c_addr[] = { 0x84, 0x86 }; for(uint8_t i = 0U; i < 2U; i++) { diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index 382b878b7..7b618b2e4 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -49,7 +49,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, @@ -127,11 +127,11 @@ void board_init(void) { #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); + SysTick_Config(SystemCoreClock / 1000u); #elif CFG_TUSB_OS == OPT_OS_FREERTOS // Explicitly disable systick to prevent its ISR runs before scheduler start - SysTick->CTRL &= ~1U; + SysTick->CTRL &= ~1UL; // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) #ifdef USB_OTG_FS_PERIPH_BASE diff --git a/hw/bsp/stm32h7/family.cmake b/hw/bsp/stm32h7/family.cmake index b4f0bebbf..8b6086356 100644 --- a/hw/bsp/stm32h7/family.cmake +++ b/hw/bsp/stm32h7/family.cmake @@ -41,24 +41,22 @@ endif () cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - if(NOT DEFINED LD_FILE_IAR) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) - endif() +set(LD_FILE_Clang ${LD_FILE_GNU}) +if(NOT DEFINED LD_FILE_IAR) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +endif() +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -73,7 +71,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -89,57 +86,43 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32H7) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32H7) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC "LINKER:--script=${LD_FILE_GNU}") + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC -nostartfiles --specs=nosys.specs --specs=nano.specs) + endif () + + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC "LINKER:--config=${LD_FILE_IAR}") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake index aae820aee..7b3456585 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake @@ -1,5 +1,5 @@ set(MCU_VARIANT stm32h7s3xx) -set(JLINK_DEVICE stm32h7s3xx) +set(JLINK_DEVICE stm32h7s3l8) set(LD_FILE_Clang ${LD_FILE_GNU}) diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk index 47055a108..40b15bc0e 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = stm32h7s3xx CFLAGS += -DSTM32H7S3xx # For flash-jlink target -JLINK_DEVICE = stm32h7s3xx +JLINK_DEVICE = stm32h7s3l8 # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index 80ac81125..6192f7a40 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -49,7 +49,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index 40230ef12..1fd1cb057 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -40,27 +40,23 @@ endif () cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - if(NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT}_flash.ld) - endif() - set(LD_FILE_Clang ${LD_FILE_GNU}) - if(NOT DEFINED LD_FILE_IAR) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) - endif() +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +if(NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_flash.ld) +endif() +set(LD_FILE_Clang ${LD_FILE_GNU}) +if(NOT DEFINED LD_FILE_IAR) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +endif() +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -74,7 +70,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -92,56 +87,52 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32H7RS ${RTOS}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32H7RS ${RTOS}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/stm32h7rs/family.mk b/hw/bsp/stm32h7rs/family.mk index fba38448d..7082cc900 100644 --- a/hw/bsp/stm32h7rs/family.mk +++ b/hw/bsp/stm32h7rs/family.mk @@ -43,7 +43,7 @@ CFLAGS += \ -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ - -DSEGGER_RTT_SECTION="noncacheable_buffer" \ + -DSEGGER_RTT_SECTION="\"noncacheable_buffer\"" \ -DBUFFER_SIZE_UP=0x300 \ # GCC Flags diff --git a/hw/bsp/stm32l0/family.cmake b/hw/bsp/stm32l0/family.cmake index 954bdb158..b6b0139a0 100644 --- a/hw/bsp/stm32l0/family.cmake +++ b/hw/bsp/stm32l0/family.cmake @@ -18,22 +18,18 @@ set(FAMILY_MCUS STM32L0 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -43,7 +39,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -58,55 +53,49 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32L0) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32L0) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32l4/boards/stm32l496nucleo/STM32L496ZGTX_FLASH.ld b/hw/bsp/stm32l4/boards/stm32l496nucleo/STM32L496ZGTX_FLASH.ld new file mode 100644 index 000000000..fcd5daee3 --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l496nucleo/STM32L496ZGTX_FLASH.ld @@ -0,0 +1,208 @@ +/* +****************************************************************************** +** +** @file : LinkerScript.ld +** +** @author : Auto-generated by STM32CubeIDE +** +** Abstract : Linker script for NUCLEO-L496ZG Board embedding STM32L496ZGTx Device from stm32l4 series +** 1024Kbytes ROM +** 256Kbytes RAM +** 64Kbytes SRAM2 +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +** Copyright (c) 2022 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K + SRAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 64K + ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +} + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +/* Sections */ +SECTIONS +{ + /* The startup code into "ROM" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >ROM + + /* The program code and other data into "ROM" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >ROM + + /* Constant data into "ROM" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >ROM + + .ARM.extab : + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >ROM + + .ARM : + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >ROM + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >ROM + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >ROM + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >ROM + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> ROM + + _sisram2 = LOADADDR(.sram2); + + /* SRAM2 section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .sram2 : + { + . = ALIGN(4); + _ssram2 = .; /* create a global symbol at sram2 start */ + *(.sram2) + *(.sram2*) + + . = ALIGN(4); + _esram2 = .; /* create a global symbol at sram2 end */ + } >SRAM2 AT> ROM + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/hw/bsp/stm32l4/boards/stm32l496nucleo/board.cmake b/hw/bsp/stm32l4/boards/stm32l496nucleo/board.cmake new file mode 100644 index 000000000..bfa8261b9 --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l496nucleo/board.cmake @@ -0,0 +1,10 @@ +set(MCU_VARIANT stm32l496xx) +set(JLINK_DEVICE stm32l496zg) + +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/STM32L496ZGTX_FLASH.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + STM32L496xx + ) +endfunction() diff --git a/hw/bsp/stm32l4/boards/stm32l496nucleo/board.h b/hw/bsp/stm32l4/boards/stm32l496nucleo/board.h new file mode 100644 index 000000000..607210cec --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l496nucleo/board.h @@ -0,0 +1,158 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + */ + +/* metadata: + name: STM32 L496 Nucleo + url: https://www.st.com/en/evaluation-tools/nucleo-l496ZG-P.html +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define LED_PORT GPIOB +#define LED_PIN GPIO_PIN_7 +#define LED_STATE_ON 1 + +// Not a real button +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_13 +#define BUTTON_STATE_ACTIVE 1 + +#define UART_DEV LPUART1 +#define UART_CLK_EN __HAL_RCC_LPUART1_CLK_ENABLE +#define UART_GPIO_PORT GPIOG +#define UART_GPIO_AF GPIO_AF8_LPUART1 +#define UART_TX_PIN GPIO_PIN_7 +#define UART_RX_PIN GPIO_PIN_8 + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (MSI) + * SYSCLK(Hz) = 80000000 + * HCLK(Hz) = 80000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 1 + * APB2 Prescaler = 1 + * MSI Frequency(Hz) = 8000000 + * PLL_M = 1 + * PLL_N = 10 + * PLL_Q = 2 + * PLL_R = 2 + * VDD(V) = 3.3 + * @param None + * @retval None + */ + +static inline void board_clock_init(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + + /** Configure the main internal regulator output voltage + */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); + + /** Configure LSE Drive Capability + */ + HAL_PWR_EnableBkUpAccess(); + __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = 1; + RCC_OscInitStruct.PLL.PLLN = 10; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); + + // /** Enable the SYSCFG APB clock + // */ + // __HAL_RCC_CRS_CLK_ENABLE(); + // + // /** Configures CRS + // */ + // RCC_CRSInitTypeDef RCC_CRSInitStruct = {0}; + // RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1; + // RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB; + // RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING; + // RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000); + // RCC_CRSInitStruct.ErrorLimitValue = 34; + // RCC_CRSInitStruct.HSI48CalibrationValue = 32; + // + // HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct); + + /* Select HSI48 output as USB clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + + /* Select PLL output as UART clock source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPUART1; + PeriphClkInitStruct.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); +} + +static inline void board_vbus_sense_init(void) +{ + // Enable VBUS sense (B device) via pin PA9 + USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32l4/boards/stm32l496nucleo/board.mk b/hw/bsp/stm32l4/boards/stm32l496nucleo/board.mk new file mode 100644 index 000000000..bc0a63c1c --- /dev/null +++ b/hw/bsp/stm32l4/boards/stm32l496nucleo/board.mk @@ -0,0 +1,13 @@ +CFLAGS += \ + -DSTM32L496xx \ + +# GCC +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l496xx.s +LD_FILE_GCC = $(BOARD_PATH)/STM32L496ZGTX_FLASH.ld + +# IAR +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_stm32l496xx.s +LD_FILE_IAR = $(ST_CMSIS)/Source/Templates/iar/linker/stm32l496xx_flash.icf + +# For flash-jlink target +JLINK_DEVICE = stm32l496zg diff --git a/hw/bsp/stm32l4/family.c b/hw/bsp/stm32l4/family.c index 5c6ba5c61..114a6a483 100644 --- a/hw/bsp/stm32l4/family.c +++ b/hw/bsp/stm32l4/family.c @@ -145,7 +145,7 @@ void board_init(void) { GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; #if defined(USB_OTG_FS) GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; #else diff --git a/hw/bsp/stm32l4/family.cmake b/hw/bsp/stm32l4/family.cmake index eebcff4f3..5bc28dd5d 100644 --- a/hw/bsp/stm32l4/family.cmake +++ b/hw/bsp/stm32l4/family.cmake @@ -18,22 +18,18 @@ set(FAMILY_MCUS STM32L4 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -46,7 +42,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -54,62 +49,54 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) -# target_compile_options(${BOARD_TARGET} PUBLIC) -# target_compile_definitions(${BOARD_TARGET} PUBLIC) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${FAMILY_MCUS}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${FAMILY_MCUS}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32n6/boards/stm32n6570dk/board.h b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h index a3d945f76..bbcad6340 100644 --- a/hw/bsp/stm32n6/boards/stm32n6570dk/board.h +++ b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h @@ -97,7 +97,7 @@ static board_pindef_t board_pindef[] = { //--------------------------------------------------------------------+ // RCC Clock //--------------------------------------------------------------------+ -void SystemClock_Config(void) { +static void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /* Configure the power domain */ @@ -214,7 +214,7 @@ static I2C_HandleTypeDef i2c_handle = { }}; static TCPP0203_Object_t tcpp0203_obj = {0}; -int32_t board_tcpp0203_init(void) { +static int32_t board_tcpp0203_init(void) { board_pindef_t *pindef = &board_pindef[PINID_TCPP0203_EN]; HAL_GPIO_WritePin(pindef->port, pindef->pin_init.Pin, GPIO_PIN_SET); @@ -231,16 +231,16 @@ int32_t board_tcpp0203_init(void) { return 0; } -int32_t board_tcpp0203_deinit(void) { +static int32_t board_tcpp0203_deinit(void) { return 0; } -int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { +static int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { TU_ASSERT(HAL_OK == HAL_I2C_Mem_Read(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); return 0; } -int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { +static int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { TU_ASSERT(HAL_OK == HAL_I2C_Mem_Write(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); return 0; } diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h index 963ecad61..33c68f7cf 100644 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h @@ -97,7 +97,7 @@ static board_pindef_t board_pindef[] = { //--------------------------------------------------------------------+ // RCC Clock //--------------------------------------------------------------------+ -void SystemClock_Config(void) { +static void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /* Configure the power domain */ diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c index 1d0616d8e..58be4867d 100644 --- a/hw/bsp/stm32n6/family.c +++ b/hw/bsp/stm32n6/family.c @@ -62,7 +62,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32n6/family.cmake b/hw/bsp/stm32n6/family.cmake index 89e4989ad..6c7aaea61 100644 --- a/hw/bsp/stm32n6/family.cmake +++ b/hw/bsp/stm32n6/family.cmake @@ -38,27 +38,23 @@ endif () cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - if(NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_axisram2_fsbl.ld) - endif() - set(LD_FILE_Clang ${LD_FILE_GNU}) - if(NOT DEFINED LD_FILE_IAR) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_axisram2_fsbl.icf) - endif() +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +if(NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_axisram2_fsbl.ld) +endif() +set(LD_FILE_Clang ${LD_FILE_GNU}) +if(NOT DEFINED LD_FILE_IAR) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_axisram2_fsbl.icf) +endif() +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}_fsbl.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -72,11 +68,10 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMSIS_5}/CMSIS/Core/Include + ${TOP}/lib/CMSIS_6/CMSIS/Core/Include ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) @@ -90,56 +85,53 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32N6 ${RTOS}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32N6 ${RTOS}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/stm32n6/family.mk b/hw/bsp/stm32n6/family.mk index 37087ed42..45554e251 100644 --- a/hw/bsp/stm32n6/family.mk +++ b/hw/bsp/stm32n6/family.mk @@ -76,7 +76,7 @@ SRC_C += \ INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/lib/CMSIS_6/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc diff --git a/hw/bsp/stm32u0/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32u0/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..b63275276 --- /dev/null +++ b/hw/bsp/stm32u0/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,149 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "stm32u0xx.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 0 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 200 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<<configPRIO_BITS) - 1) + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +#endif diff --git a/hw/bsp/stm32u0/boards/stm32u083cdk/STM32U083MCTx_FLASH.ld b/hw/bsp/stm32u0/boards/stm32u083cdk/STM32U083MCTx_FLASH.ld new file mode 100644 index 000000000..c5ea72fb0 --- /dev/null +++ b/hw/bsp/stm32u0/boards/stm32u083cdk/STM32U083MCTx_FLASH.ld @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file LinkerScript.ld + * @author Auto-generated by STM32CubeIDE + * @brief Linker script for STM32U083MCTx Device from STM32U0 series + * 256KBytes FLASH + * 40KBytes RAM + * + * Set heap size, stack size and stack location according + * to application requirements. + * + * Set memory bank area and size if external memory is used + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Memories definition */ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 40K + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K +} + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x800; /* required amount of stack */ + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/hw/bsp/stm32u0/boards/stm32u083cdk/board.cmake b/hw/bsp/stm32u0/boards/stm32u083cdk/board.cmake new file mode 100644 index 000000000..945146810 --- /dev/null +++ b/hw/bsp/stm32u0/boards/stm32u083cdk/board.cmake @@ -0,0 +1,12 @@ +set(MCU_VARIANT stm32u083xx) +set(JLINK_DEVICE stm32u083mc) + +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/STM32U083MCTx_FLASH.ld) +set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/stm32u083xx_flash.icf) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + STM32U083xx + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/stm32u0/boards/stm32u083cdk/board.h b/hw/bsp/stm32u0/boards/stm32u083cdk/board.h new file mode 100644 index 000000000..3030b1a1d --- /dev/null +++ b/hw/bsp/stm32u0/boards/stm32u083cdk/board.h @@ -0,0 +1,129 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + */ + +/* metadata: + name: STM32U083C-DK Discovery Kit + url: https://www.st.com/en/evaluation-tools/stm32u083c-dk.html +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED - using PA5 (Blue LED from CubeMX) +#define LED_PORT GPIOA +#define LED_PIN GPIO_PIN_5 +#define LED_STATE_ON 1 + +// Button - using PC2 (from CubeMX generated code) +#define BUTTON_PORT GPIOC +#define BUTTON_PIN GPIO_PIN_2 +#define BUTTON_STATE_ACTIVE 0 // Active low (pressed = 0) + +// UART - using USART2 on PA2/PA3 (VCP TX/RX from CubeMX) +#define UART_DEV USART2 +#define UART_CLK_EN __HAL_RCC_USART2_CLK_ENABLE +#define UART_GPIO_PORT GPIOA +#define UART_GPIO_AF GPIO_AF7_USART2 +#define UART_TX_PIN GPIO_PIN_2 +#define UART_RX_PIN GPIO_PIN_3 + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +static inline void board_stm32u0_clock_init(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_CRSInitTypeDef RCC_CRSInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Configure the main internal regulator output voltage + */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1; + RCC_OscInitStruct.PLL.PLLN = 8; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV4; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); + + /** Enable the CRS clock + */ + __HAL_RCC_CRS_CLK_ENABLE(); + + /** Configures CRS + */ + RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1; + RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB; + RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING; + RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000); + RCC_CRSInitStruct.ErrorLimitValue = 34; + RCC_CRSInitStruct.HSI48CalibrationValue = 32; + HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct); + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2; + PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); +} + +static inline void board_vbus_sense_init(void) +{ + // USB VBUS sensing not required for device-only operation +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32u0/boards/stm32u083cdk/board.mk b/hw/bsp/stm32u0/boards/stm32u083cdk/board.mk new file mode 100644 index 000000000..892854f54 --- /dev/null +++ b/hw/bsp/stm32u0/boards/stm32u083cdk/board.mk @@ -0,0 +1,13 @@ +MCU_VARIANT = stm32u083xx +CFLAGS += \ + -DSTM32U083xx + +# All source paths should be relative to the top level. +LD_FILE = $(BOARD_PATH)/STM32U083MCTx_FLASH.ld +LD_FILE_IAR = $(BOARD_PATH)/stm32u083xx_flash.icf + +# For flash-jlink target +JLINK_DEVICE = STM32U083MC + +# flash target using on-board stlink +flash: flash-stlink diff --git a/hw/bsp/stm32u0/boards/stm32u083cdk/stm32u083xx_flash.icf b/hw/bsp/stm32u0/boards/stm32u083cdk/stm32u083xx_flash.icf new file mode 100644 index 000000000..cfaa305af --- /dev/null +++ b/hw/bsp/stm32u0/boards/stm32u083cdk/stm32u083xx_flash.icf @@ -0,0 +1,32 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0803FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x20007FFF; + +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x800; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + + +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite, + block CSTACK, block HEAP }; diff --git a/hw/bsp/stm32u0/family.c b/hw/bsp/stm32u0/family.c new file mode 100644 index 000000000..bf2503865 --- /dev/null +++ b/hw/bsp/stm32u0/family.c @@ -0,0 +1,182 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 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. + */ + +/* metadata: + manufacturer: STMicroelectronics +*/ + +#include "stm32u0xx_hal.h" +#include "bsp/board_api.h" +#include "board.h" + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_DRD_FS_IRQHandler(void) { + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ +#ifdef UART_DEV +UART_HandleTypeDef UartHandle; +#endif + +void board_init(void) { + board_stm32u0_clock_init(); + + // Enable All GPIOs clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); +#ifdef GPIOD + __HAL_RCC_GPIOD_CLK_ENABLE(); +#endif +#ifdef GPIOE + __HAL_RCC_GPIOE_CLK_ENABLE(); +#endif +#ifdef GPIOF + __HAL_RCC_GPIOF_CLK_ENABLE(); +#endif +#ifdef GPIOG + __HAL_RCC_GPIOG_CLK_ENABLE(); +#endif +#ifdef GPIOH + __HAL_RCC_GPIOH_CLK_ENABLE(); +#endif + __HAL_RCC_PWR_CLK_ENABLE(); + + // LED + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = LED_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + // Button + GPIO_InitStruct.Pin = BUTTON_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN : GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct); + +#ifdef UART_DEV + // UART + GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = UART_GPIO_AF; + HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct); + + UART_CLK_EN(); + UartHandle.Instance = UART_DEV; + UartHandle.Init.BaudRate = CFG_BOARD_UART_BAUDRATE; + UartHandle.Init.WordLength = UART_WORDLENGTH_8B; + UartHandle.Init.StopBits = UART_STOPBITS_1; + UartHandle.Init.Parity = UART_PARITY_NONE; + UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + UartHandle.Init.Mode = UART_MODE_TX_RX; + UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; + HAL_UART_Init(&UartHandle); +#endif + +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_DRD_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + + // USB Pins TODO double check USB clock and pin setup + // Configure USB DM and DP pins. This is optional, and maintained only for user guidance. + GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_USB; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // Enable VDDUSB + HAL_PWREx_EnableVddUSB(); + // USB Clock enable + __HAL_RCC_USB_CLK_ENABLE(); + + board_vbus_sense_init(); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { + GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1-LED_STATE_ON)); + HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state); +} + +uint32_t board_button_read(void) { + return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); +} + +int board_uart_read(uint8_t* buf, int len) { +#ifdef UART_DEV + (void) buf; (void) len; + return 0; +#else + return 0; +#endif +} + +int board_uart_write(void const * buf, int len) { +#ifdef UART_DEV + HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff); + return len; +#else + (void) buf; (void) len; + return 0; +#endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) { + system_ticks++; +} + +uint32_t board_millis(void) { + return system_ticks; +} +#endif + +void HardFault_Handler(void) { + __asm("BKPT #0\n"); +} + +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) { + +} diff --git a/hw/bsp/stm32u0/family.cmake b/hw/bsp/stm32u0/family.cmake new file mode 100644 index 000000000..4f9b03109 --- /dev/null +++ b/hw/bsp/stm32u0/family.cmake @@ -0,0 +1,106 @@ +include_guard() + +set(ST_FAMILY u0) +set(ST_PREFIX stm32${ST_FAMILY}xx) + +set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) +set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis-device-${ST_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m0plus CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS STM32U0 CACHE INTERNAL "") + + +#------------------------------------ +# Startup & Linker script +#------------------------------------ +string(REPLACE "stm32u" "STM32U" MCU_VARIANT_UPPER ${MCU_VARIANT}) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT_UPPER}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +if (NOT DEFINED LD_FILE_IAR) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +endif () + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + update_board(${BOARD_TARGET}) +endfunction() + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32U0) + + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_stlink(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/stm32u0/family.mk b/hw/bsp/stm32u0/family.mk new file mode 100644 index 000000000..d5a850050 --- /dev/null +++ b/hw/bsp/stm32u0/family.mk @@ -0,0 +1,50 @@ +ST_FAMILY = u0 +ST_CMSIS = hw/mcu/st/cmsis-device-$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= cortex-m0plus + +CFLAGS += \ + -DCFG_EXAMPLE_MSC_READONLY \ + -DCFG_EXAMPLE_VIDEO_READONLY \ + -DCFG_TUSB_MCU=OPT_MCU_STM32U0 + +# mcu driver cause following warnings +CFLAGS_GCC += \ + -flto \ + -Wno-error=unused-parameter \ + -Wno-error=redundant-decls \ + -Wno-error=cast-align \ + -Wno-error=maybe-uninitialized \ + +CFLAGS_CLANG += \ + -Wno-error=parentheses-equality + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs + +SRC_C += \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ + $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + ${ST_HAL_DRIVER}/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc + +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_${MCU_VARIANT}.s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_${MCU_VARIANT}.s + +# Linker +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf diff --git a/hw/bsp/stm32u0/stm32u0xx_hal_conf.h b/hw/bsp/stm32u0/stm32u0xx_hal_conf.h new file mode 100644 index 000000000..ece5baf69 --- /dev/null +++ b/hw/bsp/stm32u0/stm32u0xx_hal_conf.h @@ -0,0 +1,337 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32u0xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32U0xx_HAL_CONF_H +#define __STM32U0xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_COMP_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRS_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_I2C_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LCD_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_OPAMP_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +/* #define HAL_TSC_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 4000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI32_VALUE) +#define MSI32_VALUE 32000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI32_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (3U) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ + +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32u0xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LCD_REGISTER_CALLBACKS 0U /* LCD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32u0xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32u0xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32u0xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32u0xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32u0xx_hal_adc.h" +#include "stm32u0xx_hal_adc_ex.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32u0xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32u0xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRS_MODULE_ENABLED +#include "stm32u0xx_ll_crs.h" +#endif /* HAL_CRS_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32u0xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32u0xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32u0xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32u0xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32u0xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32u0xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32u0xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32u0xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32u0xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32u0xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32u0xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32u0xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32u0xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED +#include "stm32u0xx_ll_system.h" +#include "stm32u0xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32u0xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32u0xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32u0xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32u0xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32u0xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32u0xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t *file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32U0xx_HAL_CONF_H */ diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake index 7a5935961..70e0c313c 100644 --- a/hw/bsp/stm32u5/family.cmake +++ b/hw/bsp/stm32u5/family.cmake @@ -18,26 +18,22 @@ set(FAMILY_MCUS STM32U5 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - - string(REPLACE "stm32u" "STM32U" MCU_VARIANT_UPPER ${MCU_VARIANT}) - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT_UPPER}_FLASH.ld) - endif () - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +string(REPLACE "stm32u" "STM32U" MCU_VARIANT_UPPER ${MCU_VARIANT}) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT_UPPER}_FLASH.ld) +endif () +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -49,7 +45,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -58,59 +53,52 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Inc ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32U5) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32U5) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - #${TOP}/src/portable/st/typec/typec_stm32.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32wb/family.cmake b/hw/bsp/stm32wb/family.cmake index 0ea937257..1a96e3d7e 100644 --- a/hw/bsp/stm32wb/family.cmake +++ b/hw/bsp/stm32wb/family.cmake @@ -18,25 +18,21 @@ set(FAMILY_MCUS STM32WB CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}_cm4.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}_cm4.s) - - if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash_cm4.ld) - endif() - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash_cm4.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}_cm4.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}_cm4.s) +if (NOT DEFINED LD_FILE_GNU) +set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash_cm4.ld) +endif() +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash_cm4.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -49,7 +45,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -57,59 +52,51 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) -# target_compile_options(${BOARD_TARGET} PUBLIC) -# target_compile_definitions(${BOARD_TARGET} PUBLIC) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_${FAMILY_MCUS}) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${FAMILY_MCUS}) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing diff --git a/hw/bsp/stm32wba/family.cmake b/hw/bsp/stm32wba/family.cmake index 3f42879be..9628913cc 100644 --- a/hw/bsp/stm32wba/family.cmake +++ b/hw/bsp/stm32wba/family.cmake @@ -27,27 +27,23 @@ set(RHPORT_DEVICE_SPEED OPT_MODE_HIGH_SPEED) set(RHPORT_HOST_SPEED OPT_MODE_HIGH_SPEED) #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - # STM32WBA HAL uses uppercase MCU_VARIANT (excluding the x's) for linking and lowercase MCU_VARIANT for startup. - string(TOUPPER "${MCU_VARIANT}" UPPERCASE_MCU_VARIANT) - string(REGEX REPLACE "X" "x" UPPERCASE_MCU_VARIANT "${UPPERCASE_MCU_VARIANT}") - - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +# STM32WBA HAL uses uppercase MCU_VARIANT (excluding the x's) for linking and lowercase MCU_VARIANT for startup. +string(TOUPPER "${MCU_VARIANT}" UPPERCASE_MCU_VARIANT) +string(REGEX REPLACE "X" "x" UPPERCASE_MCU_VARIANT "${UPPERCASE_MCU_VARIANT}") - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld) - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash_ns.icf) +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash_ns.icf) +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c @@ -62,7 +58,6 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_ll_usb.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} @@ -72,60 +67,52 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_STM32WBA) - target_compile_definitions(${TARGET} PUBLIC - CFG_TUSB_MCU=OPT_MCU_STM32WBA - ) - - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_STM32WBA) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/tm4c/family.cmake b/hw/bsp/tm4c/family.cmake index e1cf94e96..12f0448a3 100644 --- a/hw/bsp/tm4c/family.cmake +++ b/hw/bsp/tm4c/family.cmake @@ -15,22 +15,18 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS TM4C123 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - set(LD_FILE_Clang ${LD_FILE_GNU}) - - set(STARTUP_FILE_GNU ${SDK_DIR}/Source/GCC/${MCU_VARIANT}_startup.c) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/Source/GCC/${MCU_VARIANT}_startup.c) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/Source/system_${MCU_VARIANT_UPPER}.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR}/Include/${MCU_VARIANT_UPPER} @@ -38,55 +34,47 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs --specs=nano.specs - -uvectors - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for MSP432E4") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_TM4C123) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${TOP}/src/portable/mentor/musb/dcd_musb.c + ${TOP}/src/portable/mentor/musb/hcd_musb.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_TM4C123) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mentor/musb/dcd_musb.c - ${TOP}/src/portable/mentor/musb/hcd_musb.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/xmc4000/family.cmake b/hw/bsp/xmc4000/family.cmake index 6edd72caf..a8fa5351c 100644 --- a/hw/bsp/xmc4000/family.cmake +++ b/hw/bsp/xmc4000/family.cmake @@ -12,19 +12,16 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS XMC4000 CACHE INTERNAL "") #------------------------------------ -# BOARD_TARGET +# Startup & Linker script #------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif() - - set(LD_FILE_Clang ${LD_FILE_GNU}) - - set(STARTUP_FILE_GNU ${SDK_DIR}/CMSIS/Infineon/COMPONENT_${MCU_VARIANT}/Source/TOOLCHAIN_GCC_ARM/startup_${MCU_VARIANT}.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(STARTUP_FILE_GNU ${SDK_DIR}/CMSIS/Infineon/COMPONENT_${MCU_VARIANT}/Source/TOOLCHAIN_GCC_ARM/startup_${MCU_VARIANT}.S) +set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) +#------------------------------------ +# Board Target +#------------------------------------ +function(family_add_board BOARD_TARGET) add_library(${BOARD_TARGET} STATIC ${SDK_DIR}/CMSIS/Infineon/COMPONENT_${MCU_VARIANT}/Source/system_${MCU_VARIANT}.c ${SDK_DIR}/XMCLib/src/xmc_gpio.c @@ -32,7 +29,6 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/XMCLib/src/xmc4_scu.c ${SDK_DIR}/XMCLib/src/xmc_usic.c ${SDK_DIR}/XMCLib/src/xmc_uart.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR}/CMSIS/Core/Include @@ -41,57 +37,50 @@ function(add_board_target BOARD_TARGET) ) update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - --specs=nosys.specs - -nostartfiles - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - message(FATAL_ERROR "Clang is not supported for MSP432E4") - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endfunction() - #------------------------------------ # Functions #------------------------------------ function(family_configure_example TARGET RTOS) family_configure_common(${TARGET} ${RTOS}) + family_add_tinyusb(${TARGET} OPT_MCU_XMC4000) - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC - # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c ${SDK_DIR}/Newlib/syscalls.c + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${TARGET} PUBLIC - # family, hw, board ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} ) - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_XMC4000) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c - ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + --specs=nosys.specs + -nostartfiles + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + set_source_files_properties(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") + endif () + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) # Flashing family_add_bin_hex(${TARGET}) diff --git a/hw/bsp/zephyr_board_aliases.cmake b/hw/bsp/zephyr_board_aliases.cmake index b60e97ef4..a60068208 100644 --- a/hw/bsp/zephyr_board_aliases.cmake +++ b/hw/bsp/zephyr_board_aliases.cmake @@ -1,2 +1,2 @@ -set(pca10056_BOARD_ALIAS nrf52840dk/nrf52840) +set(nrf52840dk_BOARD_ALIAS nrf52840dk/nrf52840) set(stm32n657nucleo_BOARD_ALIAS nucleo_n657x0_q) diff --git a/lib/networking/dhserver.c b/lib/networking/dhserver.c index 9dedf87e2..87a63c5de 100644 --- a/lib/networking/dhserver.c +++ b/lib/networking/dhserver.c @@ -145,7 +145,7 @@ static __inline void free_entry(dhcp_entry_t *entry) memset(entry->mac, 0, 6); } -uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) +static uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) { int i = 0; while ((i + 1) < size) @@ -159,7 +159,7 @@ uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) return NULL; } -int fill_options(void *dest, +static int fill_options(void *dest, uint8_t msg_type, const char *domain, ip4_addr_t dns, diff --git a/lib/networking/rndis_reports.c b/lib/networking/rndis_reports.c index 451d5405b..e2849fb10 100644 --- a/lib/networking/rndis_reports.c +++ b/lib/networking/rndis_reports.c @@ -29,7 +29,10 @@ #include <stdalign.h> #include <string.h> -#include "class/net/net_device.h" +#include "tusb.h" + +#if CFG_TUD_ECM_RNDIS + #include "rndis_protocol.h" #include "netif/ethernet.h" @@ -299,3 +302,5 @@ void rndis_class_set_handler(uint8_t *data, int size) break; } } + +#endif diff --git a/lib/rt-thread/SConscript b/lib/rt-thread/SConscript index 34399fd45..99517a090 100644 --- a/lib/rt-thread/SConscript +++ b/lib/rt-thread/SConscript @@ -34,6 +34,8 @@ if GetDepend(["PKG_TINYUSB_DEVICE_ENABLE"]): src += ["../../src/class/cdc/cdc_device.c"] if GetDepend(["PKG_TINYUSB_DEVICE_MSC"]): src += ["../../src/class/msc/msc_device.c", "port/msc_device_port.c"] + if GetDepend(["PKG_TINYUSB_DEVICE_MTP"]): + src += ["../../src/class/mtp/mtp_device.c"] if GetDepend(["PKG_TINYUSB_DEVICE_HID"]): src += ["../../src/class/hid/hid_device.c"] diff --git a/lib/rt-thread/tusb_config.h b/lib/rt-thread/tusb_config.h index 11dc21983..6f794dc41 100644 --- a/lib/rt-thread/tusb_config.h +++ b/lib/rt-thread/tusb_config.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __RTTHREAD__ #include <rtconfig.h> @@ -215,4 +215,4 @@ extern "C" { #endif #endif /*__RTTHREAD__*/ -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/library.json b/library.json index f1bfd6387..efad438a7 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TinyUSB", - "version": "0.18.0", + "version": "0.20.0", "description": "TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function.", "keywords": "usb, host, device", "repository": diff --git a/repository.yml b/repository.yml index 31c9eddc5..f4da056e3 100644 --- a/repository.yml +++ b/repository.yml @@ -16,5 +16,7 @@ repo.versions: "0.16.0": "0.16.0" "0.17.0": "0.17.0" "0.18.0": "0.18.0" - "0-latest": "0.18.0" + "0.19.0": "0.19.0" + "0.20.0": "0.20.0" + "0-latest": "0.20.0" "0-dev": "0.0.0" diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 000000000..c0032d6e4 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,15 @@ +sonar.projectKey=hathach_tinyusb +sonar.organization=hathach + + +# This is the name and version displayed in the SonarCloud UI. +sonar.projectName=tinyusb +sonar.projectVersion=0.20.0 + + +# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. +#sonar.sources=. +sonar.exclusions=lib/**,hw/mcu/**,test/** + +# Encoding of the source code. Default is default system encoding +#sonar.sourceEncoding=UTF-8 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 99d3059fc..48dc75e50 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.20) -# Add tinyusb to a existing target, DCD and HCD drivers are not included -function(tinyusb_target_add TARGET) - target_sources(${TARGET} PRIVATE +# Get TinyUSB sources. Note: DCD and HCD drivers are not included +function(tinyusb_sources_get OUTPUT_VAR) + set(${OUTPUT_VAR} # common ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tusb.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/common/tusb_fifo.c @@ -16,6 +16,7 @@ function(tinyusb_target_add TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_device.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/midi/midi_device.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_device.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/mtp/mtp_device.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ecm_rndis_device.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/net/ncm_device.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/usbtmc/usbtmc_device.c @@ -31,7 +32,14 @@ function(tinyusb_target_add TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_host.c # typec ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/typec/usbc.c + PARENT_SCOPE ) +endfunction() + +# Add tinyusb to a existing target +function(tinyusb_target_add TARGET) + tinyusb_sources_get(TINYUSB_SRC) + target_sources(${TARGET} PRIVATE ${TINYUSB_SRC}) target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} # TODO for net driver, should be removed/changed diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 0d1acadcc..cff38cc22 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -30,8 +30,8 @@ * Currently only MIDI subclass is supported * @{ */ -#ifndef _TUSB_AUDIO_H__ -#define _TUSB_AUDIO_H__ +#ifndef TUSB_AUDIO_H__ +#define TUSB_AUDIO_H__ #include "common/tusb_common.h" @@ -39,917 +39,1255 @@ extern "C" { #endif -/// Audio Device Class Codes +//--------------------------------------------------------------------+ +// GENERIC AUDIO CLASS CODES (COMMON TO UAC1 AND UAC2) +//--------------------------------------------------------------------+ /// A.2 - Audio Function Subclass Codes -typedef enum -{ +typedef enum { AUDIO_FUNCTION_SUBCLASS_UNDEFINED = 0x00, } audio_function_subclass_type_t; /// A.3 - Audio Function Protocol Codes -typedef enum -{ - AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +typedef enum { + AUDIO_FUNC_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_FUNC_PROTOCOL_CODE_V1 = 0x00,///< Version 1.0 - same as undefined for backward compatibility + AUDIO_FUNC_PROTOCOL_CODE_V2 = 0x20,///< Version 2.0 } audio_function_protocol_code_t; /// A.5 - Audio Interface Subclass Codes -typedef enum -{ +typedef enum { AUDIO_SUBCLASS_UNDEFINED = 0x00, - AUDIO_SUBCLASS_CONTROL , ///< Audio Control - AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming - AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming + AUDIO_SUBCLASS_CONTROL, ///< Audio Control + AUDIO_SUBCLASS_STREAMING, ///< Audio Streaming + AUDIO_SUBCLASS_MIDI_STREAMING,///< MIDI Streaming } audio_subclass_type_t; /// A.6 - Audio Interface Protocol Codes -typedef enum -{ - AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, - AUDIO_INT_PROTOCOL_CODE_V2 = 0x20, ///< Version 2.0 +typedef enum { + AUDIO_INT_PROTOCOL_CODE_UNDEF = 0x00, + AUDIO_INT_PROTOCOL_CODE_V1 = 0x00,///< Version 1.0 - same as undefined for backward compatibility + AUDIO_INT_PROTOCOL_CODE_V2 = 0x20,///< Version 2.0 } audio_interface_protocol_code_t; +/// Terminal Types + +/// 2.1 - Audio Class-Terminal Types +typedef enum { + AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, + AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, + AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, +} audio_terminal_type_t; + +/// 2.2 - Audio Class-Input Terminal Types +typedef enum { + AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, + AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, + AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, + AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, + AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, + AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, + AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, +} audio_terminal_input_type_t; + +/// 2.3 - Audio Class-Output Terminal Types +typedef enum { + AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, + AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, + AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, + AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, + AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, + AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, + AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, + AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, +} audio_terminal_output_type_t; + +/// Rest is yet to be implemented + +//--------------------------------------------------------------------+ +// USB AUDIO CLASS 1.0 (UAC1) DEFINITIONS +//--------------------------------------------------------------------+ + +/// A.5 - Audio Class-Specific AC Interface Descriptor Subtypes UAC1 +typedef enum { + AUDIO10_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO10_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO10_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO10_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO10_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO10_CS_AC_INTERFACE_PROCESSING_UNIT = 0x07, + AUDIO10_CS_AC_INTERFACE_EXTENSION_UNIT = 0x08, +} audio10_cs_ac_interface_subtype_t; + +/// A.6 - Audio Class-Specific AS Interface Descriptor Subtypes UAC1 +typedef enum { + AUDIO10_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO10_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO10_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, +} audio10_cs_as_interface_subtype_t; + +/// A.8 - Audio Class-Specific EP Descriptor Subtypes UAC1 +typedef enum { + AUDIO10_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO10_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio10_cs_ep_subtype_t; + +/// A.9 - Audio Class-Specific Request Codes UAC1 +typedef enum { + AUDIO10_CS_REQ_UNDEF = 0x00, + AUDIO10_CS_REQ_SET_CUR = 0x01, + AUDIO10_CS_REQ_GET_CUR = 0x81, + AUDIO10_CS_REQ_SET_MIN = 0x02, + AUDIO10_CS_REQ_GET_MIN = 0x82, + AUDIO10_CS_REQ_SET_MAX = 0x03, + AUDIO10_CS_REQ_GET_MAX = 0x83, + AUDIO10_CS_REQ_SET_RES = 0x04, + AUDIO10_CS_REQ_GET_RES = 0x84, + AUDIO10_CS_REQ_SET_MEM = 0x05, + AUDIO10_CS_REQ_GET_MEM = 0x85, + AUDIO10_CS_REQ_GET_STAT = 0xFF, +} audio10_cs_req_t; + +/// A.10.1 - Terminal Control Selectors UAC1 +typedef enum { + AUDIO10_TE_CTRL_UNDEF = 0x00, + AUDIO10_TE_CTRL_COPY_PROTECT = 0x01, +} audio10_terminal_control_selector_t; + +/// A.10.2 - Feature Unit Control Selectors UAC1 +typedef enum { + AUDIO10_FU_CTRL_UNDEF = 0x00, + AUDIO10_FU_CTRL_MUTE = 0x01, + AUDIO10_FU_CTRL_VOLUME = 0x02, + AUDIO10_FU_CTRL_BASS = 0x03, + AUDIO10_FU_CTRL_MID = 0x04, + AUDIO10_FU_CTRL_TREBLE = 0x05, + AUDIO10_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO10_FU_CTRL_AGC = 0x07, + AUDIO10_FU_CTRL_DELAY = 0x08, + AUDIO10_FU_CTRL_BASS_BOOST = 0x09, + AUDIO10_FU_CTRL_LOUDNESS = 0x0A, +} audio10_feature_unit_control_selector_t; + +/// A.10.3.1 - Up/Down-mix Processing Unit Control Selectors UAC1 +typedef enum { + AUDIO10_UD_CTRL_UNDEF = 0x00, + AUDIO10_UD_CTRL_ENABLE = 0x01, + AUDIO10_UD_CTRL_MODE_SELECT = 0x02, +} audio10_up_down_mix_control_selector_t; + +/// A.10.3.2 - Dolby Prologic Processing Unit Control Selectors UAC1 +typedef enum { + AUDIO10_DP_CTRL_UNDEF = 0x00, + AUDIO10_DP_CTRL_ENABLE = 0x01, + AUDIO10_DP_CTRL_MODE_SELECT = 0x02, +} audio10_dolby_prologic_control_selector_t; + +/// A.10.3.3 - 3D Stereo Extender Processing Unit Control Selectors UAC1 +typedef enum { + AUDIO10_3D_CTRL_UNDEF = 0x00, + AUDIO10_3D_CTRL_ENABLE = 0x01, + AUDIO10_3D_CTRL_SPACIOUSNESS = 0x02, +} audio10_3d_stereo_extender_control_selector_t; + +/// A.10.3.4 - Reverberation Processing Unit Control Selectors UAC1 +typedef enum { + AUDIO10_RV_CTRL_UNDEF = 0x00, + AUDIO10_RV_CTRL_ENABLE = 0x01, + AUDIO10_RV_CTRL_REVERB_LEVEL = 0x02, + AUDIO10_RV_CTRL_REVERB_TIME = 0x03, + AUDIO10_RV_CTRL_REVERB_FEEDBACK = 0x04, +} audio10_reverberation_control_selector_t; + +/// A.10.3.5 - Chorus Processing Unit Control Selectors UAC1 +typedef enum { + AUDIO10_CH_CTRL_UNDEF = 0x00, + AUDIO10_CH_CTRL_ENABLE = 0x01, + AUDIO10_CH_CTRL_CHORUS_LEVEL = 0x02, + AUDIO10_CH_CTRL_CHORUS_RATE = 0x03, + AUDIO10_CH_CTRL_CHORUS_DEPTH = 0x04, +} audio10_chorus_control_selector_t; + +/// A.10.3.6 - Dynamic Range Compressor Processing Unit Control Selectors UAC1 +typedef enum { + AUDIO10_DR_CTRL_UNDEF = 0x00, + AUDIO10_DR_CTRL_ENABLE = 0x01, + AUDIO10_DR_CTRL_COMPRESSION_RATE = 0x02, + AUDIO10_DR_CTRL_MAXAMPL = 0x03, + AUDIO10_DR_CTRL_THRESHOLD = 0x04, + AUDIO10_DR_CTRL_ATTACK_TIME = 0x05, + AUDIO10_DR_CTRL_RELEASE_TIME = 0x06, +} audio10_dynamic_range_compression_control_selector_t; + +/// A.10.4 - Extension Unit Control Selectors UAC1 +typedef enum { + AUDIO10_XU_CTRL_UNDEF = 0x00, + AUDIO10_XU_CTRL_ENABLE = 0x01, +} audio10_extension_unit_control_selector_t; + +/// A.10.5 - Endpoint Control Selectors UAC1 +typedef enum { + AUDIO10_EP_CTRL_UNDEF = 0x00, + AUDIO10_EP_CTRL_SAMPLING_FREQ = 0x01, + AUDIO10_EP_CTRL_PITCH = 0x02, +} audio10_ep_control_selector_t; + +/// Audio Class-Specific AS Isochronous Data EP Attributes UAC1 +typedef enum { + AUDIO10_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO10_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, + AUDIO10_CS_AS_ISO_DATA_EP_ATT_SAMPLING_FRQ = 0x01, + AUDIO10_CS_AS_ISO_DATA_EP_ATT_PITCH = 0x02, +} audio10_cs_as_iso_data_ep_attribute_t; + +/// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC1 +typedef enum { + AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio10_cs_as_iso_data_ep_lock_delay_unit_t; + +/// Audio Class-Feature Unit Controls UAC1 +typedef enum { + AUDIO10_FU_CONTROL_BM_MUTE = 1 << 0, + AUDIO10_FU_CONTROL_BM_VOLUME = 1 << 1, + AUDIO10_FU_CONTROL_BM_BASS = 1 << 2, + AUDIO10_FU_CONTROL_BM_MID = 1 << 3, + AUDIO10_FU_CONTROL_BM_TREBLE = 1 << 4, + AUDIO10_FU_CONTROL_BM_GRAPHIC_EQUALIZER = 1 << 5, + AUDIO10_FU_CONTROL_BM_AGC = 1 << 6, + AUDIO10_FU_CONTROL_BM_DELAY = 1 << 7, + AUDIO10_FU_CONTROL_BM_BASS_BOOST = 1 << 8, + AUDIO10_FU_CONTROL_BM_LOUDNESS = 1 << 9, +} audio10_feature_unit_control_bitmap_t; + +/// A.1 - Audio Class-Format Type Codes UAC1 +typedef enum { + AUDIO10_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO10_FORMAT_TYPE_I = 0x01, + AUDIO10_FORMAT_TYPE_II = 0x02, + AUDIO10_FORMAT_TYPE_III = 0x03, +} audio10_format_type_t; + +// A.1.1 - Audio Class-Audio Data Format Type I UAC1 +typedef enum { + AUDIO10_DATA_FORMAT_TYPE_I_PCM = 0x0001, + AUDIO10_DATA_FORMAT_TYPE_I_PCM8 = 0x0002, + AUDIO10_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 0x0003, + AUDIO10_DATA_FORMAT_TYPE_I_ALAW = 0x0004, + AUDIO10_DATA_FORMAT_TYPE_I_MULAW = 0x0005, +} audio10_data_format_type_I_t; + +// A.1.2 - Audio Class-Audio Data Format Type II UAC1 +typedef enum { + AUDIO10_DATA_FORMAT_TYPE_II_MPEG = 0x1001, + AUDIO10_DATA_FORMAT_TYPE_II_AC3 = 0x1002, +} audio10_data_format_type_II_t; + +// A.1.3 - Audio Class-Audio Data Format Type III UAC1 +typedef enum { + AUDIO10_DATA_FORMAT_TYPE_III_IEC1937_AC3_1 = 0x2001, + AUDIO10_DATA_FORMAT_TYPE_III_IEC1937_MPEG1_L1_1 = 0x2002, + AUDIO10_DATA_FORMAT_TYPE_III_IEC1937_MPEG1_L23_1 = 0x2003, + AUDIO10_DATA_FORMAT_TYPE_III_IEC1937_MPEG2_EXT_1 = 0x2004, + AUDIO10_DATA_FORMAT_TYPE_III_IEC1937_MPEG2_L1_LS_1 = 0x2005, + AUDIO10_DATA_FORMAT_TYPE_III_IEC1937_MPEG2_L23_LS_1 = 0x2006, +} audio10_data_format_type_III_t; + +/// Audio Class-Audio Channel Configuration UAC1 (Table A-7) +typedef enum { + AUDIO10_CHANNEL_CONFIG_NON_PREDEFINED = 0x0000, + AUDIO10_CHANNEL_CONFIG_LEFT_FRONT = 0x0001, + AUDIO10_CHANNEL_CONFIG_RIGHT_FRONT = 0x0002, + AUDIO10_CHANNEL_CONFIG_CENTER_FRONT = 0x0004, + AUDIO10_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x0008, + AUDIO10_CHANNEL_CONFIG_LEFT_SURROUND = 0x0010, + AUDIO10_CHANNEL_CONFIG_RIGHT_SURROUND = 0x0020, + AUDIO10_CHANNEL_CONFIG_LEFT_OF_CENTER = 0x0040, + AUDIO10_CHANNEL_CONFIG_RIGHT_OF_CENTER = 0x0080, + AUDIO10_CHANNEL_CONFIG_SURROUND = 0x0100, + AUDIO10_CHANNEL_CONFIG_SIDE_LEFT = 0x0200, + AUDIO10_CHANNEL_CONFIG_SIDE_RIGHT = 0x0400, + AUDIO10_CHANNEL_CONFIG_TOP = 0x0800, +} audio10_channel_config_t; + + +//--------------------------------------------------------------------+ +// USB AUDIO CLASS 1.0 (UAC1) DESCRIPTORS +//--------------------------------------------------------------------+ + +/// AUDIO Class-Specific AC Interface Header Descriptor UAC1 (4.3.2) +#define audio10_desc_cs_ac_interface_n_t(numInterfaces) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 8+n. */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_HEADER. */ \ + uint16_t bcdADC; /* Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: 0x0100 for UAC1. */ \ + uint16_t wTotalLength; /* Total number of bytes returned for the class-specific AudioControl interface descriptor. */ \ + uint8_t bInCollection; /* The number of AudioStreaming and MIDIStreaming interfaces in the Audio Interface Collection. */ \ + uint8_t baInterfaceNr[numInterfaces]; /* Interface number of the AudioStreaming or MIDIStreaming interface in the Collection. */ \ + } + +/// AUDIO Input Terminal Descriptor UAC1 (4.3.2.1) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes: 12. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL. + uint8_t bTerminalID; ///< Constant uniquely identifying the Terminal within the audio function. + uint16_t wTerminalType; ///< Constant characterizing the type of Terminal. + uint8_t bAssocTerminal; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bNrChannels; ///< Number of logical output channels in the Terminal's output audio channel cluster. + uint16_t wChannelConfig; ///< Describes the spatial location of the logical channels. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first logical channel. + uint8_t iTerminal; ///< Index of a string descriptor, describing the Input Terminal. +} audio10_desc_input_terminal_t; + +/// AUDIO Output Terminal Descriptor UAC1 (4.3.2.2) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID; ///< Constant uniquely identifying the Terminal within the audio function. + uint16_t wTerminalType; ///< Constant characterizing the type of Terminal. + uint8_t bAssocTerminal; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t iTerminal; ///< Index of a string descriptor, describing the Output Terminal. +} audio10_desc_output_terminal_t; + +/// AUDIO Mixer Unit Descriptor UAC1 (4.3.2.3) +#define audio10_desc_mixer_unit_n_t(numInputPins, numControlBytes) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 10+p+n. */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_MIXER_UNIT. */ \ + uint8_t bUnitID; /* Constant uniquely identifying the Unit within the audio function. */ \ + uint8_t bNrInPins; /* Number of Input Pins of this Unit: p. */ \ + uint8_t baSourceID[numInputPins]; /* ID of the Unit or Terminal to which Input Pins of this Mixer Unit are connected. */ \ + uint8_t bNrChannels; /* Number of logical output channels in the Mixer Unit's output audio channel cluster. */ \ + uint16_t wChannelConfig; /* Describes the spatial location of the logical channels. */ \ + uint8_t iChannelNames; /* Index of a string descriptor, describing the name of the first logical channel. */ \ + uint8_t bmControls[numControlBytes]; /* Mixer Unit Controls bitmap. */ \ + uint8_t iMixer; /* Index of a string descriptor, describing the Mixer Unit. */ \ + } + +/// AUDIO Selector Unit Descriptor UAC1 (4.3.2.4) +#define audio10_desc_selector_unit_n_t(numInputPins) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 6+p. */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_SELECTOR_UNIT. */ \ + uint8_t bUnitID; /* Constant uniquely identifying the Unit within the audio function. */ \ + uint8_t bNrInPins; /* Number of Input Pins of this Unit: p. */ \ + uint8_t baSourceID[numInputPins]; /* ID of the Unit or Terminal to which Input Pins of this Selector Unit are connected. */ \ + uint8_t iSelector; /* Index of a string descriptor, describing the Selector Unit. */ \ + } + +/// AUDIO Feature Unit Descriptor UAC1 (4.3.2.5) +#define audio10_desc_feature_unit_n_t(numChannels, controlSize) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 7+(ch+1)*n. */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT. */ \ + uint8_t bUnitID; /* Constant uniquely identifying the Unit within the audio function. */ \ + uint8_t bSourceID; /* ID of the Unit or Terminal to which this Feature Unit is connected. */ \ + uint8_t bControlSize; /* Size in bytes of an element of the bmaControls() array. */ \ + uint8_t bmaControls[(numChannels + 1) * controlSize]; /* Control bitmaps for master + logical channels. */ \ + uint8_t iFeature; /* Index of a string descriptor, describing this Feature Unit. */ \ + } + +/// AUDIO Processing Unit Descriptor UAC1 (4.3.2.6) +#define audio10_desc_processing_unit_n_t(numInputPins, numControlBytes) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 13+p+n. */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_PROCESSING_UNIT. */ \ + uint8_t bUnitID; /* Constant uniquely identifying the Unit within the audio function. */ \ + uint16_t wProcessType; /* Constant identifying the type of processing this Unit is performing. */ \ + uint8_t bNrInPins; /* Number of Input Pins of this Unit: p. */ \ + uint8_t baSourceID[numInputPins]; /* ID of the Unit or Terminal to which Input Pins of this Processing Unit are connected. */ \ + uint8_t bNrChannels; /* Number of logical output channels in the Processing Unit's output audio channel cluster. */ \ + uint16_t wChannelConfig; /* Describes the spatial location of the logical channels. */ \ + uint8_t iChannelNames; /* Index of a string descriptor, describing the name of the first logical channel. */ \ + uint8_t bControlSize; /* Size in bytes of the bmControls field. */ \ + uint8_t bmControls[numControlBytes]; /* Processing Unit Controls bitmap. */ \ + uint8_t iProcessing; /* Index of a string descriptor, describing the Processing Unit. */ \ + } + +/// AUDIO Extension Unit Descriptor UAC1 (4.3.2.7) +#define audio10_desc_extension_unit_n_t(numInputPins, numControlBytes) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 13+p+n. */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AC_INTERFACE_EXTENSION_UNIT. */ \ + uint8_t bUnitID; /* Constant uniquely identifying the Unit within the audio function. */ \ + uint16_t wExtensionCode; /* Vendor-specific code identifying the Extension Unit. */ \ + uint8_t bNrInPins; /* Number of Input Pins of this Unit: p. */ \ + uint8_t baSourceID[numInputPins]; /* ID of the Unit or Terminal to which Input Pins of this Extension Unit are connected. */ \ + uint8_t bNrChannels; /* Number of logical output channels in the Extension Unit's output audio channel cluster. */ \ + uint16_t wChannelConfig; /* Describes the spatial location of the logical channels. */ \ + uint8_t iChannelNames; /* Index of a string descriptor, describing the name of the first logical channel. */ \ + uint8_t bControlSize; /* Size in bytes of the bmControls field. */ \ + uint8_t bmControls[numControlBytes]; /* Extension Unit Controls bitmap. */ \ + uint8_t iExtension; /* Index of a string descriptor, describing the Extension Unit. */ \ + } + +/// AUDIO Class-Specific AS Interface Descriptor UAC1 (4.5.2) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes: 7. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO10_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink; ///< The Terminal ID of the Terminal to which the endpoint of this interface is connected. + uint8_t bDelay; ///< Expressed in number of frames. + uint16_t wFormatTag; ///< The Audio Data Format that has to be used to communicate with this interface. +} audio10_desc_cs_as_interface_t; + +/// AUDIO Type I Format Type Descriptor UAC1 (2.2.5) +#define audio10_desc_type_I_format_n_t(numSamFreq) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 8+(ns*3). */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AS_INTERFACE_FORMAT_TYPE. */ \ + uint8_t bFormatType; /* Constant identifying the Format Type the AudioStreaming interface is using. */ \ + uint8_t bNrChannels; /* Indicates the number of physical channels in the audio data stream. */ \ + uint8_t bSubFrameSize; /* The number of bytes occupied by one audio subframe. */ \ + uint8_t bBitResolution; /* The number of effectively used bits from the available bits in an audio subframe. */ \ + uint8_t bSamFreqType; /* Indicates how the sampling frequency can be programmed. */ \ + uint8_t tSamFreq[numSamFreq * 3]; /* Sampling frequency or lower/upper bounds in Hz for the sampling frequency range. */ \ + } + +/// AUDIO Type II Format Type Descriptor UAC1 (2.3.5) +#define audio10_desc_type_II_format_n_t(numSamFreq) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 9+(ns*3). */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AS_INTERFACE_FORMAT_TYPE. */ \ + uint8_t bFormatType; /* Constant identifying the Format Type the AudioStreaming interface is using. */ \ + uint16_t wMaxBitRate; /* Indicates the maximum number of bits per second this interface can handle. */ \ + uint16_t wSamplesPerFrame; /* Indicates the number of PCM audio samples contained in one encoded audio frame. */ \ + uint8_t bSamFreqType; /* Indicates how the sampling frequency can be programmed. */ \ + uint8_t tSamFreq[numSamFreq * 3]; /* Sampling frequency or lower/upper bounds in Hz for the sampling frequency range. */ \ + } + +/// AUDIO Type III Format Type Descriptor UAC1 (2.4.5) +#define audio10_desc_type_III_format_n_t(numSamFreq) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* Size of this descriptor in bytes: 8+(ns*3). */ \ + uint8_t bDescriptorType; /* Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. */ \ + uint8_t bDescriptorSubType; /* Descriptor SubType. Value: AUDIO10_CS_AS_INTERFACE_FORMAT_TYPE. */ \ + uint8_t bFormatType; /* Constant identifying the Format Type the AudioStreaming interface is using. */ \ + uint8_t bNrChannels; /* Indicates the number of physical channels in the audio data stream. */ \ + uint8_t bSubFrameSize; /* The number of bytes occupied by one audio subframe. */ \ + uint8_t bBitResolution; /* The number of effectively used bits from the available bits in an audio subframe. */ \ + uint8_t bSamFreqType; /* Indicates how the sampling frequency can be programmed. */ \ + uint8_t tSamFreq[numSamFreq * 3]; /* Sampling frequency or lower/upper bounds in Hz for the sampling frequency range. */ \ + } + +/// Standard AS Isochronous Audio Data Endpoint Descriptor UAC1 (4.6.1.1) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_ENDPOINT. + uint8_t bEndpointAddress;///< The address of the endpoint on the USB device described by this descriptor. + struct TU_ATTR_PACKED { + uint8_t xfer : 2; // Control, ISO, Bulk, Interrupt + uint8_t sync : 2; // None, Asynchronous, Adaptive, Synchronous + uint8_t usage : 2; // Data, Feedback, Implicit feedback + uint8_t : 2; + } bmAttributes; + uint16_t wMaxPacketSize; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. + uint8_t bInterval; ///< Interval for polling endpoint for data transfers. + uint8_t bRefresh; ///< The rate at which the endpoint is refreshed. + uint8_t bSynchAddress; ///< The address of the endpoint used to send synchronization information for the data endpoint. +} audio10_desc_as_iso_data_ep_t; + +/// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor UAC1 (4.6.1.2) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes: 7. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO10_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes; ///< Bit 0: Sampling Frequency, Bit 1: Pitch, Bit 7: MaxPacketsOnly. + uint8_t bLockDelayUnits; ///< Indicates the units used for the wLockDelay field. + uint16_t wLockDelay; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. +} audio10_desc_cs_as_iso_data_ep_t; + +/// AUDIO Interrupt Data Message Format UAC1 (3.7.1.2) +typedef struct TU_ATTR_PACKED { + uint8_t bStatusType;///< Indicates the type of status information being reported. + uint8_t bOriginator;///< Indicates the entity that originated this status information. +} audio10_interrupt_data_t; + +//--------------------------------------------------------------------+ +// USB AUDIO CLASS 2.0 (UAC2) DEFINITIONS +//--------------------------------------------------------------------+ + /// A.7 - Audio Function Category Codes -typedef enum -{ - AUDIO_FUNC_UNDEF = 0x00, - AUDIO_FUNC_DESKTOP_SPEAKER = 0x01, - AUDIO_FUNC_HOME_THEATER = 0x02, - AUDIO_FUNC_MICROPHONE = 0x03, - AUDIO_FUNC_HEADSET = 0x04, - AUDIO_FUNC_TELEPHONE = 0x05, - AUDIO_FUNC_CONVERTER = 0x06, - AUDIO_FUNC_SOUND_RECODER = 0x07, - AUDIO_FUNC_IO_BOX = 0x08, - AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09, - AUDIO_FUNC_PRO_AUDIO = 0x0A, - AUDIO_FUNC_AUDIO_VIDEO = 0x0B, - AUDIO_FUNC_CONTROL_PANEL = 0x0C, - AUDIO_FUNC_OTHER = 0xFF, -} audio_function_code_t; +typedef enum { + AUDIO20_FUNC_UNDEF = 0x00, + AUDIO20_FUNC_DESKTOP_SPEAKER = 0x01, + AUDIO20_FUNC_HOME_THEATER = 0x02, + AUDIO20_FUNC_MICROPHONE = 0x03, + AUDIO20_FUNC_HEADSET = 0x04, + AUDIO20_FUNC_TELEPHONE = 0x05, + AUDIO20_FUNC_CONVERTER = 0x06, + AUDIO20_FUNC_SOUND_RECODER = 0x07, + AUDIO20_FUNC_IO_BOX = 0x08, + AUDIO20_FUNC_MUSICAL_INSTRUMENT = 0x09, + AUDIO20_FUNC_PRO_AUDIO = 0x0A, + AUDIO20_FUNC_AUDIO_VIDEO = 0x0B, + AUDIO20_FUNC_CONTROL_PANEL = 0x0C, + AUDIO20_FUNC_OTHER = 0xFF, +} audio20_function_code_t; /// A.9 - Audio Class-Specific AC Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AC_INTERFACE_HEADER = 0x01, - AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, - AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, - AUDIO_CS_AC_INTERFACE_MIXER_UNIT = 0x04, - AUDIO_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, - AUDIO_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, - AUDIO_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, - AUDIO_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, - AUDIO_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, - AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, - AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, - AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, - AUDIO_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, -} audio_cs_ac_interface_subtype_t; +typedef enum { + AUDIO20_CS_AC_INTERFACE_AC_DESCRIPTOR_UNDEF = 0x00, + AUDIO20_CS_AC_INTERFACE_HEADER = 0x01, + AUDIO20_CS_AC_INTERFACE_INPUT_TERMINAL = 0x02, + AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL = 0x03, + AUDIO20_CS_AC_INTERFACE_MIXER_UNIT = 0x04, + AUDIO20_CS_AC_INTERFACE_SELECTOR_UNIT = 0x05, + AUDIO20_CS_AC_INTERFACE_FEATURE_UNIT = 0x06, + AUDIO20_CS_AC_INTERFACE_EFFECT_UNIT = 0x07, + AUDIO20_CS_AC_INTERFACE_PROCESSING_UNIT = 0x08, + AUDIO20_CS_AC_INTERFACE_EXTENSION_UNIT = 0x09, + AUDIO20_CS_AC_INTERFACE_CLOCK_SOURCE = 0x0A, + AUDIO20_CS_AC_INTERFACE_CLOCK_SELECTOR = 0x0B, + AUDIO20_CS_AC_INTERFACE_CLOCK_MULTIPLIER = 0x0C, + AUDIO20_CS_AC_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D, +} audio20_cs_ac_interface_subtype_t; /// A.10 - Audio Class-Specific AS Interface Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, - AUDIO_CS_AS_INTERFACE_AS_GENERAL = 0x01, - AUDIO_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, - AUDIO_CS_AS_INTERFACE_ENCODER = 0x03, - AUDIO_CS_AS_INTERFACE_DECODER = 0x04, -} audio_cs_as_interface_subtype_t; +typedef enum { + AUDIO20_CS_AS_INTERFACE_AS_DESCRIPTOR_UNDEF = 0x00, + AUDIO20_CS_AS_INTERFACE_AS_GENERAL = 0x01, + AUDIO20_CS_AS_INTERFACE_FORMAT_TYPE = 0x02, + AUDIO20_CS_AS_INTERFACE_ENCODER = 0x03, + AUDIO20_CS_AS_INTERFACE_DECODER = 0x04, +} audio20_cs_as_interface_subtype_t; /// A.11 - Effect Unit Effect Types -typedef enum -{ - AUDIO_EFFECT_TYPE_UNDEF = 0x00, - AUDIO_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, - AUDIO_EFFECT_TYPE_REVERBERATION = 0x02, - AUDIO_EFFECT_TYPE_MOD_DELAY = 0x03, - AUDIO_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, -} audio_effect_unit_effect_type_t; +typedef enum { + AUDIO20_EFFECT_TYPE_UNDEF = 0x00, + AUDIO20_EFFECT_TYPE_PARAM_EQ_SECTION = 0x01, + AUDIO20_EFFECT_TYPE_REVERBERATION = 0x02, + AUDIO20_EFFECT_TYPE_MOD_DELAY = 0x03, + AUDIO20_EFFECT_TYPE_DYN_RANGE_COMP = 0x04, +} audio20_effect_unit_effect_type_t; /// A.12 - Processing Unit Process Types -typedef enum -{ - AUDIO_PROCESS_TYPE_UNDEF = 0x00, - AUDIO_PROCESS_TYPE_UP_DOWN_MIX = 0x01, - AUDIO_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, - AUDIO_PROCESS_TYPE_STEREO_EXTENDER = 0x03, -} audio_processing_unit_process_type_t; +typedef enum { + AUDIO20_PROCESS_TYPE_UNDEF = 0x00, + AUDIO20_PROCESS_TYPE_UP_DOWN_MIX = 0x01, + AUDIO20_PROCESS_TYPE_DOLBY_PROLOGIC = 0x02, + AUDIO20_PROCESS_TYPE_STEREO_EXTENDER = 0x03, +} audio20_processing_unit_process_type_t; /// A.13 - Audio Class-Specific EP Descriptor Subtypes UAC2 -typedef enum -{ - AUDIO_CS_EP_SUBTYPE_UNDEF = 0x00, - AUDIO_CS_EP_SUBTYPE_GENERAL = 0x01, -} audio_cs_ep_subtype_t; +typedef enum { + AUDIO20_CS_EP_SUBTYPE_UNDEF = 0x00, + AUDIO20_CS_EP_SUBTYPE_GENERAL = 0x01, +} audio20_cs_ep_subtype_t; -/// A.14 - Audio Class-Specific Request Codes -typedef enum -{ - AUDIO_CS_REQ_UNDEF = 0x00, - AUDIO_CS_REQ_CUR = 0x01, - AUDIO_CS_REQ_RANGE = 0x02, - AUDIO_CS_REQ_MEM = 0x03, -} audio_cs_req_t; +/// A.14 - Audio Class-Specific Request Codes UAC2 +typedef enum { + AUDIO20_CS_REQ_UNDEF = 0x00, + AUDIO20_CS_REQ_CUR = 0x01, + AUDIO20_CS_REQ_RANGE = 0x02, + AUDIO20_CS_REQ_MEM = 0x03, +} audio20_cs_req_t; -/// A.17 - Control Selector Codes +/// A.17 - Control Selector Codes UAC2 /// A.17.1 - Clock Source Control Selectors -typedef enum -{ - AUDIO_CS_CTRL_UNDEF = 0x00, - AUDIO_CS_CTRL_SAM_FREQ = 0x01, - AUDIO_CS_CTRL_CLK_VALID = 0x02, -} audio_clock_src_control_selector_t; +typedef enum { + AUDIO20_CS_CTRL_UNDEF = 0x00, + AUDIO20_CS_CTRL_SAM_FREQ = 0x01, + AUDIO20_CS_CTRL_CLK_VALID = 0x02, +} audio20_clock_src_control_selector_t; /// A.17.2 - Clock Selector Control Selectors -typedef enum -{ - AUDIO_CX_CTRL_UNDEF = 0x00, - AUDIO_CX_CTRL_CONTROL = 0x01, -} audio_clock_sel_control_selector_t; +typedef enum { + AUDIO20_CX_CTRL_UNDEF = 0x00, + AUDIO20_CX_CTRL_CONTROL = 0x01, +} audio20_clock_sel_control_selector_t; /// A.17.3 - Clock Multiplier Control Selectors -typedef enum -{ - AUDIO_CM_CTRL_UNDEF = 0x00, - AUDIO_CM_CTRL_NUMERATOR_CONTROL = 0x01, - AUDIO_CM_CTRL_DENOMINATOR_CONTROL = 0x02, -} audio_clock_mul_control_selector_t; +typedef enum { + AUDIO20_CM_CTRL_UNDEF = 0x00, + AUDIO20_CM_CTRL_NUMERATOR_CONTROL = 0x01, + AUDIO20_CM_CTRL_DENOMINATOR_CONTROL = 0x02, +} audio20_clock_mul_control_selector_t; -/// A.17.4 - Terminal Control Selectors -typedef enum -{ - AUDIO_TE_CTRL_UNDEF = 0x00, - AUDIO_TE_CTRL_COPY_PROTECT = 0x01, - AUDIO_TE_CTRL_CONNECTOR = 0x02, - AUDIO_TE_CTRL_OVERLOAD = 0x03, - AUDIO_TE_CTRL_CLUSTER = 0x04, - AUDIO_TE_CTRL_UNDERFLOW = 0x05, - AUDIO_TE_CTRL_OVERFLOW = 0x06, - AUDIO_TE_CTRL_LATENCY = 0x07, -} audio_terminal_control_selector_t; +/// A.17.4 - Terminal Control Selectors UAC2 +typedef enum { + AUDIO20_TE_CTRL_UNDEF = 0x00, + AUDIO20_TE_CTRL_COPY_PROTECT = 0x01, + AUDIO20_TE_CTRL_CONNECTOR = 0x02, + AUDIO20_TE_CTRL_OVERLOAD = 0x03, + AUDIO20_TE_CTRL_CLUSTER = 0x04, + AUDIO20_TE_CTRL_UNDERFLOW = 0x05, + AUDIO20_TE_CTRL_OVERFLOW = 0x06, + AUDIO20_TE_CTRL_LATENCY = 0x07, +} audio20_terminal_control_selector_t; /// A.17.5 - Mixer Control Selectors -typedef enum -{ - AUDIO_MU_CTRL_UNDEF = 0x00, - AUDIO_MU_CTRL_MIXER = 0x01, - AUDIO_MU_CTRL_CLUSTER = 0x02, - AUDIO_MU_CTRL_UNDERFLOW = 0x03, - AUDIO_MU_CTRL_OVERFLOW = 0x04, - AUDIO_MU_CTRL_LATENCY = 0x05, -} audio_mixer_control_selector_t; +typedef enum { + AUDIO20_MU_CTRL_UNDEF = 0x00, + AUDIO20_MU_CTRL_MIXER = 0x01, + AUDIO20_MU_CTRL_CLUSTER = 0x02, + AUDIO20_MU_CTRL_UNDERFLOW = 0x03, + AUDIO20_MU_CTRL_OVERFLOW = 0x04, + AUDIO20_MU_CTRL_LATENCY = 0x05, +} audio20_mixer_control_selector_t; /// A.17.6 - Selector Control Selectors -typedef enum -{ - AUDIO_SU_CTRL_UNDEF = 0x00, - AUDIO_SU_CTRL_SELECTOR = 0x01, - AUDIO_SU_CTRL_LATENCY = 0x02, -} audio_sel_control_selector_t; +typedef enum { + AUDIO20_SU_CTRL_UNDEF = 0x00, + AUDIO20_SU_CTRL_SELECTOR = 0x01, + AUDIO20_SU_CTRL_LATENCY = 0x02, +} audio20_sel_control_selector_t; -/// A.17.7 - Feature Unit Control Selectors -typedef enum -{ - AUDIO_FU_CTRL_UNDEF = 0x00, - AUDIO_FU_CTRL_MUTE = 0x01, - AUDIO_FU_CTRL_VOLUME = 0x02, - AUDIO_FU_CTRL_BASS = 0x03, - AUDIO_FU_CTRL_MID = 0x04, - AUDIO_FU_CTRL_TREBLE = 0x05, - AUDIO_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, - AUDIO_FU_CTRL_AGC = 0x07, - AUDIO_FU_CTRL_DELAY = 0x08, - AUDIO_FU_CTRL_BASS_BOOST = 0x09, - AUDIO_FU_CTRL_LOUDNESS = 0x0A, - AUDIO_FU_CTRL_INPUT_GAIN = 0x0B, - AUDIO_FU_CTRL_GAIN_PAD = 0x0C, - AUDIO_FU_CTRL_INVERTER = 0x0D, - AUDIO_FU_CTRL_UNDERFLOW = 0x0E, - AUDIO_FU_CTRL_OVERVLOW = 0x0F, - AUDIO_FU_CTRL_LATENCY = 0x10, -} audio_feature_unit_control_selector_t; +/// A.17.7 - Feature Unit Control Selectors UAC2 +typedef enum { + AUDIO20_FU_CTRL_UNDEF = 0x00, + AUDIO20_FU_CTRL_MUTE = 0x01, + AUDIO20_FU_CTRL_VOLUME = 0x02, + AUDIO20_FU_CTRL_BASS = 0x03, + AUDIO20_FU_CTRL_MID = 0x04, + AUDIO20_FU_CTRL_TREBLE = 0x05, + AUDIO20_FU_CTRL_GRAPHIC_EQUALIZER = 0x06, + AUDIO20_FU_CTRL_AGC = 0x07, + AUDIO20_FU_CTRL_DELAY = 0x08, + AUDIO20_FU_CTRL_BASS_BOOST = 0x09, + AUDIO20_FU_CTRL_LOUDNESS = 0x0A, + AUDIO20_FU_CTRL_INPUT_GAIN = 0x0B, + AUDIO20_FU_CTRL_GAIN_PAD = 0x0C, + AUDIO20_FU_CTRL_INVERTER = 0x0D, + AUDIO20_FU_CTRL_UNDERFLOW = 0x0E, + AUDIO20_FU_CTRL_OVERVLOW = 0x0F, + AUDIO20_FU_CTRL_LATENCY = 0x10, +} audio20_feature_unit_control_selector_t; /// A.17.8 Effect Unit Control Selectors /// A.17.8.1 Parametric Equalizer Section Effect Unit Control Selectors -typedef enum -{ - AUDIO_PE_CTRL_UNDEF = 0x00, - AUDIO_PE_CTRL_ENABLE = 0x01, - AUDIO_PE_CTRL_CENTERFREQ = 0x02, - AUDIO_PE_CTRL_QFACTOR = 0x03, - AUDIO_PE_CTRL_GAIN = 0x04, - AUDIO_PE_CTRL_UNDERFLOW = 0x05, - AUDIO_PE_CTRL_OVERFLOW = 0x06, - AUDIO_PE_CTRL_LATENCY = 0x07, -} audio_parametric_equalizer_control_selector_t; +typedef enum { + AUDIO20_PE_CTRL_UNDEF = 0x00, + AUDIO20_PE_CTRL_ENABLE = 0x01, + AUDIO20_PE_CTRL_CENTERFREQ = 0x02, + AUDIO20_PE_CTRL_QFACTOR = 0x03, + AUDIO20_PE_CTRL_GAIN = 0x04, + AUDIO20_PE_CTRL_UNDERFLOW = 0x05, + AUDIO20_PE_CTRL_OVERFLOW = 0x06, + AUDIO20_PE_CTRL_LATENCY = 0x07, +} audio20_parametric_equalizer_control_selector_t; /// A.17.8.2 Reverberation Effect Unit Control Selectors -typedef enum -{ - AUDIO_RV_CTRL_UNDEF = 0x00, - AUDIO_RV_CTRL_ENABLE = 0x01, - AUDIO_RV_CTRL_TYPE = 0x02, - AUDIO_RV_CTRL_LEVEL = 0x03, - AUDIO_RV_CTRL_TIME = 0x04, - AUDIO_RV_CTRL_FEEDBACK = 0x05, - AUDIO_RV_CTRL_PREDELAY = 0x06, - AUDIO_RV_CTRL_DENSITY = 0x07, - AUDIO_RV_CTRL_HIFREQ_ROLLOFF = 0x08, - AUDIO_RV_CTRL_UNDERFLOW = 0x09, - AUDIO_RV_CTRL_OVERFLOW = 0x0A, - AUDIO_RV_CTRL_LATENCY = 0x0B, -} audio_reverberation_effect_control_selector_t; +typedef enum { + AUDIO20_RV_CTRL_UNDEF = 0x00, + AUDIO20_RV_CTRL_ENABLE = 0x01, + AUDIO20_RV_CTRL_TYPE = 0x02, + AUDIO20_RV_CTRL_LEVEL = 0x03, + AUDIO20_RV_CTRL_TIME = 0x04, + AUDIO20_RV_CTRL_FEEDBACK = 0x05, + AUDIO20_RV_CTRL_PREDELAY = 0x06, + AUDIO20_RV_CTRL_DENSITY = 0x07, + AUDIO20_RV_CTRL_HIFREQ_ROLLOFF = 0x08, + AUDIO20_RV_CTRL_UNDERFLOW = 0x09, + AUDIO20_RV_CTRL_OVERFLOW = 0x0A, + AUDIO20_RV_CTRL_LATENCY = 0x0B, +} audio20_reverberation_effect_control_selector_t; /// A.17.8.3 Modulation Delay Effect Unit Control Selectors -typedef enum -{ - AUDIO_MD_CTRL_UNDEF = 0x00, - AUDIO_MD_CTRL_ENABLE = 0x01, - AUDIO_MD_CTRL_BALANCE = 0x02, - AUDIO_MD_CTRL_RATE = 0x03, - AUDIO_MD_CTRL_DEPTH = 0x04, - AUDIO_MD_CTRL_TIME = 0x05, - AUDIO_MD_CTRL_FEEDBACK = 0x06, - AUDIO_MD_CTRL_UNDERFLOW = 0x07, - AUDIO_MD_CTRL_OVERFLOW = 0x08, - AUDIO_MD_CTRL_LATENCY = 0x09, -} audio_modulation_delay_control_selector_t; +typedef enum { + AUDIO20_MD_CTRL_UNDEF = 0x00, + AUDIO20_MD_CTRL_ENABLE = 0x01, + AUDIO20_MD_CTRL_BALANCE = 0x02, + AUDIO20_MD_CTRL_RATE = 0x03, + AUDIO20_MD_CTRL_DEPTH = 0x04, + AUDIO20_MD_CTRL_TIME = 0x05, + AUDIO20_MD_CTRL_FEEDBACK = 0x06, + AUDIO20_MD_CTRL_UNDERFLOW = 0x07, + AUDIO20_MD_CTRL_OVERFLOW = 0x08, + AUDIO20_MD_CTRL_LATENCY = 0x09, +} audio20_modulation_delay_control_selector_t; /// A.17.8.4 Dynamic Range Compressor Effect Unit Control Selectors -typedef enum -{ - AUDIO_DR_CTRL_UNDEF = 0x00, - AUDIO_DR_CTRL_ENABLE = 0x01, - AUDIO_DR_CTRL_COMPRESSION_RATE = 0x02, - AUDIO_DR_CTRL_MAXAMPL = 0x03, - AUDIO_DR_CTRL_THRESHOLD = 0x04, - AUDIO_DR_CTRL_ATTACK_TIME = 0x05, - AUDIO_DR_CTRL_RELEASE_TIME = 0x06, - AUDIO_DR_CTRL_UNDERFLOW = 0x07, - AUDIO_DR_CTRL_OVERFLOW = 0x08, - AUDIO_DR_CTRL_LATENCY = 0x09, -} audio_dynamic_range_compression_control_selector_t; +typedef enum { + AUDIO20_DR_CTRL_UNDEF = 0x00, + AUDIO20_DR_CTRL_ENABLE = 0x01, + AUDIO20_DR_CTRL_COMPRESSION_RATE = 0x02, + AUDIO20_DR_CTRL_MAXAMPL = 0x03, + AUDIO20_DR_CTRL_THRESHOLD = 0x04, + AUDIO20_DR_CTRL_ATTACK_TIME = 0x05, + AUDIO20_DR_CTRL_RELEASE_TIME = 0x06, + AUDIO20_DR_CTRL_UNDERFLOW = 0x07, + AUDIO20_DR_CTRL_OVERFLOW = 0x08, + AUDIO20_DR_CTRL_LATENCY = 0x09, +} audio20_dynamic_range_compression_control_selector_t; /// A.17.9 Processing Unit Control Selectors /// A.17.9.1 Up/Down-mix Processing Unit Control Selectors -typedef enum -{ - AUDIO_UD_CTRL_UNDEF = 0x00, - AUDIO_UD_CTRL_ENABLE = 0x01, - AUDIO_UD_CTRL_MODE_SELECT = 0x02, - AUDIO_UD_CTRL_CLUSTER = 0x03, - AUDIO_UD_CTRL_UNDERFLOW = 0x04, - AUDIO_UD_CTRL_OVERFLOW = 0x05, - AUDIO_UD_CTRL_LATENCY = 0x06, -} audio_up_down_mix_control_selector_t; +typedef enum { + AUDIO20_UD_CTRL_UNDEF = 0x00, + AUDIO20_UD_CTRL_ENABLE = 0x01, + AUDIO20_UD_CTRL_MODE_SELECT = 0x02, + AUDIO20_UD_CTRL_CLUSTER = 0x03, + AUDIO20_UD_CTRL_UNDERFLOW = 0x04, + AUDIO20_UD_CTRL_OVERFLOW = 0x05, + AUDIO20_UD_CTRL_LATENCY = 0x06, +} audio20_up_down_mix_control_selector_t; /// A.17.9.2 Dolby Prologic ™ Processing Unit Control Selectors -typedef enum -{ - AUDIO_DP_CTRL_UNDEF = 0x00, - AUDIO_DP_CTRL_ENABLE = 0x01, - AUDIO_DP_CTRL_MODE_SELECT = 0x02, - AUDIO_DP_CTRL_CLUSTER = 0x03, - AUDIO_DP_CTRL_UNDERFLOW = 0x04, - AUDIO_DP_CTRL_OVERFLOW = 0x05, - AUDIO_DP_CTRL_LATENCY = 0x06, -} audio_dolby_prologic_control_selector_t; +typedef enum { + AUDIO20_DP_CTRL_UNDEF = 0x00, + AUDIO20_DP_CTRL_ENABLE = 0x01, + AUDIO20_DP_CTRL_MODE_SELECT = 0x02, + AUDIO20_DP_CTRL_CLUSTER = 0x03, + AUDIO20_DP_CTRL_UNDERFLOW = 0x04, + AUDIO20_DP_CTRL_OVERFLOW = 0x05, + AUDIO20_DP_CTRL_LATENCY = 0x06, +} audio20_dolby_prologic_control_selector_t; /// A.17.9.3 Stereo Extender Processing Unit Control Selectors -typedef enum -{ - AUDIO_ST_EXT_CTRL_UNDEF = 0x00, - AUDIO_ST_EXT_CTRL_ENABLE = 0x01, - AUDIO_ST_EXT_CTRL_WIDTH = 0x02, - AUDIO_ST_EXT_CTRL_UNDERFLOW = 0x03, - AUDIO_ST_EXT_CTRL_OVERFLOW = 0x04, - AUDIO_ST_EXT_CTRL_LATENCY = 0x05, -} audio_stereo_extender_control_selector_t; +typedef enum { + AUDIO20_ST_EXT_CTRL_UNDEF = 0x00, + AUDIO20_ST_EXT_CTRL_ENABLE = 0x01, + AUDIO20_ST_EXT_CTRL_WIDTH = 0x02, + AUDIO20_ST_EXT_CTRL_UNDERFLOW = 0x03, + AUDIO20_ST_EXT_CTRL_OVERFLOW = 0x04, + AUDIO20_ST_EXT_CTRL_LATENCY = 0x05, +} audio20_stereo_extender_control_selector_t; /// A.17.10 Extension Unit Control Selectors -typedef enum -{ - AUDIO_XU_CTRL_UNDEF = 0x00, - AUDIO_XU_CTRL_ENABLE = 0x01, - AUDIO_XU_CTRL_CLUSTER = 0x02, - AUDIO_XU_CTRL_UNDERFLOW = 0x03, - AUDIO_XU_CTRL_OVERFLOW = 0x04, - AUDIO_XU_CTRL_LATENCY = 0x05, -} audio_extension_unit_control_selector_t; +typedef enum { + AUDIO20_XU_CTRL_UNDEF = 0x00, + AUDIO20_XU_CTRL_ENABLE = 0x01, + AUDIO20_XU_CTRL_CLUSTER = 0x02, + AUDIO20_XU_CTRL_UNDERFLOW = 0x03, + AUDIO20_XU_CTRL_OVERFLOW = 0x04, + AUDIO20_XU_CTRL_LATENCY = 0x05, +} audio20_extension_unit_control_selector_t; /// A.17.11 AudioStreaming Interface Control Selectors -typedef enum -{ - AUDIO_AS_CTRL_UNDEF = 0x00, - AUDIO_AS_CTRL_ACT_ALT_SETTING = 0x01, - AUDIO_AS_CTRL_VAL_ALT_SETTINGS = 0x02, - AUDIO_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, -} audio_audiostreaming_interface_control_selector_t; +typedef enum { + AUDIO20_AS_CTRL_UNDEF = 0x00, + AUDIO20_AS_CTRL_ACT_ALT_SETTING = 0x01, + AUDIO20_AS_CTRL_VAL_ALT_SETTINGS = 0x02, + AUDIO20_AS_CTRL_AUDIO_DATA_FORMAT = 0x03, +} audio20_audiostreaming_interface_control_selector_t; /// A.17.12 Encoder Control Selectors -typedef enum -{ - AUDIO_EN_CTRL_UNDEF = 0x00, - AUDIO_EN_CTRL_BIT_RATE = 0x01, - AUDIO_EN_CTRL_QUALITY = 0x02, - AUDIO_EN_CTRL_VBR = 0x03, - AUDIO_EN_CTRL_TYPE = 0x04, - AUDIO_EN_CTRL_UNDERFLOW = 0x05, - AUDIO_EN_CTRL_OVERFLOW = 0x06, - AUDIO_EN_CTRL_ENCODER_ERROR = 0x07, - AUDIO_EN_CTRL_PARAM1 = 0x08, - AUDIO_EN_CTRL_PARAM2 = 0x09, - AUDIO_EN_CTRL_PARAM3 = 0x0A, - AUDIO_EN_CTRL_PARAM4 = 0x0B, - AUDIO_EN_CTRL_PARAM5 = 0x0C, - AUDIO_EN_CTRL_PARAM6 = 0x0D, - AUDIO_EN_CTRL_PARAM7 = 0x0E, - AUDIO_EN_CTRL_PARAM8 = 0x0F, -} audio_encoder_control_selector_t; +typedef enum { + AUDIO20_EN_CTRL_UNDEF = 0x00, + AUDIO20_EN_CTRL_BIT_RATE = 0x01, + AUDIO20_EN_CTRL_QUALITY = 0x02, + AUDIO20_EN_CTRL_VBR = 0x03, + AUDIO20_EN_CTRL_TYPE = 0x04, + AUDIO20_EN_CTRL_UNDERFLOW = 0x05, + AUDIO20_EN_CTRL_OVERFLOW = 0x06, + AUDIO20_EN_CTRL_ENCODER_ERROR = 0x07, + AUDIO20_EN_CTRL_PARAM1 = 0x08, + AUDIO20_EN_CTRL_PARAM2 = 0x09, + AUDIO20_EN_CTRL_PARAM3 = 0x0A, + AUDIO20_EN_CTRL_PARAM4 = 0x0B, + AUDIO20_EN_CTRL_PARAM5 = 0x0C, + AUDIO20_EN_CTRL_PARAM6 = 0x0D, + AUDIO20_EN_CTRL_PARAM7 = 0x0E, + AUDIO20_EN_CTRL_PARAM8 = 0x0F, +} audio20_encoder_control_selector_t; /// A.17.13 Decoder Control Selectors /// A.17.13.1 MPEG Decoder Control Selectors -typedef enum -{ - AUDIO_MPD_CTRL_UNDEF = 0x00, - AUDIO_MPD_CTRL_DUAL_CHANNEL = 0x01, - AUDIO_MPD_CTRL_SECOND_STEREO = 0x02, - AUDIO_MPD_CTRL_MULTILINGUAL = 0x03, - AUDIO_MPD_CTRL_DYN_RANGE = 0x04, - AUDIO_MPD_CTRL_SCALING = 0x05, - AUDIO_MPD_CTRL_HILO_SCALING = 0x06, - AUDIO_MPD_CTRL_UNDERFLOW = 0x07, - AUDIO_MPD_CTRL_OVERFLOW = 0x08, - AUDIO_MPD_CTRL_DECODER_ERROR = 0x09, -} audio_MPEG_decoder_control_selector_t; +typedef enum { + AUDIO20_MPD_CTRL_UNDEF = 0x00, + AUDIO20_MPD_CTRL_DUAL_CHANNEL = 0x01, + AUDIO20_MPD_CTRL_SECOND_STEREO = 0x02, + AUDIO20_MPD_CTRL_MULTILINGUAL = 0x03, + AUDIO20_MPD_CTRL_DYN_RANGE = 0x04, + AUDIO20_MPD_CTRL_SCALING = 0x05, + AUDIO20_MPD_CTRL_HILO_SCALING = 0x06, + AUDIO20_MPD_CTRL_UNDERFLOW = 0x07, + AUDIO20_MPD_CTRL_OVERFLOW = 0x08, + AUDIO20_MPD_CTRL_DECODER_ERROR = 0x09, +} audio20_MPEG_decoder_control_selector_t; /// A.17.13.2 AC-3 Decoder Control Selectors -typedef enum -{ - AUDIO_AD_CTRL_UNDEF = 0x00, - AUDIO_AD_CTRL_MODE = 0x01, - AUDIO_AD_CTRL_DYN_RANGE = 0x02, - AUDIO_AD_CTRL_SCALING = 0x03, - AUDIO_AD_CTRL_HILO_SCALING = 0x04, - AUDIO_AD_CTRL_UNDERFLOW = 0x05, - AUDIO_AD_CTRL_OVERFLOW = 0x06, - AUDIO_AD_CTRL_DECODER_ERROR = 0x07, -} audio_AC3_decoder_control_selector_t; +typedef enum { + AUDIO20_AD_CTRL_UNDEF = 0x00, + AUDIO20_AD_CTRL_MODE = 0x01, + AUDIO20_AD_CTRL_DYN_RANGE = 0x02, + AUDIO20_AD_CTRL_SCALING = 0x03, + AUDIO20_AD_CTRL_HILO_SCALING = 0x04, + AUDIO20_AD_CTRL_UNDERFLOW = 0x05, + AUDIO20_AD_CTRL_OVERFLOW = 0x06, + AUDIO20_AD_CTRL_DECODER_ERROR = 0x07, +} audio20_AC3_decoder_control_selector_t; /// A.17.13.3 WMA Decoder Control Selectors -typedef enum -{ - AUDIO_WD_CTRL_UNDEF = 0x00, - AUDIO_WD_CTRL_UNDERFLOW = 0x01, - AUDIO_WD_CTRL_OVERFLOW = 0x02, - AUDIO_WD_CTRL_DECODER_ERROR = 0x03, -} audio_WMA_decoder_control_selector_t; +typedef enum { + AUDIO20_WD_CTRL_UNDEF = 0x00, + AUDIO20_WD_CTRL_UNDERFLOW = 0x01, + AUDIO20_WD_CTRL_OVERFLOW = 0x02, + AUDIO20_WD_CTRL_DECODER_ERROR = 0x03, +} audio20_WMA_decoder_control_selector_t; /// A.17.13.4 DTS Decoder Control Selectors -typedef enum -{ - AUDIO_DD_CTRL_UNDEF = 0x00, - AUDIO_DD_CTRL_UNDERFLOW = 0x01, - AUDIO_DD_CTRL_OVERFLOW = 0x02, - AUDIO_DD_CTRL_DECODER_ERROR = 0x03, -} audio_DTS_decoder_control_selector_t; +typedef enum { + AUDIO20_DD_CTRL_UNDEF = 0x00, + AUDIO20_DD_CTRL_UNDERFLOW = 0x01, + AUDIO20_DD_CTRL_OVERFLOW = 0x02, + AUDIO20_DD_CTRL_DECODER_ERROR = 0x03, +} audio20_DTS_decoder_control_selector_t; /// A.17.14 Endpoint Control Selectors -typedef enum -{ - AUDIO_EP_CTRL_UNDEF = 0x00, - AUDIO_EP_CTRL_PITCH = 0x01, - AUDIO_EP_CTRL_DATA_OVERRUN = 0x02, - AUDIO_EP_CTRL_DATA_UNDERRUN = 0x03, -} audio_EP_control_selector_t; - -/// Terminal Types - -/// 2.1 - Audio Class-Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_USB_UNDEFINED = 0x0100, - AUDIO_TERM_TYPE_USB_STREAMING = 0x0101, - AUDIO_TERM_TYPE_USB_VENDOR_SPEC = 0x01FF, -} audio_terminal_type_t; - -/// 2.2 - Audio Class-Input Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_IN_UNDEFINED = 0x0200, - AUDIO_TERM_TYPE_IN_GENERIC_MIC = 0x0201, - AUDIO_TERM_TYPE_IN_DESKTOP_MIC = 0x0202, - AUDIO_TERM_TYPE_IN_PERSONAL_MIC = 0x0203, - AUDIO_TERM_TYPE_IN_OMNI_MIC = 0x0204, - AUDIO_TERM_TYPE_IN_ARRAY_MIC = 0x0205, - AUDIO_TERM_TYPE_IN_PROC_ARRAY_MIC = 0x0206, -} audio_terminal_input_type_t; - -/// 2.3 - Audio Class-Output Terminal Types UAC2 -typedef enum -{ - AUDIO_TERM_TYPE_OUT_UNDEFINED = 0x0300, - AUDIO_TERM_TYPE_OUT_GENERIC_SPEAKER = 0x0301, - AUDIO_TERM_TYPE_OUT_HEADPHONES = 0x0302, - AUDIO_TERM_TYPE_OUT_HEAD_MNT_DISP_AUIDO = 0x0303, - AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER = 0x0304, - AUDIO_TERM_TYPE_OUT_ROOM_SPEAKER = 0x0305, - AUDIO_TERM_TYPE_OUT_COMMUNICATION_SPEAKER = 0x0306, - AUDIO_TERM_TYPE_OUT_LOW_FRQ_EFFECTS_SPEAKER = 0x0307, -} audio_terminal_output_type_t; - -/// Rest is yet to be implemented +typedef enum { + AUDIO20_EP_CTRL_UNDEF = 0x00, + AUDIO20_EP_CTRL_PITCH = 0x01, + AUDIO20_EP_CTRL_DATA_OVERRUN = 0x02, + AUDIO20_EP_CTRL_DATA_UNDERRUN = 0x03, +} audio20_EP_control_selector_t; /// Additional Audio Device Class Codes - Source: Audio Data Formats /// A.1 - Audio Class-Format Type Codes UAC2 -typedef enum -{ - AUDIO_FORMAT_TYPE_UNDEFINED = 0x00, - AUDIO_FORMAT_TYPE_I = 0x01, - AUDIO_FORMAT_TYPE_II = 0x02, - AUDIO_FORMAT_TYPE_III = 0x03, - AUDIO_FORMAT_TYPE_IV = 0x04, - AUDIO_EXT_FORMAT_TYPE_I = 0x81, - AUDIO_EXT_FORMAT_TYPE_II = 0x82, - AUDIO_EXT_FORMAT_TYPE_III = 0x83, -} audio_format_type_t; +typedef enum { + AUDIO20_FORMAT_TYPE_UNDEFINED = 0x00, + AUDIO20_FORMAT_TYPE_I = 0x01, + AUDIO20_FORMAT_TYPE_II = 0x02, + AUDIO20_FORMAT_TYPE_III = 0x03, + AUDIO20_FORMAT_TYPE_IV = 0x04, + AUDIO20_EXT_FORMAT_TYPE_I = 0x81, + AUDIO20_EXT_FORMAT_TYPE_II = 0x82, + AUDIO20_EXT_FORMAT_TYPE_III = 0x83, +} audio20_format_type_t; // A.2.1 - Audio Class-Audio Data Format Type I UAC2 -typedef enum -{ - AUDIO_DATA_FORMAT_TYPE_I_PCM = (uint32_t) (1 << 0), - AUDIO_DATA_FORMAT_TYPE_I_PCM8 = (uint32_t) (1 << 1), - AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), - AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), - AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000u, -} audio_data_format_type_I_t; +typedef enum { + AUDIO20_DATA_FORMAT_TYPE_I_PCM = 1 << 0, + AUDIO20_DATA_FORMAT_TYPE_I_PCM8 = 1 << 1, + AUDIO20_DATA_FORMAT_TYPE_I_IEEE_FLOAT = 1 << 2, + AUDIO20_DATA_FORMAT_TYPE_I_ALAW = 1 << 3, + AUDIO20_DATA_FORMAT_TYPE_I_MULAW = 1 << 4, + AUDIO20_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000u, +} audio20_data_format_type_I_t; + +/// Audio Class-Audio Channel Configuration UAC2 (Table A-11) +typedef enum { + AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, + AUDIO20_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, + AUDIO20_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, + AUDIO20_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, + AUDIO20_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, + AUDIO20_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, + AUDIO20_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, + AUDIO20_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, + AUDIO20_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, + AUDIO20_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, + AUDIO20_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, + AUDIO20_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, + AUDIO20_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, + AUDIO20_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, + AUDIO20_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, + AUDIO20_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, + AUDIO20_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, + AUDIO20_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, + AUDIO20_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, + AUDIO20_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, + AUDIO20_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, + AUDIO20_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, + AUDIO20_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, + AUDIO20_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, + AUDIO20_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, + AUDIO20_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, + AUDIO20_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, + AUDIO20_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, + AUDIO20_CHANNEL_CONFIG_RAW_DATA = 0x80000000u, +} audio20_channel_config_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification /// Audio Class-Control Values UAC2 -typedef enum -{ - AUDIO_CTRL_NONE = 0x00, ///< No Host access - AUDIO_CTRL_R = 0x01, ///< Host read access only - AUDIO_CTRL_RW = 0x03, ///< Host read write access -} audio_control_t; +typedef enum { + AUDIO20_CTRL_NONE = 0x00,///< No Host access + AUDIO20_CTRL_R = 0x01, ///< Host read access only + AUDIO20_CTRL_RW = 0x03, ///< Host read write access +} audio20_control_t; /// Audio Class-Specific AC Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, -} audio_cs_ac_interface_control_pos_t; +typedef enum { + AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS = 0, +} audio20_cs_ac_interface_control_pos_t; /// Audio Class-Specific AS Interface Descriptor Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, - AUDIO_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, -} audio_cs_as_interface_control_pos_t; +typedef enum { + AUDIO20_CS_AS_INTERFACE_CTRL_ACTIVE_ALT_SET_POS = 0, + AUDIO20_CS_AS_INTERFACE_CTRL_VALID_ALT_SET_POS = 2, +} audio20_cs_as_interface_control_pos_t; /// Audio Class-Specific AS Isochronous Data EP Attributes UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, - AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, -} audio_cs_as_iso_data_ep_attribute_t; +typedef enum { + AUDIO20_CS_AS_ISO_DATA_EP_ATT_MAX_PACKETS_ONLY = 0x80, + AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK = 0x00, +} audio20_cs_as_iso_data_ep_attribute_t; /// Audio Class-Specific AS Isochronous Data EP Controls UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, - AUDIO_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, -} audio_cs_as_iso_data_ep_control_pos_t; +typedef enum { + AUDIO20_CS_AS_ISO_DATA_EP_CTRL_PITCH_POS = 0, + AUDIO20_CS_AS_ISO_DATA_EP_CTRL_DATA_OVERRUN_POS = 2, + AUDIO20_CS_AS_ISO_DATA_EP_CTRL_DATA_UNDERRUN_POS = 4, +} audio20_cs_as_iso_data_ep_control_pos_t; /// Audio Class-Specific AS Isochronous Data EP Lock Delay Units UAC2 -typedef enum -{ - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, - AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, -} audio_cs_as_iso_data_ep_lock_delay_unit_t; +typedef enum { + AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED = 0x00, + AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC = 0x01, + AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_PCM_SAMPLES = 0x02, +} audio20_cs_as_iso_data_ep_lock_delay_unit_t; /// Audio Class-Clock Source Attributes UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, - AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, - AUDIO_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, - AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, - AUDIO_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, -} audio_clock_source_attribute_t; +typedef enum { + AUDIO20_CLOCK_SOURCE_ATT_EXT_CLK = 0x00, + AUDIO20_CLOCK_SOURCE_ATT_INT_FIX_CLK = 0x01, + AUDIO20_CLOCK_SOURCE_ATT_INT_VAR_CLK = 0x02, + AUDIO20_CLOCK_SOURCE_ATT_INT_PRO_CLK = 0x03, + AUDIO20_CLOCK_SOURCE_ATT_CLK_SYC_SOF = 0x04, +} audio20_clock_source_attribute_t; /// Audio Class-Clock Source Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, - AUDIO_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, -} audio_clock_source_control_pos_t; +typedef enum { + AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS = 0, + AUDIO20_CLOCK_SOURCE_CTRL_CLK_VAL_POS = 2, +} audio20_clock_source_control_pos_t; /// Audio Class-Clock Selector Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_SELECTOR_CTRL_POS = 0, -} audio_clock_selector_control_pos_t; +typedef enum { + AUDIO20_CLOCK_SELECTOR_CTRL_POS = 0, +} audio20_clock_selector_control_pos_t; /// Audio Class-Clock Multiplier Controls UAC2 -typedef enum -{ - AUDIO_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, - AUDIO_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, -} audio_clock_multiplier_control_pos_t; +typedef enum { + AUDIO20_CLOCK_MULTIPLIER_CTRL_NUMERATOR_POS = 0, + AUDIO20_CLOCK_MULTIPLIER_CTRL_DENOMINATOR_POS = 2, +} audio20_clock_multiplier_control_pos_t; /// Audio Class-Input Terminal Controls UAC2 -typedef enum -{ - AUDIO_IN_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_IN_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_IN_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_IN_TERM_CTRL_CLUSTER_POS = 6, - AUDIO_IN_TERM_CTRL_UNDERFLOW_POS = 8, - AUDIO_IN_TERM_CTRL_OVERFLOW_POS = 10, -} audio_terminal_input_control_pos_t; +typedef enum { + AUDIO20_IN_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO20_IN_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO20_IN_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO20_IN_TERM_CTRL_CLUSTER_POS = 6, + AUDIO20_IN_TERM_CTRL_UNDERFLOW_POS = 8, + AUDIO20_IN_TERM_CTRL_OVERFLOW_POS = 10, +} audio20_terminal_input_control_pos_t; /// Audio Class-Output Terminal Controls UAC2 -typedef enum -{ - AUDIO_OUT_TERM_CTRL_CPY_PROT_POS = 0, - AUDIO_OUT_TERM_CTRL_CONNECTOR_POS = 2, - AUDIO_OUT_TERM_CTRL_OVERLOAD_POS = 4, - AUDIO_OUT_TERM_CTRL_UNDERFLOW_POS = 6, - AUDIO_OUT_TERM_CTRL_OVERFLOW_POS = 8, -} audio_terminal_output_control_pos_t; +typedef enum { + AUDIO20_OUT_TERM_CTRL_CPY_PROT_POS = 0, + AUDIO20_OUT_TERM_CTRL_CONNECTOR_POS = 2, + AUDIO20_OUT_TERM_CTRL_OVERLOAD_POS = 4, + AUDIO20_OUT_TERM_CTRL_UNDERFLOW_POS = 6, + AUDIO20_OUT_TERM_CTRL_OVERFLOW_POS = 8, +} audio20_terminal_output_control_pos_t; /// Audio Class-Feature Unit Controls UAC2 -typedef enum -{ - AUDIO_FEATURE_UNIT_CTRL_MUTE_POS = 0, - AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS = 2, - AUDIO_FEATURE_UNIT_CTRL_BASS_POS = 4, - AUDIO_FEATURE_UNIT_CTRL_MID_POS = 6, - AUDIO_FEATURE_UNIT_CTRL_TREBLE_POS = 8, - AUDIO_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, - AUDIO_FEATURE_UNIT_CTRL_AGC_POS = 12, - AUDIO_FEATURE_UNIT_CTRL_DELAY_POS = 14, - AUDIO_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, - AUDIO_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, - AUDIO_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, - AUDIO_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, - AUDIO_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, - AUDIO_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, -} audio_feature_unit_control_pos_t; +typedef enum { + AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS = 0, + AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS = 2, + AUDIO20_FEATURE_UNIT_CTRL_BASS_POS = 4, + AUDIO20_FEATURE_UNIT_CTRL_MID_POS = 6, + AUDIO20_FEATURE_UNIT_CTRL_TREBLE_POS = 8, + AUDIO20_FEATURE_UNIT_CTRL_GRAPHIC_EQU_POS = 10, + AUDIO20_FEATURE_UNIT_CTRL_AGC_POS = 12, + AUDIO20_FEATURE_UNIT_CTRL_DELAY_POS = 14, + AUDIO20_FEATURE_UNIT_CTRL_BASS_BOOST_POS = 16, + AUDIO20_FEATURE_UNIT_CTRL_LOUDNESS_POS = 18, + AUDIO20_FEATURE_UNIT_CTRL_INPUT_GAIN_POS = 20, + AUDIO20_FEATURE_UNIT_CTRL_INPUT_GAIN_PAD_POS = 22, + AUDIO20_FEATURE_UNIT_CTRL_PHASE_INV_POS = 24, + AUDIO20_FEATURE_UNIT_CTRL_UNDERFLOW_POS = 26, + AUDIO20_FEATURE_UNIT_CTRL_OVERFLOW_POS = 28, +} audio20_feature_unit_control_pos_t; -/// Audio Class-Audio Channel Configuration UAC2 -typedef enum -{ - AUDIO_CHANNEL_CONFIG_NON_PREDEFINED = 0x00000000, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT = 0x00000001, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT = 0x00000002, - AUDIO_CHANNEL_CONFIG_FRONT_CENTER = 0x00000004, - AUDIO_CHANNEL_CONFIG_LOW_FRQ_EFFECTS = 0x00000008, - AUDIO_CHANNEL_CONFIG_BACK_LEFT = 0x00000010, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT = 0x00000020, - AUDIO_CHANNEL_CONFIG_FRONT_LEFT_OF_CENTER = 0x00000040, - AUDIO_CHANNEL_CONFIG_FRONT_RIGHT_OF_CENTER = 0x00000080, - AUDIO_CHANNEL_CONFIG_BACK_CENTER = 0x00000100, - AUDIO_CHANNEL_CONFIG_SIDE_LEFT = 0x00000200, - AUDIO_CHANNEL_CONFIG_SIDE_RIGHT = 0x00000400, - AUDIO_CHANNEL_CONFIG_TOP_CENTER = 0x00000800, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT = 0x00001000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_CENTER = 0x00002000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT = 0x00004000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_LEFT = 0x00008000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_CENTER = 0x00010000, - AUDIO_CHANNEL_CONFIG_TOP_BACK_RIGHT = 0x00020000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_LEFT_OF_CENTER = 0x00040000, - AUDIO_CHANNEL_CONFIG_TOP_FRONT_RIGHT_OF_CENTER = 0x00080000, - AUDIO_CHANNEL_CONFIG_LEFT_LOW_FRQ_EFFECTS = 0x00100000, - AUDIO_CHANNEL_CONFIG_RIGHT_LOW_FRQ_EFFECTS = 0x00200000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_LEFT = 0x00400000, - AUDIO_CHANNEL_CONFIG_TOP_SIDE_RIGHT = 0x00800000, - AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, - AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, - AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000u, -} audio_channel_config_t; +//--------------------------------------------------------------------+ +// USB AUDIO CLASS 2.0 (UAC2) DESCRIPTORS +//--------------------------------------------------------------------+ -/// AUDIO Channel Cluster Descriptor (4.1) +/// AUDIO Channel Cluster Descriptor UAC2 (4.1) typedef struct TU_ATTR_PACKED { - uint8_t bNrChannels; ///< Number of channels currently connected. - audio_channel_config_t bmChannelConfig; ///< Bitmap according to 'audio_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. - uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. -} audio_desc_channel_cluster_t; + uint8_t bNrChannels; ///< Number of channels currently connected. + uint32_t bmChannelConfig;///< Bitmap according to 'audio20_channel_config_t' with a 1 set if channel is connected and 0 else. In case channels are non-predefined ignore them here (see UAC2 specification 4.1 Audio Channel Cluster Descriptor. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first inserted channel with a non-predefined spatial location. +} audio20_desc_channel_cluster_t; -/// AUDIO Class-Specific AC Interface Header Descriptor (4.7.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 9. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_HEADER. - uint16_t bcdADC ; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). - uint8_t bCategory ; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio_function_t. - uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. - uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. -} audio_desc_cs_ac_interface_t; -TU_VERIFY_STATIC(sizeof(audio_desc_cs_ac_interface_t) == 9, "size is not correct"); +/// AUDIO Class-Specific AC Interface Header Descriptor UAC2 (4.7.2) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes: 9. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AC_INTERFACE_HEADER. + uint16_t bcdADC; ///< Audio Device Class Specification Release Number in Binary-Coded Decimal. Value: U16_TO_U8S_LE(0x0200). + uint8_t bCategory; ///< Constant, indicating the primary use of this audio function, as intended by the manufacturer. See: audio20_function_code_t. + uint16_t wTotalLength; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. + uint8_t bmControls; ///< See: audio20_cs_ac_interface_control_pos_t. +} audio20_desc_cs_ac_interface_t; +TU_VERIFY_STATIC(sizeof(audio20_desc_cs_ac_interface_t) == 9, "size is not correct"); -/// AUDIO Clock Source Descriptor (4.7.2.1) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bmAttributes ; ///< See: audio_clock_source_attribute_t. - uint8_t bmControls ; ///< See: audio_clock_source_control_pos_t. - uint8_t bAssocTerminal ; ///< Terminal ID of the Terminal that is associated with this Clock Source. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Source Entity. -} audio_desc_clock_source_t; +/// AUDIO Clock Source Descriptor UAC2 (4.7.2.1) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes: 8. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AC_INTERFACE_CLOCK_SOURCE. + uint8_t bClockID; ///< Constant uniquely identifying the Clock Source Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bmAttributes; ///< See: audio20_clock_source_attribute_t. + uint8_t bmControls; ///< See: audio20_clock_source_control_pos_t. + uint8_t bAssocTerminal; ///< Terminal ID of the Terminal that is associated with this Clock Source. + uint8_t iClockSource; ///< Index of a string descriptor, describing the Clock Source Entity. +} audio20_desc_clock_source_t; -/// AUDIO Clock Selector Descriptor (4.7.2.2) for ONE pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7+p. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_SELECTOR. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bNrInPins ; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. - uint8_t baCSourceID ; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. - uint8_t bmControls ; ///< See: audio_clock_selector_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Selector Entity. -} audio_desc_clock_selector_t; +/// AUDIO Clock Selector Descriptor UAC2 (4.7.2.2) for ONE pin +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 7+p. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AC_INTERFACE_CLOCK_SELECTOR. + uint8_t bClockID; ///< Constant uniquely identifying the Clock Selector Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bNrInPins; ///< Number of Input Pins of this Unit: p = 1 thus bNrInPins = 1. + uint8_t baCSourceID; ///< ID of the Clock Entity to which the first Clock Input Pin of this Clock Selector Entity is connected.. + uint8_t bmControls; ///< See: audio20_clock_selector_control_pos_t. + uint8_t iClockSource; ///< Index of a string descriptor, describing the Clock Selector Entity. +} audio20_desc_clock_selector_t; /// AUDIO Clock Selector Descriptor (4.7.2.2) for multiple pins -#define audio_desc_clock_selector_n_t(source_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bClockID ; \ - uint8_t bNrInPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID ; \ - } sourceID[source_num] ; \ - uint8_t bmControls ; \ - uint8_t iClockSource ; \ -} +#define audio20_desc_clock_selector_n_t(source_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bClockID; \ + uint8_t bNrInPins; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID; \ + } sourceID[source_num]; \ + uint8_t bmControls; \ + uint8_t iClockSource; \ + } -/// AUDIO Clock Multiplier Descriptor (4.7.2.3) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 7. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_CLOCK_MULTIPLIER. - uint8_t bClockID ; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. - uint8_t bmControls ; ///< See: audio_clock_multiplier_control_pos_t. - uint8_t iClockSource ; ///< Index of a string descriptor, describing the Clock Multiplier Entity. -} audio_desc_clock_multiplier_t; +/// AUDIO Clock Multiplier Descriptor UAC2 (4.7.2.3) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 7. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AC_INTERFACE_CLOCK_MULTIPLIER. + uint8_t bClockID; ///< Constant uniquely identifying the Clock Multiplier Entity within the audio function. This value is used in all requests to address this Entity. + uint8_t bCSourceID; ///< ID of the Clock Entity to which the last Clock Input Pin of this Clock Selector Entity is connected. + uint8_t bmControls; ///< See: audio20_clock_multiplier_control_pos_t. + uint8_t iClockSource; ///< Index of a string descriptor, describing the Clock Multiplier Entity. +} audio20_desc_clock_multiplier_t; /// AUDIO Input Terminal Descriptor(4.7.2.4) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 17. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. - uint8_t bAssocTerminal ; ///< ID of the Output Terminal to which this Input Terminal is associated. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Input Terminal is connected. - uint8_t bNrChannels ; ///< Number of logical output channels in the Terminal’s output audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the logical channels. See:audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first logical channel. - uint16_t bmControls ; ///< See: audio_terminal_input_control_pos_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Input Terminal. -} audio_desc_input_terminal_t; +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 17. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL. + uint8_t bTerminalID; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this terminal. + uint16_t wTerminalType; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_input_type_t for other input types. + uint8_t bAssocTerminal; ///< ID of the Output Terminal to which this Input Terminal is associated. + uint8_t bCSourceID; ///< ID of the Clock Entity to which this Input Terminal is connected. + uint8_t bNrChannels; ///< Number of logical output channels in the Terminal’s output audio channel cluster. + uint32_t bmChannelConfig; ///< Describes the spatial location of the logical channels. See:audio20_channel_config_t. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first logical channel. + uint16_t bmControls; ///< See: audio_terminal_input_control_pos_t. + uint8_t iTerminal; ///< Index of a string descriptor, describing the Input Terminal. +} audio20_desc_input_terminal_t; -/// AUDIO Output Terminal Descriptor(4.7.2.5) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 12. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL. - uint8_t bTerminalID ; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. - uint16_t wTerminalType ; ///< Constant characterizing the type of Terminal. See: audio_terminal_type_t for USB streaming and audio_terminal_output_type_t for other output types. - uint8_t bAssocTerminal ; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Terminal is connected. - uint8_t bCSourceID ; ///< ID of the Clock Entity to which this Output Terminal is connected. - uint16_t bmControls ; ///< See: audio_terminal_output_type_t. - uint8_t iTerminal ; ///< Index of a string descriptor, describing the Output Terminal. -} audio_desc_output_terminal_t; +/// AUDIO Output Terminal Descriptor UAC2 (4.7.2.5) +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 12. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL. + uint8_t bTerminalID; ///< Constant uniquely identifying the Terminal within the audio function. This value is used in all requests to address this Terminal. + uint16_t wTerminalType; ///< Constant characterizing the type of Terminal. See: audio20_terminal_type_t for USB streaming and audio20_terminal_output_type_t for other output types. + uint8_t bAssocTerminal; ///< Constant, identifying the Input Terminal to which this Output Terminal is associated. + uint8_t bSourceID; ///< ID of the Unit or Terminal to which this Terminal is connected. + uint8_t bCSourceID; ///< ID of the Clock Entity to which this Output Terminal is connected. + uint16_t bmControls; ///< See: audio20_terminal_output_control_pos_t. + uint8_t iTerminal; ///< Index of a string descriptor, describing the Output Terminal. +} audio20_desc_output_terminal_t; -/// AUDIO Feature Unit Descriptor(4.7.2.8) for ONE channel -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 14. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AC_INTERFACE_FEATURE_UNIT. - uint8_t bUnitID ; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. - uint8_t bSourceID ; ///< ID of the Unit or Terminal to which this Feature Unit is connected. +/// AUDIO Feature Unit Descriptor UAC2 (4.7.2.8) for ONE channel +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 14. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AC_INTERFACE_FEATURE_UNIT. + uint8_t bUnitID; ///< Constant uniquely identifying the Unit within the audio function. This value is used in all requests to address this Unit. + uint8_t bSourceID; ///< ID of the Unit or Terminal to which this Feature Unit is connected. struct TU_ATTR_PACKED { - uint32_t bmaControls ; ///< See: audio_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. - } controls[2] ; - uint8_t iTerminal ; ///< Index of a string descriptor, describing this Feature Unit. -} audio_desc_feature_unit_t; + uint32_t bmaControls;///< See: audio20_feature_unit_control_pos_t. Controls0 is master channel 0 (always present) and Controls1 is logical channel 1. + } controls[2]; + uint8_t iTerminal;///< Index of a string descriptor, describing this Feature Unit. +} audio20_desc_feature_unit_t; /// AUDIO Feature Unit Descriptor(4.7.2.8) for multiple channels -#define audio_desc_feature_unit_n_t(ch_num)\ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; /* 6+(ch_num+1)*4 */\ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bUnitID ; \ - uint8_t bSourceID ; \ - struct TU_ATTR_PACKED { \ - uint32_t bmaControls ; \ - } controls[ch_num+1] ; \ - uint8_t iTerminal ; \ -} +#define audio20_desc_feature_unit_n_t(ch_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; /* 6+(ch_num+1)*4 */ \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bUnitID; \ + uint8_t bSourceID; \ + struct TU_ATTR_PACKED { \ + uint32_t bmaControls; \ + } controls[ch_num + 1]; \ + uint8_t iTerminal; \ + } /// AUDIO Class-Specific AS Interface Descriptor(4.9.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 16. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_AS_GENERAL. - uint8_t bTerminalLink ; ///< The Terminal ID of the Terminal to which this interface is connected. - uint8_t bmControls ; ///< See: audio_cs_as_interface_control_pos_t. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio_format_type_t. - uint32_t bmFormats ; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio_data_format_type_I_t. - uint8_t bNrChannels ; ///< Number of physical channels in the AS Interface audio channel cluster. - uint32_t bmChannelConfig ; ///< Describes the spatial location of the physical channels. See: audio_channel_config_t. - uint8_t iChannelNames ; ///< Index of a string descriptor, describing the name of the first physical channel. -} audio_desc_cs_as_interface_t; +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 16. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AS_INTERFACE_AS_GENERAL. + uint8_t bTerminalLink; ///< The Terminal ID of the Terminal to which this interface is connected. + uint8_t bmControls; ///< See: audio20_cs_as_interface_control_pos_t. + uint8_t bFormatType; ///< Constant identifying the Format Type the AudioStreaming interface is using. See: audio20_format_type_t. + uint32_t bmFormats; ///< The Audio Data Format(s) that can be used to communicate with this interface.See: audio20_data_format_type_I_t. + uint8_t bNrChannels; ///< Number of physical channels in the AS Interface audio channel cluster. + uint32_t bmChannelConfig; ///< Describes the spatial location of the physical channels. See: audio20_channel_config_t. + uint8_t iChannelNames; ///< Index of a string descriptor, describing the name of the first physical channel. +} audio20_desc_cs_as_interface_t; /// AUDIO Type I Format Type Descriptor(2.3.1.6 - Audio Formats) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 6. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_AS_INTERFACE_FORMAT_TYPE. - uint8_t bFormatType ; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO_FORMAT_TYPE_I. - uint8_t bSubslotSize ; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. - uint8_t bBitResolution ; ///< The number of effectively used bits from the available bits in an audio subslot. -} audio_desc_type_I_format_t; +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 6. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_INTERFACE. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_AS_INTERFACE_FORMAT_TYPE. + uint8_t bFormatType; ///< Constant identifying the Format Type the AudioStreaming interface is using. Value: AUDIO20_FORMAT_TYPE_I. + uint8_t bSubslotSize; ///< The number of bytes occupied by one audio subslot. Can be 1, 2, 3 or 4. + uint8_t bBitResolution; ///< The number of effectively used bits from the available bits in an audio subslot. +} audio20_desc_type_I_format_t; /// AUDIO Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor, in bytes: 8. - uint8_t bDescriptorType ; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. - uint8_t bDescriptorSubType ; ///< Descriptor SubType. Value: AUDIO_CS_EP_SUBTYPE_GENERAL. - uint8_t bmAttributes ; ///< See: audio_cs_as_iso_data_ep_attribute_t. - uint8_t bmControls ; ///< See: audio_cs_as_iso_data_ep_control_pos_t. - uint8_t bLockDelayUnits ; ///< Indicates the units used for the wLockDelay field. See: audio_cs_as_iso_data_ep_lock_delay_unit_t. - uint16_t wLockDelay ; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. -} audio_desc_cs_as_iso_data_ep_t; +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor, in bytes: 8. + uint8_t bDescriptorType; ///< Descriptor Type. Value: TUSB_DESC_CS_ENDPOINT. + uint8_t bDescriptorSubType;///< Descriptor SubType. Value: AUDIO20_CS_EP_SUBTYPE_GENERAL. + uint8_t bmAttributes; ///< See: audio20_cs_as_iso_data_ep_attribute_t. + uint8_t bmControls; ///< See: audio20_cs_as_iso_data_ep_control_pos_t. + uint8_t bLockDelayUnits; ///< Indicates the units used for the wLockDelay field. See: audio20_cs_as_iso_data_ep_lock_delay_unit_t. + uint16_t wLockDelay; ///< Indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry. Units used depend on the value of the bLockDelayUnits field. +} audio20_desc_cs_as_iso_data_ep_t; // 5.2.2 Control Request Layout -typedef struct TU_ATTR_PACKED -{ - union - { - struct TU_ATTR_PACKED - { - uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. - uint8_t type : 2; ///< Request type tusb_request_type_t. - uint8_t direction : 1; ///< Direction type. tusb_dir_t - } bmRequestType_bit; +typedef struct TU_ATTR_PACKED { + union { + struct TU_ATTR_PACKED { + uint8_t recipient : 5;///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1;///< Direction type. tusb_dir_t + } bmRequestType_bit; - uint8_t bmRequestType; - }; + uint8_t bmRequestType; + }; - uint8_t bRequest; ///< Request type audio_cs_req_t - uint8_t bChannelNumber; - uint8_t bControlSelector; - union - { - uint8_t bInterface; - uint8_t bEndpoint; - }; - uint8_t bEntityID; - uint16_t wLength; -} audio_control_request_t; + uint8_t bRequest;///< Request type audio_cs_req_t + uint8_t bChannelNumber; + uint8_t bControlSelector; + union { + uint8_t bInterface; + uint8_t bEndpoint; + }; + uint8_t bEntityID; + uint16_t wLength; +} audio20_control_request_t; //// 5.2.3 Control Request Parameter Block Layout // 5.2.3.1 1-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int8_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_1_t; +typedef struct TU_ATTR_PACKED { + int8_t bCur;///< The setting for the CUR attribute of the addressed Control +} audio20_control_cur_1_t; // 5.2.3.2 2-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int16_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_2_t; - -// 5.2.3.3 4-byte Control CUR Parameter Block -typedef struct TU_ATTR_PACKED -{ - int32_t bCur ; ///< The setting for the CUR attribute of the addressed Control -} audio_control_cur_4_t; - -// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the one below for predefined lengths - or if you know what you are doing do what you like -// 5.2.3.1 1-byte Control RANGE Parameter Block typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_1_t; + int16_t bCur;///< The setting for the CUR attribute of the addressed Control +} audio20_control_cur_2_t; -// 5.2.3.2 2-byte Control RANGE Parameter Block +// 5.2.3.3 4-byte Control CUR Parameter Block typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_2_t; + int32_t bCur;///< The setting for the CUR attribute of the addressed Control +} audio20_control_cur_4_t; -// 5.2.3.3 4-byte Control RANGE Parameter Block -typedef struct TU_ATTR_PACKED { - uint16_t wNumSubRanges; - struct TU_ATTR_PACKED { - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ - } subrange[] ; -} audio_control_range_4_t; +// Use the following ONLY for RECEIVED data - compiler does not know how many subranges are defined! Use the #define macros below for predefined lengths. // 5.2.3.1 1-byte Control RANGE Parameter Block -#define audio_control_range_1_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int8_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int8_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint8_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges] ; \ -} +#define audio20_control_range_1_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int8_t bMin; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ \ + int8_t bMax; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ \ + uint8_t bRes; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ \ + } subrange[numSubRanges]; \ + } /// 5.2.3.2 2-byte Control RANGE Parameter Block -#define audio_control_range_2_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int16_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int16_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint16_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} +#define audio20_control_range_2_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int16_t bMin; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ \ + int16_t bMax; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ \ + uint16_t bRes; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ \ + } subrange[numSubRanges]; \ + } // 5.2.3.3 4-byte Control RANGE Parameter Block -#define audio_control_range_4_n_t(numSubRanges) \ - struct TU_ATTR_PACKED { \ - uint16_t wNumSubRanges; \ - struct TU_ATTR_PACKED { \ - int32_t bMin ; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/\ - int32_t bMax ; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/\ - uint32_t bRes ; /*The setting for the RES attribute of the nth subrange of the addressed Control*/\ - } subrange[numSubRanges]; \ -} +#define audio20_control_range_4_n_t(numSubRanges) \ + struct TU_ATTR_PACKED { \ + uint16_t wNumSubRanges; \ + struct TU_ATTR_PACKED { \ + int32_t bMin; /*The setting for the MIN attribute of the nth subrange of the addressed Control*/ \ + int32_t bMax; /*The setting for the MAX attribute of the nth subrange of the addressed Control*/ \ + uint32_t bRes; /*The setting for the RES attribute of the nth subrange of the addressed Control*/ \ + } subrange[numSubRanges]; \ + } // 6.1 Interrupt Data Message Format -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bInfo; uint8_t bAttribute; - union - { + union { uint16_t wValue; - struct - { + struct { uint8_t wValue_cn_or_mcn; uint8_t wValue_cs; }; }; - union - { + union { uint16_t wIndex; - struct - { + struct { uint8_t wIndex_ep_or_int; uint8_t wIndex_entity_id; }; }; +} audio20_interrupt_data_t; + +//--------------------------------------------------------------------+ +// APPLICATION HELPER DEFINITIONS +//--------------------------------------------------------------------+ + +// Combined Interrupt Data Message Format for both UAC1 and UAC2 +typedef union { + audio10_interrupt_data_t v1; + audio20_interrupt_data_t v2; } audio_interrupt_data_t; +// MIDI1.0 use the same CS AC Interface Descriptor as UAC1 +typedef audio10_desc_cs_ac_interface_n_t(1) midi10_desc_cs_ac_interface_t; + +// UAC1.0 AC Interface Descriptor with 1 interface, used to read fields other than baInterfaceNr +typedef audio10_desc_cs_ac_interface_n_t(1) audio10_desc_cs_ac_interface_1_t; + /** @} */ #ifdef __cplusplus diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 701411401..1dda8af99 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -79,10 +79,9 @@ // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer // is available or driver is would need to be changed dramatically -// Only STM32 and dcd_transdimension use non-linear buffer for now -// dwc2 except esp32sx (since it may use dcd_esp32sx) +// Only STM32 and ChipIdea HS use non-linear buffer for now // Ring buffer is incompatible with dcache, since neither address nor size is aligned to cache line -#if (defined(TUP_USBIP_DWC2) && !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3)) || \ +#if defined(TUP_USBIP_DWC2) || \ defined(TUP_USBIP_FSDEV) || \ CFG_TUSB_MCU == OPT_MCU_RX63X || \ CFG_TUSB_MCU == OPT_MCU_RX65X || \ @@ -181,16 +180,8 @@ tu_static CFG_TUD_MEM_SECTION struct { } lin_buf_out; #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && USE_LINEAR_BUFFER -// Control buffers -tu_static CFG_TUD_MEM_SECTION struct { - TUD_EPBUF_DEF(buf1, CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ); - #if CFG_TUD_AUDIO > 1 - TUD_EPBUF_DEF(buf2, CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ); - #endif - #if CFG_TUD_AUDIO > 2 - TUD_EPBUF_DEF(buf3, CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ); - #endif -} ctrl_buf; +// Control buffer +CFG_TUD_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_AUDIO_CTRL_BUF_SZ]; // Aligned buffer for feedback EP #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -218,12 +209,15 @@ typedef struct { uint8_t rhport; uint8_t const *p_desc;// Pointer pointing to Standard AC Interface Descriptor(4.7.1) - Audio Control descriptor defining audio function + uint8_t const *p_desc_as;// Pointer pointing to 1st Standard AS Interface Descriptor(4.9.1) - Audio Streaming descriptor defining audio function + uint16_t desc_length;// Length of audio function descriptor #if CFG_TUD_AUDIO_ENABLE_EP_IN uint8_t ep_in; // TX audio data EP. uint16_t ep_in_sz; // Current size of TX EP uint8_t ep_in_as_intf_num;// Corresponding Standard AS Interface Descriptor (4.9.1) belonging to output terminal to which this EP belongs - 0 is invalid (this fits to UAC2 specification since AS interfaces can not have interface number equal to zero) uint8_t ep_in_alt; // Current alternate setting of TX EP + uint16_t ep_in_fifo_threshold;// Target size for the EP IN FIFO. #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -243,8 +237,6 @@ typedef struct bool mounted;// Device opened - uint16_t desc_length;// Length of audio function descriptor - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP struct { uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). @@ -253,7 +245,6 @@ typedef struct uint8_t frame_shift;// bInterval-1 in unit of frame (FS), micro-frame (HS) uint8_t compute_method; - bool format_correction; union { uint8_t power_of_2;// pre-computed power of 2 shift float float_const; // pre-computed float constant @@ -279,21 +270,13 @@ typedef struct uint16_t packet_sz_tx[3]; uint8_t bclock_id_tx; uint8_t interval_tx; -#endif - -// Encoding parameters - parameters are set when alternate AS interface is set by host -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - audio_format_type_t format_type_tx; + uint8_t format_type_tx; uint8_t n_channels_tx; uint8_t n_bytes_per_sample_tx; #endif /*------------- From this point, data is not cleared by bus reset -------------*/ - // Buffer for control requests - uint8_t *ctrl_buf; - uint8_t ctrl_buf_sz; - // EP Transfer buffers and FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_OUT tu_fifo_t ep_out_ff; @@ -327,7 +310,11 @@ typedef struct #define USE_LINEAR_BUFFER_RX 0 #endif -#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ep_out_ff) +#else +#define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ep_in_ff) +#endif //--------------------------------------------------------------------+ // WEAK FUNCTION STUBS @@ -363,11 +350,6 @@ TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, feedback_param->method = AUDIO_FEEDBACK_METHOD_DISABLED; } -TU_ATTR_WEAK bool tud_audio_feedback_format_correction_cb(uint8_t func_id) { - (void) func_id; - return CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION; -} - TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift) { (void) func_id; (void) frame_number; @@ -376,7 +358,7 @@ TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func #endif #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP -TU_ATTR_WEAK void tud_audio_int_xfer_cb(uint8_t rhport) { +TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport) { (void) rhport; } #endif @@ -465,16 +447,16 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *func_id); static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); -static uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio); +static inline uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio); #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL static void audiod_parse_flow_control_params(audiod_function_t *audio, uint8_t const *p_desc); static bool audiod_calc_tx_packet_sz(audiod_function_t *audio); -static uint16_t audiod_tx_packet_size(const uint16_t *norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_size); +static uint16_t audiod_tx_packet_size(const uint16_t *nominal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t fifo_threshold, uint16_t max_size); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool audiod_set_fb_params_freq(audiod_function_t *audio, uint32_t sample_freq, uint32_t mclk_freq); +static bool audiod_fb_params_prepare(uint8_t func_id, uint8_t alt); static void audiod_fb_fifo_count_update(audiod_function_t *audio, uint16_t lvl_new); #endif @@ -518,13 +500,13 @@ static bool audiod_rx_xfer_isr(uint8_t rhport, audiod_function_t* audio, uint16_ #if USE_LINEAR_BUFFER_RX // Data currently is in linear buffer, copy into EP OUT FIFO - TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); + TU_VERIFY(0 < tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); // Schedule for next receive - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz, true)); #else // Data is already placed in EP FIFO, schedule for next receive - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz, true)); #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -564,6 +546,17 @@ tu_fifo_t *tud_audio_n_get_ep_in_ff(uint8_t func_id) { return NULL; } +uint16_t tud_audio_n_get_ep_in_fifo_threshold(uint8_t func_id) { + if (func_id < CFG_TUD_AUDIO) return _audiod_fct[func_id].ep_in_fifo_threshold; + return 0; +} + +void tud_audio_n_set_ep_in_fifo_threshold(uint8_t func_id, uint16_t threshold) { + if (func_id < CFG_TUD_AUDIO && threshold < _audiod_fct[func_id].ep_in_ff.depth) { + _audiod_fct[func_id].ep_in_fifo_threshold = threshold; + } +} + static bool audiod_tx_xfer_isr(uint8_t rhport, audiod_function_t * audio, uint16_t n_bytes_sent) { uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); @@ -575,16 +568,16 @@ static bool audiod_tx_xfer_isr(uint8_t rhport, audiod_function_t * audio, uint16 #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL // packet_sz_tx is based on total packet size, here we want size for each support buffer. - n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_sz); + n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_fifo_threshold, audio->ep_in_sz); #else n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz);// Limit up to max packet size, more can not be done for ISO #endif #if USE_LINEAR_BUFFER_TX tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx, true)); #else // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx, true)); #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer @@ -595,6 +588,10 @@ static bool audiod_tx_xfer_isr(uint8_t rhport, audiod_function_t * audio, uint16 #endif +//--------------------------------------------------------------------+ +// OTHER API +//--------------------------------------------------------------------+ + #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_done_cb() is called in inform user bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data) { @@ -605,10 +602,15 @@ bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data) // We write directly into the EP's buffer - abort if previous transfer not complete TU_VERIFY(usbd_edpt_claim(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int)); + uint8_t size = tud_audio_n_version(func_id) == 2 ? sizeof(audio20_interrupt_data_t) : sizeof(audio10_interrupt_data_t); + + // INT EP buffer must be large enough + TU_ASSERT(size <= sizeof(int_ep_buf[func_id].buf)); + // Check length - if (tu_memcpy_s(int_ep_buf[func_id].buf, sizeof(int_ep_buf[func_id].buf), data, sizeof(audio_interrupt_data_t)) == 0) { + if (tu_memcpy_s(int_ep_buf[func_id].buf, sizeof(int_ep_buf[func_id].buf), data, size) == 0) { // Schedule transmit - TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int, int_ep_buf[func_id].buf, sizeof(int_ep_buf[func_id].buf)), 0); + TU_ASSERT(usbd_edpt_xfer(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int, int_ep_buf[func_id].buf, size, false)); } else { // Release endpoint since we don't make any transfer usbd_edpt_release(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_int); @@ -620,10 +622,11 @@ bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data) #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent -static inline bool audiod_fb_send(audiod_function_t *audio) { - bool apply_correction = (TUSB_SPEED_FULL == tud_speed_get()) && audio->feedback.format_correction; +static inline bool audiod_fb_send(uint8_t func_id, bool is_isr) { + audiod_function_t *audio = &_audiod_fct[func_id]; + uint8_t uac_version = tud_audio_n_version(func_id); // Format the feedback value - if (apply_correction) { + if (uac_version == 1) { uint8_t *fb = (uint8_t *) audio->fb_buf; // For FS format is 10.14 @@ -635,23 +638,70 @@ static inline bool audiod_fb_send(audiod_function_t *audio) { *audio->fb_buf = audio->feedback.value; } - // About feedback format on FS - // - // 3 variables: Format | packetSize | sendSize | Working OS: - // 16.16 4 4 Linux, Windows - // 16.16 4 3 Linux - // 16.16 3 4 Linux - // 16.16 3 3 Linux - // 10.14 4 4 Linux - // 10.14 4 3 Linux - // 10.14 3 4 Linux, OSX - // 10.14 3 3 Linux, OSX - // - // We send 3 bytes since sending packet larger than wMaxPacketSize is pretty ugly - return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) audio->fb_buf, apply_correction ? 3 : 4); + return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) audio->fb_buf, uac_version == 1 ? 3 : 4, is_isr); +} + +uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) { + audiod_function_t *audio = &_audiod_fct[func_id]; + uint32_t feedback; + + switch (audio->feedback.compute_method) { + case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: + feedback = (cycles << audio->feedback.compute.power_of_2); + break; + + case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: + feedback = (uint32_t) ((float) cycles * audio->feedback.compute.float_const); + break; + + case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: { + uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - (audio->feedback.frame_shift - 1)); + feedback = (uint32_t) (fb64 / audio->feedback.compute.fixed.mclk_freq); + } break; + + default: + return 0; + } + + // For Windows: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/usb-2-0-audio-drivers + // The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1. + // This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot + // (audio slot = channel count samples). + if (feedback > audio->feedback.max_value) { + feedback = audio->feedback.max_value; + } + if (feedback < audio->feedback.min_value) { + feedback = audio->feedback.min_value; + } + + tud_audio_n_fb_set(func_id, feedback); + + return feedback; +} + +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) { + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + + _audiod_fct[func_id].feedback.value = feedback; + + return true; } #endif +uint8_t tud_audio_n_version(uint8_t func_id) { + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + + uint8_t bIntfProtocol = ((tusb_desc_interface_t const *)_audiod_fct[func_id].p_desc)->bInterfaceProtocol; + + if (bIntfProtocol == AUDIO_INT_PROTOCOL_CODE_V1) { + return 1; + } else if (bIntfProtocol == AUDIO_INT_PROTOCOL_CODE_V2) { + return 2; + } else { + return 0; // Unknown version + } +} + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ @@ -661,29 +711,8 @@ void audiod_init(void) { for (uint8_t i = 0; i < CFG_TUD_AUDIO; i++) { audiod_function_t *audio = &_audiod_fct[i]; - // Initialize control buffers - switch (i) { - case 0: - audio->ctrl_buf = ctrl_buf.buf1; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; - break; -#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 - case 1: - audio->ctrl_buf = ctrl_buf.buf2; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; - break; -#endif -#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 - case 2: - audio->ctrl_buf = ctrl_buf.buf3; - audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; - break; -#endif - } - // Initialize IN EP FIFO if required #if CFG_TUD_AUDIO_ENABLE_EP_IN - switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 case 0: @@ -817,7 +846,8 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint AUDIO_SUBCLASS_CONTROL == itf_desc->bInterfaceSubClass); // Verify version is correct - this check can be omitted - TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); + TU_VERIFY(itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V1 || + itf_desc->bInterfaceProtocol == AUDIO_INT_PROTOCOL_CODE_V2); // Verify interrupt control EP is enabled if demanded by descriptor TU_ASSERT(itf_desc->bNumEndpoints <= 1);// 0 or 1 EPs are allowed @@ -835,21 +865,32 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint _audiod_fct[i].p_desc = (uint8_t const *) itf_desc;// Save pointer to AC descriptor which is by specification always the first one _audiod_fct[i].rhport = rhport; - // Setup descriptor lengths - switch (i) { - case 0: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_1_DESC_LEN; - break; -#if CFG_TUD_AUDIO > 1 - case 1: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_2_DESC_LEN; - break; -#endif -#if CFG_TUD_AUDIO > 2 - case 2: - _audiod_fct[i].desc_length = CFG_TUD_AUDIO_FUNC_3_DESC_LEN; - break; -#endif + // Calculate descriptor length + { + uint8_t const *p_desc = (uint8_t const *) itf_desc; + uint8_t const *p_desc_end = p_desc + max_len; + uint16_t total_len = sizeof(tusb_desc_interface_t); + // Skip Standard AC interface descriptor + p_desc = tu_desc_next(p_desc); + while (p_desc_end - p_desc > 0) { + // Stop if: + // - Non audio streaming interface descriptor found + // - IAD found + if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && + !(((tusb_desc_interface_t const *) p_desc)->bInterfaceClass == TUSB_CLASS_AUDIO && ((tusb_desc_interface_t const *) p_desc)->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING)) + || tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { + break; + } else if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *) p_desc)->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING) { + if (_audiod_fct[i].p_desc_as == NULL) { + _audiod_fct[i].p_desc_as = p_desc; + } + } else { + // nothing to do + } + total_len += p_desc[0]; + p_desc = tu_desc_next(p_desc); + } + _audiod_fct[i].desc_length = total_len; } #ifdef TUP_DCD_EDPT_ISO_ALLOC @@ -868,54 +909,67 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint uint8_t ep_fb = 0; #endif uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length; // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { + // Unified UAC1/UAC2 endpoint processing tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Explicit feedback EP - if (desc_ep->bmAttributes.usage == 1) { - ep_fb = desc_ep->bEndpointAddress; - } - #endif - #if CFG_TUD_AUDIO_ENABLE_EP_IN - // Data or data with implicit feedback IN EP - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN - && (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) { - ep_in = desc_ep->bEndpointAddress; - ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); - } - #endif - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - // Data OUT EP - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT - && desc_ep->bmAttributes.usage == 0) { - ep_out = desc_ep->bEndpointAddress; - ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); - } - #endif + bool is_feedback_ep = false; + bool is_data_ep = false; + + if (tud_audio_n_version(i) == 1) { + // UAC1: Use bRefresh field to distinguish endpoint types + audio10_desc_as_iso_data_ep_t const *desc_ep_uac1 = (audio10_desc_as_iso_data_ep_t const *) p_desc; + is_data_ep = (desc_ep_uac1->bmAttributes.sync != TUSB_ISO_EP_ATT_NO_SYNC); + is_feedback_ep = (desc_ep_uac1->bmAttributes.sync == TUSB_ISO_EP_ATT_NO_SYNC); + } else { + // UAC2: Use bmAttributes.usage to distinguish endpoint types + is_data_ep = (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2); + is_feedback_ep = (desc_ep->bmAttributes.usage == 1); } + + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + // Explicit feedback EP + if (is_feedback_ep) { + ep_fb = desc_ep->bEndpointAddress; + } + #else + (void) is_feedback_ep; + #endif + #if CFG_TUD_AUDIO_ENABLE_EP_IN + // Data or data with implicit feedback IN EP + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN && is_data_ep) { + ep_in = desc_ep->bEndpointAddress; + ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); + } + #endif + #if CFG_TUD_AUDIO_ENABLE_EP_OUT + // Data OUT EP + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT && is_data_ep) { + ep_out = desc_ep->bEndpointAddress; + ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); + } + #endif } p_desc = tu_desc_next(p_desc); } #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (ep_in) { + if (ep_in != 0) { usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size); } #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (ep_out) { + if (ep_out != 0) { usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size); } #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (ep_fb) { + if (ep_fb != 0) { usbd_edpt_iso_alloc(rhport, ep_fb, 4); } #endif @@ -925,22 +979,27 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL { uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length; // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { // For data or data with implicit feedback IN EP + // For UAC1 this is always the case since there is no usage field if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN && (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) { _audiod_fct[i].interval_tx = desc_ep->bInterval; } } - } else if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) { + } else if (tud_audio_n_version(i) == 2 && + tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL) { + // For UAC2 only, UAC1 doesn't have a clock source if (tu_unaligned_read16(p_desc + 4) == AUDIO_TERM_TYPE_USB_STREAMING) { _audiod_fct[i].bclock_id_tx = p_desc[8]; } + } else { + // nothing to do } p_desc = tu_desc_next(p_desc); } @@ -950,7 +1009,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP { uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length; // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning while (p_desc_end - p_desc > 0) { // For each endpoint @@ -978,7 +1037,7 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint TU_ASSERT(i < CFG_TUD_AUDIO); // This is all we need so far - the EPs are setup by a later set_interface request (as per UAC2 specification) - uint16_t drv_len = _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;// - TUD_AUDIO_DESC_IAD_LEN since tinyUSB already handles the IAD descriptor + uint16_t drv_len = _audiod_fct[i].desc_length; return drv_len; } @@ -1088,11 +1147,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT // Open new EP if necessary - EPs are only to be closed or opened for AS interfaces - Look for AS interface with correct alternate interface - uint8_t const *p_desc = tu_desc_next(audio->p_desc); - // Skip entire AC descriptor block - p_desc += ((audio_desc_cs_ac_interface_t const *) p_desc)->wTotalLength; + + uint8_t const *p_desc = audio->p_desc_as; // Get pointer at end - uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = audio->p_desc + audio->desc_length; // p_desc starts at required interface with alternate setting zero // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning @@ -1115,18 +1173,34 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #endif uint8_t const ep_addr = desc_ep->bEndpointAddress; + bool is_feedback_ep = false; + bool is_data_ep = false; + + if (tud_audio_n_version(func_id) == 1) { + // UAC1: Use bRefresh field to distinguish endpoint types + audio10_desc_as_iso_data_ep_t const *desc_ep_uac1 = (audio10_desc_as_iso_data_ep_t const *) p_desc; + is_data_ep = (desc_ep_uac1->bmAttributes.sync != TUSB_ISO_EP_ATT_NO_SYNC); + is_feedback_ep = (desc_ep_uac1->bmAttributes.sync == TUSB_ISO_EP_ATT_NO_SYNC); + } else { + // UAC2: Use bmAttributes.usage to distinguish endpoint types + is_data_ep = (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2); + is_feedback_ep = (desc_ep->bmAttributes.usage == 1); + } + //TODO: We need to set EP non busy since this is not taken care of right now in ep_close() - THIS IS A WORKAROUND! usbd_edpt_clear_stall(rhport, ep_addr); #if CFG_TUD_AUDIO_ENABLE_EP_IN // For data or data with implicit feedback IN EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && is_data_ep) { // Save address audio->ep_in = ep_addr; audio->ep_in_as_intf_num = itf; audio->ep_in_alt = alt; audio->ep_in_sz = tu_edpt_packet_size(desc_ep); + // Set the default EP IN FIFO threshold to half fifo depth. + audio->ep_in_fifo_threshold = audio->ep_in_ff.depth / 2; // If flow control is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL @@ -1134,17 +1208,17 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #endif // Schedule first transmit if alternate interface is not zero, as sample data is available a ZLP is loaded #if USE_LINEAR_BUFFER_TX - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, 0)); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, 0, false)); #else // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, 0)); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, 0, false)); #endif } #endif// CFG_TUD_AUDIO_ENABLE_EP_IN #if CFG_TUD_AUDIO_ENABLE_EP_OUT // Checking usage not necessary - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) { + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT && is_data_ep) { // Save address audio->ep_out = ep_addr; audio->ep_out_as_intf_num = itf; @@ -1153,21 +1227,25 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p // Prepare for incoming data #if USE_LINEAR_BUFFER_RX - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz, false)); #else - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz, false)); #endif } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Check if usage is explicit data feedback - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) { + if (is_feedback_ep) { audio->ep_fb = ep_addr; audio->feedback.frame_shift = desc_ep->bInterval - 1; // Schedule first feedback transmit - audiod_fb_send(audio); + audiod_fb_send(func_id, false); } + #else + (void) is_feedback_ep; #endif +#else + (void) is_feedback_ep; #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT foundEPs += 1; @@ -1181,50 +1259,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Prepare feedback computation if endpoint is available - if (audio->ep_fb != 0) { - audio_feedback_params_t fb_param; - - tud_audio_feedback_params_cb(func_id, alt, &fb_param); - audio->feedback.compute_method = fb_param.method; - - if (TUSB_SPEED_FULL == tud_speed_get()) - audio->feedback.format_correction = tud_audio_feedback_format_correction_cb(func_id); - - // Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame) - uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000; - audio->feedback.min_value = ((fb_param.sample_freq - 1) / frame_div) << 16; - audio->feedback.max_value = (fb_param.sample_freq / frame_div + 1) << 16; - - switch (fb_param.method) { - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: - case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - audiod_set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); - break; - - case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: { - // Initialize the threshold level to half filled - uint16_t fifo_lvl_thr = tu_fifo_depth(&audio->ep_out_ff) / 2; - audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr; - audio->feedback.compute.fifo_count.fifo_lvl_avg = ((uint32_t) fifo_lvl_thr) << 16; - // Avoid 64bit division - uint32_t nominal = ((fb_param.sample_freq / 100) << 16) / (frame_div / 100); - audio->feedback.compute.fifo_count.nom_value = nominal; - audio->feedback.compute.fifo_count.rate_const[0] = (uint16_t) ((audio->feedback.max_value - nominal) / fifo_lvl_thr); - audio->feedback.compute.fifo_count.rate_const[1] = (uint16_t) ((nominal - audio->feedback.min_value) / fifo_lvl_thr); - // On HS feedback is more sensitive since packet size can vary every MSOF, could cause instability - if (tud_speed_get() == TUSB_SPEED_HIGH) { - audio->feedback.compute.fifo_count.rate_const[0] /= 8; - audio->feedback.compute.fifo_count.rate_const[1] /= 8; - } - } break; - - // nothing to do - default: - break; - } - } + // Prepare feedback computation parameters + TU_VERIFY(audiod_fb_params_prepare(func_id, alt)); #endif// CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // We are done - abort loop @@ -1276,20 +1312,23 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - if (_audiod_fct[func_id].bclock_id_tx == entityID && ctrlSel == AUDIO_CS_CTRL_SAM_FREQ && p_request->bRequest == AUDIO_CS_REQ_CUR) { - _audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(_audiod_fct[func_id].ctrl_buf); + if (tud_audio_n_version(func_id) == 2) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + if (_audiod_fct[func_id].bclock_id_tx == entityID && ctrlSel == AUDIO20_CS_CTRL_SAM_FREQ && p_request->bRequest == AUDIO20_CS_REQ_CUR) { + _audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(ctrl_buf); + audiod_calc_tx_packet_sz(&_audiod_fct[func_id]); + } } #endif // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + return tud_audio_set_req_entity_cb(rhport, p_request, ctrl_buf); } else { // Find index of audio driver structure and verify interface really exists TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); + return tud_audio_set_req_itf_cb(rhport, p_request, ctrl_buf); } } break; @@ -1299,8 +1338,32 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const // Check if entity is present and get corresponding driver index TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + if (tud_audio_n_version(func_id) == 1) { + if (_audiod_fct[func_id].ep_in == ep) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + if (ctrlSel == AUDIO10_EP_CTRL_SAMPLING_FREQ && p_request->bRequest == AUDIO10_CS_REQ_SET_CUR) { + _audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(ctrl_buf) & 0x00FFFFFF; + audiod_calc_tx_packet_sz(&_audiod_fct[func_id]); + } + } + } +#endif + + // Invoke callback + bool ret = tud_audio_set_req_ep_cb(rhport, p_request, ctrl_buf); + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if (ret && tud_audio_n_version(func_id) == 1) { + if (_audiod_fct[func_id].ep_out == ep) { + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + if (ctrlSel == AUDIO10_EP_CTRL_SAMPLING_FREQ && p_request->bRequest == AUDIO10_CS_REQ_SET_CUR) { + audiod_fb_params_prepare(func_id, _audiod_fct[func_id].ep_out_alt); + } + } + } +#endif + return ret; } break; // Unknown/Unsupported recipient default: @@ -1385,7 +1448,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const } // If we end here, the received request is a set request - we schedule a receive for the data stage and return true here. We handle the rest later in audiod_control_complete() once the data stage was finished - TU_VERIFY(tud_control_xfer(rhport, p_request, _audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz)); + TU_VERIFY(tud_control_xfer(rhport, p_request, ctrl_buf, sizeof(ctrl_buf))); return true; } @@ -1399,6 +1462,8 @@ bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_ return audiod_control_request(rhport, request); } else if (stage == CONTROL_STAGE_DATA) { return audiod_control_complete(rhport, request); + } else { + // nothing to do } return true; @@ -1422,7 +1487,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // I assume here, that things above are handled by PHY // All transmission is done - what remains to do is to inform job was completed - tud_audio_int_xfer_cb(rhport); + tud_audio_int_done_cb(rhport); return true; } @@ -1473,7 +1538,7 @@ bool audiod_xfer_isr(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if (audio->ep_fb == ep_addr) { // Schedule a transmit with the new value if EP is not busy // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - audiod_fb_send(audio); + audiod_fb_send(func_id, true); return true; } #endif @@ -1485,30 +1550,72 @@ bool audiod_xfer_isr(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool audiod_set_fb_params_freq(audiod_function_t *audio, uint32_t sample_freq, uint32_t mclk_freq) { - // Check if frame interval is within sane limits - // The interval value n_frames was taken from the descriptors within audiod_set_interface() +static bool audiod_fb_params_prepare(uint8_t func_id, uint8_t alt) { + audiod_function_t *audio = &_audiod_fct[func_id]; - // n_frames_min is ceil(2^10 * f_s / f_m) for full speed and ceil(2^13 * f_s / f_m) for high speed - // this lower limit ensures the measures feedback value has sufficient precision - uint32_t const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13; - uint32_t const n_frame = (1UL << audio->feedback.frame_shift); + // Prepare feedback computation if endpoint is available + if (audio->ep_fb != 0) { + audio_feedback_params_t fb_param = {0}; - if ((((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame) { - TU_LOG1(" UAC2 feedback interval too small\r\n"); - TU_BREAKPOINT(); - return false; - } + tud_audio_feedback_params_cb(func_id, alt, &fb_param); + audio->feedback.compute_method = fb_param.method; - // Check if parameters really allow for a power of two division - if ((mclk_freq % sample_freq) == 0 && tu_is_power_of_two(mclk_freq / sample_freq)) { - audio->feedback.compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2; - audio->feedback.compute.power_of_2 = (uint8_t) (16 - (audio->feedback.frame_shift - 1) - tu_log2(mclk_freq / sample_freq)); - } else if (audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) { - audio->feedback.compute.float_const = (float) sample_freq / (float) mclk_freq * (1UL << (16 - (audio->feedback.frame_shift - 1))); - } else { - audio->feedback.compute.fixed.sample_freq = sample_freq; - audio->feedback.compute.fixed.mclk_freq = mclk_freq; + // Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame) + uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000; + audio->feedback.min_value = ((fb_param.sample_freq - 1) / frame_div) << 16; + audio->feedback.max_value = (fb_param.sample_freq / frame_div + 1) << 16; + + switch (fb_param.method) { + case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: + case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: + case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: { + // Check if frame interval is within sane limits + // The interval value n_frames was taken from the descriptors within audiod_set_interface() + + // n_frames_min is ceil(2^10 * f_s / f_m) for full speed and ceil(2^13 * f_s / f_m) for high speed + // this lower limit ensures the measures feedback value has sufficient precision + uint32_t const k = (TUSB_SPEED_FULL == tud_speed_get()) ? 10 : 13; + uint32_t const n_frame = (1UL << audio->feedback.frame_shift); + + if ((((1UL << k) * fb_param.sample_freq / fb_param.frequency.mclk_freq) + 1) > n_frame) { + TU_LOG1(" UAC2 feedback interval too small\r\n"); + TU_BREAKPOINT(); + return false; + } + + // Check if parameters really allow for a power of two division + if ((fb_param.frequency.mclk_freq % fb_param.sample_freq) == 0 && tu_is_power_of_two(fb_param.frequency.mclk_freq / fb_param.sample_freq)) { + audio->feedback.compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2; + audio->feedback.compute.power_of_2 = (uint8_t) (16 - (audio->feedback.frame_shift - 1) - tu_log2(fb_param.frequency.mclk_freq / fb_param.sample_freq)); + } else if (audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) { + audio->feedback.compute.float_const = (float) fb_param.sample_freq / (float) fb_param.frequency.mclk_freq * (1UL << (16 - (audio->feedback.frame_shift - 1))); + } else { + audio->feedback.compute.fixed.sample_freq = fb_param.sample_freq; + audio->feedback.compute.fixed.mclk_freq = fb_param.frequency.mclk_freq; + } + } break; + + case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: { + // Determine FIFO threshold + uint16_t fifo_threshold = fb_param.fifo_count.fifo_threshold ? fb_param.fifo_count.fifo_threshold : tu_fifo_depth(&audio->ep_out_ff) / 2; + audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_threshold; + audio->feedback.compute.fifo_count.fifo_lvl_avg = ((uint32_t) fifo_threshold) << 16; + // Avoid 64bit division + uint32_t nominal = ((fb_param.sample_freq / 100) << 16) / (frame_div / 100); + audio->feedback.compute.fifo_count.nom_value = nominal; + audio->feedback.compute.fifo_count.rate_const[0] = (uint16_t) ((audio->feedback.max_value - nominal) / fifo_threshold); + audio->feedback.compute.fifo_count.rate_const[1] = (uint16_t) ((nominal - audio->feedback.min_value) / fifo_threshold); + // On HS feedback is more sensitive since packet size can vary every MSOF, could cause instability + if (tud_speed_get() == TUSB_SPEED_HIGH) { + audio->feedback.compute.fifo_count.rate_const[0] /= 8; + audio->feedback.compute.fifo_count.rate_const[1] /= 8; + } + } break; + + // nothing to do + default: + break; + } } return true; @@ -1532,52 +1639,15 @@ static void audiod_fb_fifo_count_update(audiod_function_t *audio, uint16_t lvl_n feedback = audio->feedback.compute.fifo_count.nom_value - (ff_lvl - ff_thr) * rate[1]; } - if (feedback > audio->feedback.max_value) feedback = audio->feedback.max_value; - if (feedback < audio->feedback.min_value) feedback = audio->feedback.min_value; - audio->feedback.value = feedback; -} - -uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) { - audiod_function_t *audio = &_audiod_fct[func_id]; - uint32_t feedback; - - switch (audio->feedback.compute_method) { - case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - feedback = (cycles << audio->feedback.compute.power_of_2); - break; - - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: - feedback = (uint32_t) ((float) cycles * audio->feedback.compute.float_const); - break; - - case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: { - uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - (audio->feedback.frame_shift - 1)); - feedback = (uint32_t) (fb64 / audio->feedback.compute.fixed.mclk_freq); - } break; - - default: - return 0; + if (feedback > audio->feedback.max_value) { + feedback = audio->feedback.max_value; } - - // For Windows: https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/usb-2-0-audio-drivers - // The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1. - // This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot - // (audio slot = channel count samples). - if (feedback > audio->feedback.max_value) feedback = audio->feedback.max_value; - if (feedback < audio->feedback.min_value) feedback = audio->feedback.min_value; - - tud_audio_n_fb_set(func_id, feedback); - - return feedback; + if (feedback < audio->feedback.min_value) { + feedback = audio->feedback.min_value; + } + audio->feedback.value = feedback; } -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - _audiod_fct[func_id].feedback.value = feedback; - - return true; -} #endif TU_ATTR_FAST_FUNC void audiod_sof_isr(uint8_t rhport, uint32_t frame_count) { @@ -1645,24 +1715,27 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req } // Crop length - if (len > _audiod_fct[func_id].ctrl_buf_sz) len = _audiod_fct[func_id].ctrl_buf_sz; + if (len > sizeof(ctrl_buf)) len = sizeof(ctrl_buf); // Copy into buffer - TU_VERIFY(0 == tu_memcpy_s(_audiod_fct[func_id].ctrl_buf, _audiod_fct[func_id].ctrl_buf_sz, data, (size_t) len)); + TU_VERIFY(0 == tu_memcpy_s(ctrl_buf, sizeof(ctrl_buf), data, (size_t) len)); #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - // Find data for sampling_frequency_control - if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { - uint8_t entityID = TU_U16_HIGH(p_request->wIndex); - uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); - if (_audiod_fct[func_id].bclock_id_tx == entityID && ctrlSel == AUDIO_CS_CTRL_SAM_FREQ && p_request->bRequest == AUDIO_CS_REQ_CUR) { - _audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(_audiod_fct[func_id].ctrl_buf); + if (tud_audio_n_version(func_id) == 2) { + // Find data for sampling_frequency_control + if (p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS && p_request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE) { + uint8_t entityID = TU_U16_HIGH(p_request->wIndex); + uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); + if (_audiod_fct[func_id].bclock_id_tx == entityID && ctrlSel == AUDIO20_CS_CTRL_SAM_FREQ && p_request->bRequest == AUDIO20_CS_REQ_CUR) { + _audiod_fct[func_id].sample_rate_tx = tu_unaligned_read32(ctrl_buf); + audiod_calc_tx_packet_sz(&_audiod_fct[func_id]); + } } } #endif // Schedule transmit - return tud_control_xfer(rhport, p_request, (void *) _audiod_fct[func_id].ctrl_buf, len); + return tud_control_xfer(rhport, p_request, ctrl_buf, len); } // Verify an entity with the given ID exists and returns also the corresponding driver index @@ -1673,11 +1746,9 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * if (_audiod_fct[i].p_desc && ((tusb_desc_interface_t const *) _audiod_fct[i].p_desc)->bInterfaceNumber == itf) { // Get pointers after class specific AC descriptors and end of AC descriptors - entities are defined in between uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc);// Points to CS AC descriptor - uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *) p_desc)->wTotalLength + p_desc; p_desc = tu_desc_next(p_desc);// Get past CS AC descriptor - // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning - while (p_desc_end - p_desc > 0) { + while (_audiod_fct[i].p_desc_as - p_desc > 0) { // Entity IDs are always at offset 3 if (p_desc[3] == entityID) { *func_id = i; @@ -1693,10 +1764,10 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_fct[i].p_desc) { + if (_audiod_fct[i].p_desc != NULL) { // Get pointer at beginning and end uint8_t const *p_desc = _audiod_fct[i].p_desc; - uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; + uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)p_desc)->bInterfaceNumber == itf) { @@ -1718,8 +1789,7 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) { uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; // Advance past AC descriptors - EP we look for are streaming EPs - uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); - p_desc += ((audio_desc_cs_ac_interface_t const *) p_desc)->wTotalLength; + uint8_t const *p_desc = _audiod_fct[i].p_desc_as; // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning while (p_desc_end - p_desc > 0) { @@ -1739,20 +1809,34 @@ static void audiod_parse_flow_control_params(audiod_function_t *audio, uint8_t c p_desc = tu_desc_next(p_desc);// Exclude standard AS interface descriptor of current alternate interface descriptor - // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) { - audio->n_channels_tx = ((audio_desc_cs_as_interface_t const *) p_desc)->bNrChannels; - audio->format_type_tx = (audio_format_type_t) (((audio_desc_cs_as_interface_t const *) p_desc)->bFormatType); - // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) - p_desc = tu_desc_next(p_desc); - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const *) p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { - audio->n_bytes_per_sample_tx = ((audio_desc_type_I_format_t const *) p_desc)->bSubslotSize; + if (tud_audio_n_version(audiod_get_audio_fct_idx(audio)) == 1) { + p_desc = tu_desc_next(p_desc);// Exclude Class-Specific AS Interface Descriptor(4.5.2) to get to format type descriptor + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO10_CS_AS_INTERFACE_FORMAT_TYPE) { + audio->format_type_tx = ((audio10_desc_type_I_format_n_t(1) const *) p_desc)->bFormatType; + if (audio->format_type_tx == AUDIO10_FORMAT_TYPE_I) { + audio->n_channels_tx = ((audio10_desc_type_I_format_n_t(1) const *) p_desc)->bNrChannels; + audio->n_bytes_per_sample_tx = ((audio10_desc_type_I_format_n_t(1) const *) p_desc)->bSubFrameSize; + // Save sample rate - needed when EP doesn't support setting sample rate + audio->sample_rate_tx = tu_unaligned_read32(((audio10_desc_type_I_format_n_t(1) const *) p_desc)->tSamFreq) & 0x00FFFFFF; + } + } + } else { + // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO20_CS_AS_INTERFACE_AS_GENERAL) { + audio->n_channels_tx = ((audio20_desc_cs_as_interface_t const *) p_desc)->bNrChannels; + audio->format_type_tx = ((audio20_desc_cs_as_interface_t const *) p_desc)->bFormatType; + // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) + p_desc = tu_desc_next(p_desc); + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO20_CS_AS_INTERFACE_FORMAT_TYPE && ((audio20_desc_type_I_format_t const *) p_desc)->bFormatType == AUDIO20_FORMAT_TYPE_I) { + audio->n_bytes_per_sample_tx = ((audio20_desc_type_I_format_t const *) p_desc)->bSubslotSize; + } } } } static bool audiod_calc_tx_packet_sz(audiod_function_t *audio) { - TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I); + // AUDIO20_FORMAT_TYPE_I = AUDIO10_FORMAT_TYPE_I + TU_VERIFY(audio->format_type_tx == AUDIO20_FORMAT_TYPE_I); TU_VERIFY(audio->n_channels_tx); TU_VERIFY(audio->n_bytes_per_sample_tx); TU_VERIFY(audio->interval_tx); @@ -1787,22 +1871,22 @@ static bool audiod_calc_tx_packet_sz(audiod_function_t *audio) { return true; } -static uint16_t audiod_tx_packet_size(const uint16_t *norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_depth) { +static uint16_t audiod_tx_packet_size(const uint16_t *nominal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t fifo_threshold, uint16_t max_depth) { // Flow control need a FIFO size of at least 4*Navg - if (norminal_size[1] && norminal_size[1] <= fifo_depth * 4) { + if (nominal_size[1] && nominal_size[1] <= fifo_depth * 4) { // Use blackout to prioritize normal size packet static int ctrl_blackout = 0; uint16_t packet_size; - uint16_t slot_size = norminal_size[2] - norminal_size[1]; - if (data_count < norminal_size[0]) { + uint16_t slot_size = nominal_size[2] - nominal_size[1]; + if (data_count < nominal_size[0]) { // If you get here frequently, then your I2S clock deviation is too big ! packet_size = 0; - } else if (data_count < fifo_depth / 2 - slot_size && !ctrl_blackout) { - packet_size = norminal_size[0]; + } else if (data_count < (fifo_threshold - slot_size) && !ctrl_blackout) { + packet_size = nominal_size[0]; ctrl_blackout = 10; - } else if (data_count > fifo_depth / 2 + slot_size && !ctrl_blackout) { - packet_size = norminal_size[2]; - if (norminal_size[0] == norminal_size[1]) { + } else if (data_count > (fifo_threshold + slot_size) && !ctrl_blackout) { + packet_size = nominal_size[2]; + if (nominal_size[0] == nominal_size[1]) { // nav > INT(nav), eg. 44.1k, 88.2k ctrl_blackout = 0; } else { @@ -1810,7 +1894,7 @@ static uint16_t audiod_tx_packet_size(const uint16_t *norminal_size, uint16_t da ctrl_blackout = 10; } } else { - packet_size = norminal_size[1]; + packet_size = nominal_size[1]; if (ctrl_blackout) { ctrl_blackout--; } @@ -1825,11 +1909,8 @@ static uint16_t audiod_tx_packet_size(const uint16_t *norminal_size, uint16_t da #endif // No security checks here - internal function only which should always succeed -static uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio) { - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO; cnt++) { - if (&_audiod_fct[cnt] == audio) return cnt; - } - return 0; +static inline uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio) { + return (uint8_t) (audio - _audiod_fct); } #endif // (CFG_TUD_ENABLED && CFG_TUD_AUDIO) diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index fd47c649d..1e0c46915 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -37,35 +37,10 @@ // All sizes are in bytes! -#ifndef CFG_TUD_AUDIO_FUNC_1_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_DESC_LEN -#error You must tell the driver the length of the audio function descriptor including IAD descriptor -#endif -#endif - -// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors -#ifndef CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif - -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif -#endif - -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ -#error You must define an audio class control request buffer size! -#endif +// Size of control buffer used to receive and send control messages via EP0 - has to be big enough to hold your +// biggest request structure e.g. range requests with multiple intervals defined or cluster descriptors +#ifndef CFG_TUD_AUDIO_CTRL_BUF_SZ +#define CFG_TUD_AUDIO_CTRL_BUF_SZ 64 #endif // End point sizes IN BYTES - Limits: Full Speed <= 1023, High Speed <= 1024 @@ -167,7 +142,8 @@ #endif #endif -// (For TYPE-I format only) Flow control is necessary to allow IN ep send correct amount of data, unless it's a virtual device where data is perfectly synchronized to USB clock. +// (For TYPE-I format only) Flow control is necessary to allow IN ep send correct amount of data, unless it's a +// virtual device where data is perfectly synchronized to USB clock. #ifndef CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL #define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 #endif @@ -177,12 +153,6 @@ #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 0 // Feedback - 0 or 1 #endif -// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). -// Can be override by tud_audio_feedback_format_correction_cb() -#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION -#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 -#endif - // Enable/disable interrupt EP (required for notifying host of control changes) #ifndef CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP #define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0 // Feedback - 0 or 1 @@ -205,6 +175,7 @@ extern "C" { // CFG_TUD_AUDIO > 1 //--------------------------------------------------------------------+ bool tud_audio_n_mounted(uint8_t func_id); +uint8_t tud_audio_n_version(uint8_t func_id); #if CFG_TUD_AUDIO_ENABLE_EP_OUT uint16_t tud_audio_n_available (uint8_t func_id); @@ -217,6 +188,8 @@ tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); +uint16_t tud_audio_n_get_ep_in_fifo_threshold(uint8_t func_id); +void tud_audio_n_set_ep_in_fifo_threshold(uint8_t func_id, uint16_t threshold); #endif #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP @@ -227,6 +200,7 @@ bool tud_audio_int_n_write (uint8_t func_id, const audio_ // Application API (Interface0) //--------------------------------------------------------------------+ static inline bool tud_audio_mounted (void); +static inline uint8_t tud_audio_version (void); #if CFG_TUD_AUDIO_ENABLE_EP_OUT static inline uint16_t tud_audio_available (void); @@ -248,12 +222,15 @@ static inline bool tud_audio_int_write (const audio_interru #endif // Buffer control EP data and schedule a transmit -// This function is intended to be used if you do not have a persistent buffer or memory location available (e.g. non-local variables) and need to answer onto a -// get request. This function buffers your answer request frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. -// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer pointer in pointing. If you already have such -// available you may directly use 'tud_control_xfer(...)'. In this case data does not need to be copied into an additional buffer and you save some time. +// This function is intended to be used if you do not have a persistent buffer or memory location available +// (e.g. non-local variables) and need to answer onto a get request. This function buffers your answer request +// frame into the control buffer of the corresponding audio driver and schedules a transmit for sending it. +// Since transmission is triggered via interrupts, a persistent memory location is required onto which the buffer +// pointer in pointing. If you already have such available you may directly use 'tud_control_xfer(...)'. In this +// case data does not need to be copied into an additional buffer and you save some time. // If the request's wLength is zero, a status packet is sent instead. -bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); +bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, + void* data, uint16_t len); //--------------------------------------------------------------------+ // Application Callback API @@ -261,14 +238,18 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req #if CFG_TUD_AUDIO_ENABLE_EP_IN // Invoked in ISR context once an audio packet was sent successfully. -// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock), call tud_audio_write() in I2S receive callback. -bool tud_audio_tx_done_isr(uint8_t rhport, uint16_t n_bytes_sent, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock), +// call tud_audio_write() in I2S receive callback. +bool tud_audio_tx_done_isr(uint8_t rhport, uint16_t n_bytes_sent, uint8_t func_id, uint8_t ep_in, + uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT // Invoked in ISR context once an audio packet was received successfully. -// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock), call tud_audio_read() in I2S transmit callback. -bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock), +// call tud_audio_read() in I2S transmit callback. +bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, + uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -277,42 +258,55 @@ bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t fu // // Option 1 - AUDIO_FEEDBACK_METHOD_FIFO_COUNT // Feedback value is calculated within the audio driver by regulating the FIFO level to half fill. -// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, well tested -// (Windows, Linux, OSX) with a reliable result so far. -// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is introduced. +// Advantage: No SOF interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus +// less CPU load, well tested (Windows, Linux, OSX) with a reliable result so far. +// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is +// introduced. // // Option 2 - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED / AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT -// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from -// which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter). +// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information +// about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle +// count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter). // See tud_audio_set_fb_params() and tud_audio_feedback_update() -// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a smaller delay is possible. -// Disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. (The most critical point is the reading of the cycle counter value of f_m. -// It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced). -// Long-term drift could occur since error is accumulated. +// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a +// smaller delay is possible. +// Disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. (The most critical point +// is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, +// hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is +// introduced). Long-term drift will cause the FIFO under/overflow, you still needs to correct it somehow. // // Option 3 - manual -// Determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. -// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load. -// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay is introduced. +// Determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined +// e.g. from some fill status of some FIFO buffer. +// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus +// less CPU load. +// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay +// is introduced. -// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. +// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at +// FB endpoint interval till it's changed. // -// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set or tud_audio_feedback_format_correction_cb() -// return true, then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS. +// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus +// Specification Revision 2.0 5.12.4.2). For simplicity, this function always uses 16.16 format. For FS devices, +// the driver will automatically convert the value to 10.14 format. // -// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and it seems the -// driver can work with either format. +// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 +// devices. On Linux and it seems the driver can work with either format. // -// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value. +// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the +// feature is used, the user can not set the feedback value. // // Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec // Boiled down, the feedback value Ff = n_samples / (micro)frame. -// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 -// for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) -// The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K) -// feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames +// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames +// need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency +// e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is +// available and locked to f_s) +// The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where +// P = min( ceil(log2(f_m / f_s)), K) +// feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles +// within fb_n_frames bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); // Update feedback value with passed MCLK cycles since last time this update function is called. @@ -339,10 +333,12 @@ typedef struct { union { struct { uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on - }frequency; - + } frequency; + struct { + uint16_t fifo_threshold; // Target FIFO threshold level, default to half FIFO if not set + } fifo_count; }; -}audio_feedback_params_t; +} audio_feedback_params_t; // Invoked when needed to set feedback parameters void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param); @@ -352,13 +348,10 @@ void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedba // frame_number : current SOF count // interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); - -// (Full-Speed only) Callback to set feedback format correction is applied or not, -// default to CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION if not implemented. -bool tud_audio_feedback_format_correction_cb(uint8_t func_id); #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP +// Invoked when an interrupt notification transfer is complete void tud_audio_int_done_cb(uint8_t rhport); #endif @@ -397,6 +390,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_audio_mounted(void) { return tud_audio_n_mounted(0); } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_audio_version(void) { + return tud_audio_n_version(0); +} + #if CFG_TUD_AUDIO_ENABLE_EP_OUT TU_ATTR_ALWAYS_INLINE static inline uint16_t tud_audio_available(void) { @@ -431,6 +428,16 @@ TU_ATTR_ALWAYS_INLINE static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) { return tud_audio_n_get_ep_in_ff(0); } +TU_ATTR_ALWAYS_INLINE static inline uint16_t tud_audio_get_ep_in_fifo_threshold(void) +{ + return tud_audio_n_get_ep_in_fifo_threshold(0); +} + +TU_ATTR_ALWAYS_INLINE static inline void tud_audio_set_ep_in_fifo_threshold(uint16_t threshold) +{ + tud_audio_n_set_ep_in_fifo_threshold(0, threshold); +} + #endif #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP @@ -461,7 +468,7 @@ void audiod_sof_isr (uint8_t rhport, uint32_t frame_count); } #endif -#endif /* _TUSB_AUDIO_DEVICE_H_ */ +#endif /* TUSB_AUDIO_DEVICE_H_ */ /** @} */ /** @} */ diff --git a/src/class/bth/bth_device.c b/src/class/bth/bth_device.c index 3f1529cb6..b679d6ab6 100755 --- a/src/class/bth/bth_device.c +++ b/src/class/bth/bth_device.c @@ -67,7 +67,7 @@ static bool bt_tx_data(uint8_t ep, void *data, uint16_t len) { // skip if previous transfer not complete TU_VERIFY(!usbd_edpt_busy(rhport, ep)); - TU_ASSERT(usbd_edpt_xfer(rhport, ep, data, len)); + TU_ASSERT(usbd_edpt_xfer(rhport, ep, data, len, false)); return true; } @@ -169,7 +169,7 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_ itf_desc = (tusb_desc_interface_t const *) tu_desc_next(tu_desc_next(desc_ep)); // Prepare for incoming data from host - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0); + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE, false), 0); drv_len = hci_itf_size; @@ -272,7 +272,7 @@ bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, tud_bt_acl_data_received_cb(_btd_epbuf.epout_buf, xferred_bytes); // prepare for next data - TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE)); + TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE, false)); } else if (ep_addr == _btd_itf.ep_ev) { tud_bt_event_sent_cb((uint16_t) xferred_bytes); } else if (ep_addr == _btd_itf.ep_acl_in) { diff --git a/src/class/bth/bth_device.h b/src/class/bth/bth_device.h index 68f073bff..89a056dc8 100755 --- a/src/class/bth/bth_device.h +++ b/src/class/bth/bth_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_BTH_DEVICE_H_ -#define _TUSB_BTH_DEVICE_H_ +#ifndef TUSB_BTH_DEVICE_H_ +#define TUSB_BTH_DEVICE_H_ #include <common/tusb_common.h> #include <device/usbd.h> @@ -114,4 +114,4 @@ bool btd_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t r } #endif -#endif /* _TUSB_BTH_DEVICE_H_ */ +#endif /* TUSB_BTH_DEVICE_H_ */ diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 10ba16a7c..679723ba6 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -29,8 +29,8 @@ * Currently only Abstract Control Model subclass is supported * @{ */ -#ifndef _TUSB_CDC_H__ -#define _TUSB_CDC_H__ +#ifndef TUSB_CDC_H__ +#define TUSB_CDC_H__ #include "common/tusb_common.h" @@ -192,10 +192,10 @@ typedef enum { CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits } cdc_line_coding_stopbits_t; -#define CDC_LINE_CODING_STOP_BITS_TEXT(STOP_BITS) ( \ - STOP_BITS == CDC_LINE_CODING_STOP_BITS_1 ? "1" : \ - STOP_BITS == CDC_LINE_CODING_STOP_BITS_1_5 ? "1.5" : \ - STOP_BITS == CDC_LINE_CODING_STOP_BITS_2 ? "2" : "?" ) +#define CDC_LINE_CODING_STOP_BITS_TEXT(STOP_BITS) ( \ + (STOP_BITS) == CDC_LINE_CODING_STOP_BITS_1 ? "1" : \ + (STOP_BITS) == CDC_LINE_CODING_STOP_BITS_1_5 ? "1.5" : \ + (STOP_BITS) == CDC_LINE_CODING_STOP_BITS_2 ? "2" : "?" ) // TODO Backward compatible for typos. Maybe removed in the future release #define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1 @@ -211,11 +211,11 @@ typedef enum { } cdc_line_coding_parity_t; #define CDC_LINE_CODING_PARITY_CHAR(PARITY) ( \ - PARITY == CDC_LINE_CODING_PARITY_NONE ? 'N' : \ - PARITY == CDC_LINE_CODING_PARITY_ODD ? 'O' : \ - PARITY == CDC_LINE_CODING_PARITY_EVEN ? 'E' : \ - PARITY == CDC_LINE_CODING_PARITY_MARK ? 'M' : \ - PARITY == CDC_LINE_CODING_PARITY_SPACE ? 'S' : '?' ) + (PARITY) == CDC_LINE_CODING_PARITY_NONE ? 'N' : \ + (PARITY) == CDC_LINE_CODING_PARITY_ODD ? 'O' : \ + (PARITY) == CDC_LINE_CODING_PARITY_EVEN ? 'E' : \ + (PARITY) == CDC_LINE_CODING_PARITY_MARK ? 'M' : \ + (PARITY) == CDC_LINE_CODING_PARITY_SPACE ? 'S' : '?' ) //--------------------------------------------------------------------+ // Management Element Notification (Notification Endpoint) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f1c4a3bbf..9e62c6509 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -48,28 +48,23 @@ typedef struct { uint8_t rhport; uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - uint8_t ep_notify; uint8_t line_state; // Bit 0: DTR, Bit 1: RTS /*------------- From this point, data is not cleared by bus reset -------------*/ - char wanted_char; TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; + char wanted_char; - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; + struct { + tu_edpt_stream_t tx; + tu_edpt_stream_t rx; - OSAL_MUTEX_DEF(rx_ff_mutex); - OSAL_MUTEX_DEF(tx_ff_mutex); + uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; + uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; + } stream; } cdcd_interface_t; -#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) +#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, line_coding) typedef struct { TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE); @@ -81,110 +76,100 @@ typedef struct { } cdcd_epbuf_t; //--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; -CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; - -static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT(); - -static bool _prep_out_transaction(uint8_t itf) { - const uint8_t rhport = 0; - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY(tud_ready() && p_cdc->ep_out); - - uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_out)); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_cdc->rx_ff); - - if (available >= CFG_TUD_CDC_EP_BUFSIZE) { - return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE); - } else { - // Release endpoint since we don't make any transfer - usbd_edpt_release(p_cdc->rhport, p_cdc->ep_out); - return false; - } -} - -//--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { - (void) itf; - (void) wanted_char; + (void)itf; + (void)wanted_char; } TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_notify_complete_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - (void) itf; - (void) dtr; - (void) rts; + (void)itf; + (void)dtr; + (void)rts; } -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) { - (void) itf; - (void) p_line_coding; +TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, const cdc_line_coding_t *p_line_coding) { + (void)itf; + (void)p_line_coding; } TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { - (void) itf; - (void) duration_ms; + (void)itf; + (void)duration_ms; +} + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; +CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; +static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT(); + +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_cdc_itf(uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUD_CDC; idx++) { + const cdcd_interface_t *p_cdc = &_cdcd_itf[idx]; + if (ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr || + (ep_addr == p_cdc->ep_notify && ep_addr != 0)) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; } //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) { - TU_VERIFY(driver_cfg); + TU_VERIFY(driver_cfg != NULL); _cdcd_cfg = *driver_cfg; return true; } bool tud_cdc_n_ready(uint8_t itf) { - return tud_ready() && _cdcd_itf[itf].ep_in != 0 && _cdcd_itf[itf].ep_out != 0; + TU_VERIFY(itf < CFG_TUD_CDC); + TU_VERIFY(tud_ready()); + const cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + + const bool in_opened = tu_edpt_stream_is_opened(&p_cdc->stream.tx); + const bool out_opened = tu_edpt_stream_is_opened(&p_cdc->stream.rx); + return in_opened && out_opened; } bool tud_cdc_n_connected(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_CDC); + TU_VERIFY(tud_ready()); // DTR (bit 0) active is considered as connected - return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); + return tu_bit_test(_cdcd_itf[itf].line_state, 0); } uint8_t tud_cdc_n_get_line_state(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_CDC, 0); return _cdcd_itf[itf].line_state; } -void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) { +void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t *coding) { + TU_VERIFY(itf < CFG_TUD_CDC, ); (*coding) = _cdcd_itf[itf].line_coding; } #if CFG_TUD_CDC_NOTIFY bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *state) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf]; TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); @@ -196,12 +181,13 @@ bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *st notify_msg->request.wLength = sizeof(cdc_notify_uart_state_t); notify_msg->serial_state = *state; - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t)); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t), false); } bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf]; TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); @@ -213,11 +199,12 @@ bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed notify_msg->request.wLength = sizeof(cdc_notify_conn_speed_change_t); notify_msg->conn_speed_change = *conn_speed_change; - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t)); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t), false); } #endif void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { + TU_VERIFY(itf < CFG_TUD_CDC, ); _cdcd_itf[itf].wanted_char = wanted; } @@ -225,77 +212,53 @@ void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { // READ API //--------------------------------------------------------------------+ uint32_t tud_cdc_n_available(uint8_t itf) { - return tu_fifo_count(&_cdcd_itf[itf].rx_ff); + TU_VERIFY(itf < CFG_TUD_CDC, 0); + return tu_edpt_stream_read_available(&_cdcd_itf[itf].stream.rx); } uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - _prep_out_transaction(itf); - return num_read; + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_read(p_cdc->rhport, &p_cdc->stream.rx, buffer, bufsize); } -bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { - return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); +bool tud_cdc_n_peek(uint8_t itf, uint8_t *chr) { + TU_VERIFY(itf < CFG_TUD_CDC); + return tu_edpt_stream_peek(&_cdcd_itf[itf].stream.rx, chr); } void tud_cdc_n_read_flush(uint8_t itf) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(itf); + TU_VERIFY(itf < CFG_TUD_CDC, ); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + tu_edpt_stream_clear(&p_cdc->stream.rx); + tu_edpt_stream_read_xfer(p_cdc->rhport, &p_cdc->stream.rx); } //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t wr_count = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - - // flush if queue more than packet size - if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE - #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE - || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size - #endif - ) { - tud_cdc_n_write_flush(itf); - } - - return wr_count; + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write(p_cdc->rhport, &p_cdc->stream.tx, buffer, bufsize); } uint32_t tud_cdc_n_write_flush(uint8_t itf) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - TU_VERIFY(tud_ready(), 0); // Skip if usb is not ready yet - - // No data to send - if (!tu_fifo_count(&p_cdc->tx_ff)) { - return 0; - } - - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_in), 0); // Claim the endpoint - - // Pull data from FIFO - const uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); - - if (count) { - TU_ASSERT(usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_in, p_epbuf->epin, count), 0); - return count; - } else { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(p_cdc->rhport, p_cdc->ep_in); - return 0; - } + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write_xfer(p_cdc->rhport, &p_cdc->stream.tx); } uint32_t tud_cdc_n_write_available(uint8_t itf) { - return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write_available(p_cdc->rhport, &p_cdc->stream.tx); } bool tud_cdc_n_write_clear(uint8_t itf) { - return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_clear(&p_cdc->stream.tx); } //--------------------------------------------------------------------+ @@ -304,7 +267,8 @@ bool tud_cdc_n_write_clear(uint8_t itf) { void cdcd_init(void) { tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { - cdcd_interface_t* p_cdc = &_cdcd_itf[i]; + cdcd_interface_t *p_cdc = &_cdcd_itf[i]; + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i]; p_cdc->wanted_char = (char) -1; @@ -314,44 +278,23 @@ void cdcd_init(void) { p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; - // Config RX fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + tu_edpt_stream_init(&p_cdc->stream.rx, false, false, false, p_cdc->stream.rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, + p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE); // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not // know if data is actually polled by terminal. This way the most current data is prioritized. // Default: is overwritable - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, _cdcd_cfg.tx_overwritabe_if_not_connected); - - #if OSAL_MUTEX_REQUIRED - osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex); - osal_mutex_t mutex_wr = osal_mutex_create(&p_cdc->tx_ff_mutex); - TU_ASSERT(mutex_rd != NULL && mutex_wr != NULL, ); - - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, mutex_rd); - tu_fifo_config_mutex(&p_cdc->tx_ff, mutex_wr, NULL); - #endif + tu_edpt_stream_init(&p_cdc->stream.tx, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, + p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); } } bool cdcd_deinit(void) { - #if OSAL_MUTEX_REQUIRED - for(uint8_t i=0; i<CFG_TUD_CDC; i++) { + for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; - osal_mutex_t mutex_rd = p_cdc->rx_ff.mutex_rd; - osal_mutex_t mutex_wr = p_cdc->tx_ff.mutex_wr; - - if (mutex_rd) { - osal_mutex_delete(mutex_rd); - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, NULL); - } - - if (mutex_wr) { - osal_mutex_delete(mutex_wr); - tu_fifo_config_mutex(&p_cdc->tx_ff, NULL, NULL); - } + tu_edpt_stream_deinit(&p_cdc->stream.rx); + tu_edpt_stream_deinit(&p_cdc->stream.tx); } - #endif - return true; } @@ -360,74 +303,85 @@ void cdcd_reset(uint8_t rhport) { for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; - tu_memclr(p_cdc, ITF_MEM_RESET_SIZE); - if (!_cdcd_cfg.rx_persistent) { - tu_fifo_clear(&p_cdc->rx_ff); - } - if (!_cdcd_cfg.tx_persistent) { - tu_fifo_clear(&p_cdc->tx_ff); - } - tu_fifo_set_overwritable(&p_cdc->tx_ff, _cdcd_cfg.tx_overwritabe_if_not_connected); + + tu_fifo_set_overwritable(&p_cdc->stream.tx.ff, _cdcd_cfg.tx_overwritabe_if_not_connected); // back to default + tu_edpt_stream_close(&p_cdc->stream.rx); + tu_edpt_stream_close(&p_cdc->stream.tx); } } uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) { // Only support ACM subclass - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); + TU_VERIFY(TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, + 0); - // Find available interface - cdcd_interface_t* p_cdc; - uint8_t cdc_id; - for (cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) { - p_cdc = &_cdcd_itf[cdc_id]; - if (p_cdc->ep_in == 0) { - break; - } - } + const uint8_t cdc_id = find_cdc_itf(0); // Find available interface TU_ASSERT(cdc_id < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[cdc_id]; //------------- Control Interface -------------// p_cdc->rhport = rhport; p_cdc->itf_num = itf_desc->bInterfaceNumber; - uint16_t drv_len = sizeof(tusb_desc_interface_t); - const uint8_t* p_desc = tu_desc_next(itf_desc); + const uint8_t *p_desc = (const uint8_t *)itf_desc; + const uint8_t *desc_end = p_desc + max_len; - // Communication Functional Descriptors - while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) { - drv_len += tu_desc_len(p_desc); + // Skip all class-specific descriptor + p_desc = tu_desc_next(itf_desc); + while (tu_desc_in_bounds(p_desc, desc_end) && TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) { p_desc = tu_desc_next(p_desc); } + // notification endpoint (optional) if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { - // notification endpoint const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); p_cdc->ep_notify = desc_ep->bEndpointAddress; - drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - //------------- Data Interface (if any) -------------// - if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((const tusb_desc_interface_t*) p_desc)->bInterfaceClass)) { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + //------------- Data Interface (optional) -------------// + if (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) { + const tusb_desc_interface_t *data_itf_desc = (const tusb_desc_interface_t *)p_desc; + if (TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass) { + for (uint8_t e = 0; e < data_itf_desc->bNumEndpoints; e++) { + if (!tu_desc_in_bounds(p_desc, desc_end)) { + break; + } + p_desc = tu_desc_next(p_desc); - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); - drv_len += 2 * sizeof(tusb_desc_endpoint_t); - } + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { + tu_edpt_stream_t *stream_tx = &p_cdc->stream.tx; - // Prepare for incoming data - _prep_out_transaction(cdc_id); + tu_edpt_stream_open(stream_tx, desc_ep); + if (_cdcd_cfg.tx_persistent) { + tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data + } else { + tu_edpt_stream_clear(stream_tx); + } + } else { + tu_edpt_stream_t *stream_rx = &p_cdc->stream.rx; - return drv_len; + tu_edpt_stream_open(stream_rx, desc_ep); + if (!_cdcd_cfg.rx_persistent) { + tu_edpt_stream_clear(stream_rx); + } + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare for incoming data + } + } + + p_desc = tu_desc_next(p_desc); + } + } + + return (uint16_t)(p_desc - (const uint8_t *)itf_desc); } // Invoked when a control transfer occurred on an interface of this class @@ -456,6 +410,8 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); } else if (stage == CONTROL_STAGE_ACK) { tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + } else { + // nothing to do } break; @@ -482,15 +438,15 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ // If enabled: fifo overwriting is disabled if DTR bit is set and vice versa if (_cdcd_cfg.tx_overwritabe_if_not_connected) { - tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); + tu_fifo_set_overwritable(&p_cdc->stream.tx.ff, !dtr); } else { - tu_fifo_set_overwritable(&p_cdc->tx_ff, false); + tu_fifo_set_overwritable(&p_cdc->stream.tx.ff, false); } TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - - // Invoke callback - tud_cdc_line_state_cb(itf, dtr, rts); + tud_cdc_line_state_cb(itf, dtr, rts); // invoke callback + } else { + // nothing to do } break; @@ -500,6 +456,8 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } else if (stage == CONTROL_STAGE_ACK) { TU_LOG_DRV(" Send Break\r\n"); tud_cdc_send_break_cb(itf, request->wValue); + } else { + // nothing to do } break; @@ -511,58 +469,45 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) result; + (void)result; - uint8_t itf; - cdcd_interface_t* p_cdc; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_CDC; itf++) { - p_cdc = &_cdcd_itf[itf]; - if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in) || (ep_addr == p_cdc->ep_notify)) { - break; - } - } + uint8_t itf = find_cdc_itf(ep_addr); TU_ASSERT(itf < CFG_TUD_CDC); - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + tu_edpt_stream_t *stream_rx = &p_cdc->stream.rx; + tu_edpt_stream_t *stream_tx = &p_cdc->stream.tx; - // Received new data - if (ep_addr == p_cdc->ep_out) { - tu_fifo_write_n(&p_cdc->rx_ff, p_epbuf->epout, (uint16_t) xferred_bytes); + // Received new data, move to fifo + if (ep_addr == stream_rx->ep_addr) { + tu_edpt_stream_read_xfer_complete(stream_rx, xferred_bytes); - // Check for wanted char and invoke callback if needed - if (((signed char) p_cdc->wanted_char) != -1) { + // Check for wanted char and invoke wanted callback (multiple times if multiple wanted received) + if (((signed char)p_cdc->wanted_char) != -1) { for (uint32_t i = 0; i < xferred_bytes; i++) { - if ((p_cdc->wanted_char == p_epbuf->epout[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) { + if ((p_cdc->wanted_char == (char)stream_rx->ep_buf[i]) && !tu_edpt_stream_empty(stream_rx)) { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } - // invoke receive callback (if there is still data) - if (!tu_fifo_empty(&p_cdc->rx_ff)) { + // invoke receive callback if there is still data + if (!tu_edpt_stream_empty(stream_rx)) { tud_cdc_rx_cb(itf); } - // prepare for OUT transaction - _prep_out_transaction(itf); + tu_edpt_stream_read_xfer(rhport, stream_rx); // prepare for more data } // Data sent to host, we continue to fetch from tx fifo to send. // Note: This will cause incorrect baudrate set in line coding. // Though maybe the baudrate is not really important !!! - if (ep_addr == p_cdc->ep_in) { + if (ep_addr == stream_tx->ep_addr) { // invoke transmit callback to possibly refill tx fifo tud_cdc_tx_complete_cb(itf); - if (0 == tud_cdc_n_write_flush(itf)) { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP Packet size and not zero - if (!tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) { - if (usbd_edpt_claim(rhport, p_cdc->ep_in)) { - TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0)); - } - } + if (0 == tu_edpt_stream_write_xfer(rhport, stream_tx)) { + // If there is no data left, a ZLP should be sent if needed + tu_edpt_stream_write_zlp_if_needed(rhport, stream_tx, xferred_bytes); } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 9673b9807..6f21af4f3 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -53,15 +53,16 @@ // Driver Configuration //--------------------------------------------------------------------+ typedef struct TU_ATTR_PACKED { - uint8_t rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect - uint8_t tx_persistent : 1; // keep tx fifo data even with reset or disconnect - uint8_t tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten + bool rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect + bool tx_persistent : 1; // keep tx fifo data even with reset or disconnect + bool tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten } tud_cdc_configure_t; +TU_VERIFY_STATIC(sizeof(tud_cdc_configure_t) == 1, "size is not correct"); #define TUD_CDC_CONFIGURE_DEFAULT() { \ - .rx_persistent = 0, \ - .tx_persistent = 0, \ - .tx_overwritabe_if_not_connected = 1, \ + .rx_persistent = false, \ + .tx_persistent = false, \ + .tx_overwritabe_if_not_connected = true, \ } // Configure CDC driver behavior @@ -257,4 +258,4 @@ bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t re } #endif -#endif /* _TUSB_CDC_DEVICE_H_ */ +#endif /* TUSB_CDC_DEVICE_H_ */ diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index beef03eff..35717ddf6 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -298,6 +298,7 @@ TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial d //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static bool open_ep_stream_pair(cdch_interface_t *p_cdc, const tusb_desc_endpoint_t *desc_ep); TU_ATTR_ALWAYS_INLINE static inline cdch_interface_t * get_itf(uint8_t idx) { TU_ASSERT(idx < CFG_TUH_CDC, NULL); @@ -364,7 +365,7 @@ static cdch_interface_t* get_itf_by_xfer(const tuh_xfer_t * xfer) { #endif default: - break; + break; // unknown driver } } } @@ -389,8 +390,6 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons return NULL; } -static bool open_ep_stream_pair(cdch_interface_t * p_cdc , tusb_desc_endpoint_t const *desc_ep); - //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ @@ -519,7 +518,7 @@ bool tuh_cdc_read_clear (uint8_t idx) { TU_VERIFY(p_cdc); bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx); - tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); + (void)tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); return ret; } @@ -602,7 +601,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, p_cdc->requested_line.coding = *line_coding; p_cdc->user_complete_cb = complete_cb; - if (driver->set_line_coding) { + if (driver->set_line_coding != NULL) { // driver support set_line_coding request TU_VERIFY(driver->set_line_coding(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -611,7 +610,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, } } else { // driver does not support set_line_coding and need 2 stage to set baudrate and data format separately - if (complete_cb) { + if (complete_cb != NULL) { // non-blocking TU_VERIFY(driver->set_baudrate(p_cdc, cdch_set_line_coding_stage1_baudrate_complete, user_data)); } else { @@ -619,7 +618,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, xfer_result_t result = XFER_RESULT_INVALID; TU_VERIFY(driver->set_baudrate(p_cdc, NULL, (uintptr_t) &result)); - if (user_data) { + if (user_data != 0) { *((xfer_result_t *) user_data) = result; } TU_VERIFY(result == XFER_RESULT_SUCCESS); @@ -627,7 +626,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, result = XFER_RESULT_INVALID; TU_VERIFY(driver->set_data_format(p_cdc, NULL, (uintptr_t) &result)); - if (user_data) { + if (user_data != 0) { *((xfer_result_t *) user_data) = result; } TU_VERIFY(result == XFER_RESULT_SUCCESS); @@ -648,13 +647,10 @@ bool cdch_init(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t *p_cdc = &cdch_data[i]; cdch_epbuf_t *epbuf = &cdch_epbuf[i]; - tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, - p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, - epbuf->tx, CFG_TUH_CDC_TX_EPSIZE); - - tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, - p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, - epbuf->rx, CFG_TUH_CDC_RX_EPSIZE); + TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, + epbuf->tx, CFG_TUH_CDC_TX_EPSIZE)); + TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, p_cdc->stream.rx_ff_buf, + CFG_TUH_CDC_RX_BUFSIZE, epbuf->rx, CFG_TUH_CDC_RX_EPSIZE)); } return true; @@ -663,8 +659,8 @@ bool cdch_init(void) { bool cdch_deinit(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t *p_cdc = &cdch_data[i]; - tu_edpt_stream_deinit(&p_cdc->stream.tx); - tu_edpt_stream_deinit(&p_cdc->stream.rx); + (void)tu_edpt_stream_deinit(&p_cdc->stream.tx); + (void)tu_edpt_stream_deinit(&p_cdc->stream.rx); } return true; } @@ -674,11 +670,9 @@ void cdch_close(uint8_t daddr) { cdch_interface_t *p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { TU_LOG_CDC(p_cdc, "close"); + tuh_cdc_umount_cb(idx); // invoke callback - // Invoke application callback - tuh_cdc_umount_cb(idx); - - p_cdc->daddr = 0; + p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; p_cdc->mounted = false; tu_edpt_stream_close(&p_cdc->stream.tx); @@ -696,13 +690,12 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT(p_cdc); if (ep_addr == p_cdc->stream.tx.ep_addr) { - // invoke tx complete callback to possibly refill tx fifo - tuh_cdc_tx_complete_cb(idx); + tuh_cdc_tx_complete_cb(idx); // invoke transmit complete callback if (0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx)) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero - tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); + (void)tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); } } else if (ep_addr == p_cdc->stream.rx.ep_addr) { #if CFG_TUH_CDC_FTDI @@ -718,7 +711,6 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t #endif { tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - tuh_cdc_rx_cb(idx); // invoke receive callback } @@ -727,7 +719,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t } else if (ep_addr == p_cdc->ep_notif) { // TODO handle notification endpoint } else { - TU_ASSERT(false); + return false; } return true; @@ -736,20 +728,17 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ - static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t const *desc_ep) { for (size_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); + tu_edpt_stream_t *stream = + (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx; + tu_edpt_stream_open(stream, desc_ep); + tu_edpt_stream_clear(stream); - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - tu_edpt_stream_open(&p_cdc->stream.rx, desc_ep); - } else { - tu_edpt_stream_open(&p_cdc->stream.tx, desc_ep); - } - - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep); + desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(desc_ep); } return true; @@ -777,6 +766,8 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d } } } + } else { + // not supported class } return false; @@ -830,6 +821,7 @@ static void cdch_process_set_config(tuh_xfer_t *xfer) { } } +// return false if there is no active transfer static bool set_line_state_on_enum(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { enum { ENUM_SET_LINE_CODING = 0, @@ -894,7 +886,7 @@ static void cdch_internal_control_complete(tuh_xfer_t *xfer) { // Invoke application callback xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -910,7 +902,7 @@ static void cdch_set_line_coding_stage1_baudrate_complete(tuh_xfer_t *xfer) { TU_ASSERT(driver->set_data_format(p_cdc, cdch_set_line_coding_stage2_data_format_complete, xfer->user_data),); } else { xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -926,7 +918,7 @@ static void cdch_set_line_coding_stage2_data_format_complete(tuh_xfer_t *xfer) { } xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -950,12 +942,12 @@ static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *x break; default: - break; + break; // unknown request } } static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm.capability.support_line_request); + TU_VERIFY(p_cdc->acm.capability.support_line_request != 0); const tusb_control_request_t request = { .bmRequestType_bit = { @@ -982,7 +974,7 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co } static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm.capability.support_line_request); + TU_VERIFY(p_cdc->acm.capability.support_line_request != 0); TU_VERIFY((p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8) || p_cdc->requested_line.coding.data_bits == 16); @@ -1136,7 +1128,6 @@ static inline bool ftdi_sio_reset(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet // internal control complete to update state such as line state, line_coding static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t *xfer) { - TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); const tusb_control_request_t * setup = xfer->setup; if (xfer->result == XFER_RESULT_SUCCESS) { if (setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && @@ -1168,10 +1159,10 @@ static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint32_t index_value = ftdi_get_divisor(p_cdc); - TU_VERIFY(index_value); + TU_VERIFY(index_value != 0); uint16_t value = (uint16_t) index_value; uint16_t index = (uint16_t) (index_value >> 16); - if (p_cdc->ftdi.channel) { + if (p_cdc->ftdi.channel != 0) { index = (uint16_t) ((index << 8) | p_cdc->ftdi.channel); } @@ -1365,7 +1356,7 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { uint8_t divfrac[8] = {0, 3, 2, 4, 1, 5, 6, 7}; uint32_t divisor; /* divisor shifted 3 bits to the left */ - uint32_t divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); + uint32_t divisor3 = tu_div_round_nearest(base, 2 * baud); divisor = divisor3 >> 3; divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; /* Deal with special cases for highest baud rates. */ @@ -1373,6 +1364,8 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { divisor = 0; } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } else { + // nothing to do } return divisor; } @@ -1387,7 +1380,7 @@ static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) { uint32_t divisor3; /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ - divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud); + divisor3 = tu_div_round_nearest(8 * base, 10 * baud); divisor = divisor3 >> 3; divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; @@ -1396,12 +1389,13 @@ static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) { divisor = 0; } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } else { + // nothing to do } - /* - * Set this bit to turn off a divide by 2.5 on baud rate generator + + /* Set this bit to turn off a divide by 2.5 on baud rate generator * This enables baud rates up to 12Mbaud but cannot reach below 1200 - * baud with this bit set - */ + * baud with this bit set */ divisor |= 0x00020000; return divisor; } @@ -1413,7 +1407,7 @@ static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) { static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { uint32_t baud = p_cdc->requested_line.coding.bit_rate; uint32_t div_value = 0; - TU_VERIFY(baud); + TU_VERIFY(baud != 0); switch (p_cdc->ftdi.chip_type) { case FTDI_UNKNOWN: @@ -1553,7 +1547,8 @@ static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; break; - default: break; + default: + break; // unsupported request } } @@ -1714,7 +1709,8 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; break; - default: break; + default: + break; // unsupported } break; @@ -1722,19 +1718,20 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.control_state = p_cdc->requested_line.control_state; break; - default: break; + default: + break; // unsupported request } } static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { const uint8_t lcr = ch34x_get_lcr(p_cdc); - TU_VERIFY(lcr); + TU_VERIFY(lcr > 0); return ch34x_write_reg(p_cdc, CH32X_REG16_LCR2_LCR, lcr, complete_cb, user_data); } static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { const uint16_t div_ps = ch34x_get_divisor_prescaler(p_cdc); - TU_VERIFY(div_ps); + TU_VERIFY(div_ps > 0); return ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data); } @@ -1917,7 +1914,8 @@ static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE | CH34X_LCR_PAR_EVEN; break; - default: break; + default: + break; // invalid parity } // 1.5 stop bits not supported @@ -2000,13 +1998,15 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_c // return pl2303_set_request(p_cdc, PL2303_BREAK_REQUEST, PL2303_BREAK_REQUEST_TYPE, state, 0, NULL, 0); //} -static inline int pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool +pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { /* we don't care if it wasn't halted first. in fact some devices * (like some ibmcam model 1 units) seem to expect hosts to make * this request for iso endpoints, which can't halt! */ - return pl2303_set_request(p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, - NULL, 0, complete_cb, user_data); + return pl2303_set_request( + p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, NULL, 0, + complete_cb, user_data); } //------------- Driver API -------------// @@ -2131,10 +2131,9 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) if (type == PL2303_TYPE_NEED_SUPPORTS_HX_STATUS) { TU_ASSERT(pl2303_supports_hx_status(p_cdc, cdch_process_set_config, CONFIG_PL2303_READ1)); break; - } else { - // no transfer triggered and continue with CONFIG_PL2303_READ1 - TU_ATTR_FALLTHROUGH; } + // no transfer triggered and continue with CONFIG_PL2303_READ1 + TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ1: // get supports_hx_status, type and quirks (step 2), do special read @@ -2379,10 +2378,12 @@ static pl2303_type_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { return PL2303_TYPE_HXN; default: - break; + break; // unknown device } break; - default: break; + + default: + break; // unknown device } TU_LOG_CDC(p_cdc, "unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); @@ -2444,8 +2445,9 @@ static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_B */ baseline = 12000000 * 32; mantissa = baseline / baud; - if (mantissa == 0) + if (mantissa == 0) { mantissa = 1; /* Avoid dividing by zero if baud > 32 * 12M. */ + } exponent = 0; while (mantissa >= 512) { if (exponent < 7) { @@ -2517,7 +2519,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ * Use direct method for supported baud rates, otherwise use divisors. * Newer chip types do not support divisor encoding. */ - if (type_data->no_divisors) { + if (type_data->no_divisors != 0) { baud_sup = baud; } else { baud_sup = pl2303_get_supported_baud_rate(baud); @@ -2525,7 +2527,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ if (baud == baud_sup) { baud = pl2303_encode_baud_rate_direct(buf, baud); - } else if (type_data->alt_divisors) { + } else if (type_data->alt_divisors != 0) { baud = pl2303_encode_baud_rate_divisor_alt(buf, baud); } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index bf6711d7e..e8637beac 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_CDC_HOST_H_ -#define _TUSB_CDC_HOST_H_ +#ifndef TUSB_CDC_HOST_H_ +#define TUSB_CDC_HOST_H_ #include "cdc.h" @@ -255,4 +255,4 @@ void cdch_close (uint8_t dev_addr); } #endif -#endif /* _TUSB_CDC_HOST_H_ */ +#endif /* TUSB_CDC_HOST_H_ */ diff --git a/src/class/cdc/cdc_rndis.h b/src/class/cdc/cdc_rndis.h index ad153e0ac..fbbd43206 100644 --- a/src/class/cdc/cdc_rndis.h +++ b/src/class/cdc/cdc_rndis.h @@ -30,8 +30,8 @@ * \defgroup CDC_RNDIS_Common Common Definitions * @{ */ -#ifndef _TUSB_CDC_RNDIS_H_ -#define _TUSB_CDC_RNDIS_H_ +#ifndef TUSB_CDC_RNDIS_H_ +#define TUSB_CDC_RNDIS_H_ #include "cdc.h" @@ -295,7 +295,7 @@ typedef enum } #endif -#endif /* _TUSB_CDC_RNDIS_H_ */ +#endif /* TUSB_CDC_RNDIS_H_ */ /** @} */ /** @} */ diff --git a/src/class/cdc/cdc_rndis_host.h b/src/class/cdc/cdc_rndis_host.h index bb431ec1f..e70d27f79 100644 --- a/src/class/cdc/cdc_rndis_host.h +++ b/src/class/cdc/cdc_rndis_host.h @@ -28,8 +28,8 @@ * \defgroup CDC_RNSID_Host Host * @{ */ -#ifndef _TUSB_CDC_RNDIS_HOST_H_ -#define _TUSB_CDC_RNDIS_HOST_H_ +#ifndef TUSB_CDC_RNDIS_HOST_H_ +#define TUSB_CDC_RNDIS_HOST_H_ #include "common/tusb_common.h" #include "host/usbh.h" @@ -58,6 +58,6 @@ void rndish_close(uint8_t dev_addr); } #endif -#endif /* _TUSB_CDC_RNDIS_HOST_H_ */ +#endif /* TUSB_CDC_RNDIS_HOST_H_ */ /** @} */ diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h index 8abf74f11..9bd56cef4 100644 --- a/src/class/cdc/serial/ftdi_sio.h +++ b/src/class/cdc/serial/ftdi_sio.h @@ -215,17 +215,4 @@ typedef struct ftdi_private { #define FTDI_NOT_POSSIBLE -1 #define FTDI_REQUESTED -2 -// division and round function overtaken from math.h -#define DIV_ROUND_CLOSEST(x, divisor)( \ -{ \ - typeof(x) __x = x; \ - typeof(divisor) __d = divisor; \ - (((typeof(x))-1) > 0 || \ - ((typeof(divisor))-1) > 0 || \ - (((__x) > 0) == ((__d) > 0))) ? \ - (((__x) + ((__d) / 2)) / (__d)) : \ - (((__x) - ((__d) / 2)) / (__d)); \ -} \ -) - #endif //TUSB_FTDI_SIO_H diff --git a/src/class/dfu/dfu.h b/src/class/dfu/dfu.h index 114c827b8..8cd63656a 100644 --- a/src/class/dfu/dfu.h +++ b/src/class/dfu/dfu.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DFU_H_ -#define _TUSB_DFU_H_ +#ifndef TUSB_DFU_H_ +#define TUSB_DFU_H_ #include "common/tusb_common.h" @@ -116,4 +116,4 @@ TU_VERIFY_STATIC( sizeof(dfu_status_response_t) == 6, "size is not correct"); } #endif -#endif /* _TUSB_DFU_H_ */ +#endif /* TUSB_DFU_H_ */ diff --git a/src/class/dfu/dfu_device.c b/src/class/dfu/dfu_device.c index 0d2b63b57..d3cc53918 100644 --- a/src/class/dfu/dfu_device.c +++ b/src/class/dfu/dfu_device.c @@ -50,21 +50,17 @@ typedef struct { uint8_t attrs; uint8_t alt; + uint8_t state; + uint8_t status; - dfu_state_t state; - dfu_status_t status; - - bool flashing_in_progress; + bool flashing_in_progress; uint16_t block; uint16_t length; } dfu_state_ctx_t; -// Only a single dfu state is allowed static dfu_state_ctx_t _dfu_ctx; -CFG_TUD_MEM_SECTION static struct { - TUD_EPBUF_DEF(transfer_buf, CFG_TUD_DFU_XFER_BUFSIZE); -} _dfu_epbuf; +TU_ATTR_ALIGNED(4) uint8_t _transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE]; static void reset_state(void) { _dfu_ctx.state = DFU_IDLE; @@ -253,6 +249,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control tud_control_status(rhport, request); } else if (stage == CONTROL_STAGE_ACK) { tud_dfu_detach_cb(); + } else { + // nothing to do } break; @@ -275,6 +273,8 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control tud_control_status(rhport, request); } else if (stage == CONTROL_STAGE_ACK) { tud_dfu_abort_cb(_dfu_ctx.alt); + } else { + // nothing to do } break; @@ -283,10 +283,10 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD); TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE); - const uint16_t xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_epbuf.transfer_buf, + const uint16_t xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _transfer_buf, request->wLength); - return tud_control_xfer(rhport, request, _dfu_epbuf.transfer_buf, xfer_len); + return tud_control_xfer(rhport, request, _transfer_buf, xfer_len); } break; @@ -303,10 +303,10 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control _dfu_ctx.block = request->wValue; _dfu_ctx.length = request->wLength; - if (request->wLength) { + if (request->wLength > 0) { // Download with payload -> transition to DOWNLOAD SYNC _dfu_ctx.state = DFU_DNLOAD_SYNC; - return tud_control_xfer(rhport, request, _dfu_epbuf.transfer_buf, request->wLength); + return tud_control_xfer(rhport, request, _transfer_buf, request->wLength); } else { // Download is complete -> transition to MANIFEST SYNC _dfu_ctx.state = DFU_MANIFEST_SYNC; @@ -352,6 +352,8 @@ void tud_dfu_finish_flashing(uint8_t status) { _dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT) ? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET; + } else { + // nothing to do } } else { // failed while flashing, move to dfuError @@ -378,10 +380,12 @@ static bool process_download_get_status(uint8_t rhport, uint8_t stage, const tus } else if (stage == CONTROL_STAGE_ACK) { if (_dfu_ctx.flashing_in_progress) { _dfu_ctx.state = DFU_DNBUSY; - tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_epbuf.transfer_buf, _dfu_ctx.length); + tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _transfer_buf, _dfu_ctx.length); } else { _dfu_ctx.state = DFU_DNLOAD_IDLE; } + } else { + // nothing to do } return true; @@ -409,6 +413,8 @@ static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, const tus } else { _dfu_ctx.state = DFU_IDLE; } + } else { + // nothing to do } return true; diff --git a/src/class/dfu/dfu_device.h b/src/class/dfu/dfu_device.h index e59e61ce9..b22b4c450 100644 --- a/src/class/dfu/dfu_device.h +++ b/src/class/dfu/dfu_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DFU_DEVICE_H_ -#define _TUSB_DFU_DEVICE_H_ +#ifndef TUSB_DFU_DEVICE_H_ +#define TUSB_DFU_DEVICE_H_ #include "dfu.h" @@ -96,4 +96,4 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_r } #endif -#endif /* _TUSB_DFU_MODE_DEVICE_H_ */ +#endif /* TUSB_DFU_MODE_DEVICE_H_ */ diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h index 67eb26d95..c4116d8fe 100644 --- a/src/class/dfu/dfu_rt_device.h +++ b/src/class/dfu/dfu_rt_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DFU_RT_DEVICE_H_ -#define _TUSB_DFU_RT_DEVICE_H_ +#ifndef TUSB_DFU_RT_DEVICE_H_ +#define TUSB_DFU_RT_DEVICE_H_ #include "dfu.h" @@ -52,4 +52,4 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_req } #endif -#endif /* _TUSB_DFU_RT_DEVICE_H_ */ +#endif /* TUSB_DFU_RT_DEVICE_H_ */ diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index b69f623a0..0883d95ac 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -28,8 +28,8 @@ * \defgroup ClassDriver_HID Human Interface Device (HID) * @{ */ -#ifndef _TUSB_HID_H_ -#define _TUSB_HID_H_ +#ifndef TUSB_HID_H_ +#define TUSB_HID_H_ #include "common/tusb_common.h" @@ -2071,6 +2071,6 @@ enum { } #endif -#endif /* _TUSB_HID_H__ */ +#endif /* TUSB_HID_H__ */ /// @} diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index b4f24902b..6ee4cd9c1 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -128,7 +128,7 @@ bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, u TU_VERIFY(0 == tu_memcpy_s(p_epbuf->epin, CFG_TUD_HID_EP_BUFSIZE, report, len)); } - return usbd_edpt_xfer(rhport, p_hid->ep_in, p_epbuf->epin, len); + return usbd_edpt_xfer(rhport, p_hid->ep_in, p_epbuf->epin, len, false); } uint8_t tud_hid_n_interface_protocol(uint8_t instance) { @@ -263,7 +263,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16 // Prepare for output endpoint if (p_hid->ep_out) { - TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_epbuf->epout, CFG_TUD_HID_EP_BUFSIZE), drv_len); + TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_epbuf->epout, CFG_TUD_HID_EP_BUFSIZE, false), drv_len); } return drv_len; @@ -413,7 +413,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } // prepare for new transfer - TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_epbuf->epout, CFG_TUD_HID_EP_BUFSIZE)); + TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_epbuf->epout, CFG_TUD_HID_EP_BUFSIZE, false)); } return true; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index fc1dbcbd8..32b572973 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -267,14 +267,14 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u // Stylus Pen Report Descriptor Template #define TUD_HID_REPORT_DESC_STYLUS_PEN(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DIGITIZER ) , \ - HID_USAGE ( HID_USAGE_DIGITIZER_TOUCH_SCREEN ) , \ + HID_USAGE ( HID_USAGE_DIGITIZER_PEN ) , \ HID_COLLECTION ( HID_COLLECTION_APPLICATION ) , \ /* Report ID if any */\ __VA_ARGS__ \ - HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ) , \ - HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) , \ - HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_TIP_SWITCH ) , \ - HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_IN_RANGE ) , \ + HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ), \ + HID_COLLECTION ( HID_COLLECTION_PHYSICAL ), \ + HID_USAGE ( HID_USAGE_DIGITIZER_TIP_SWITCH ), \ + HID_USAGE ( HID_USAGE_DIGITIZER_IN_RANGE ), \ HID_LOGICAL_MIN ( 0 ), \ HID_LOGICAL_MAX ( 1 ), \ HID_REPORT_SIZE ( 1 ), \ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 032827af1..87f0e7dc9 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_HID_HOST_H_ -#define _TUSB_HID_HOST_H_ +#ifndef TUSB_HID_HOST_H_ +#define TUSB_HID_HOST_H_ #include "hid.h" @@ -182,4 +182,4 @@ void hidh_close(uint8_t dev_addr); } #endif -#endif /* _TUSB_HID_HOST_H_ */ +#endif /* TUSB_HID_HOST_H_ */ diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 7dac7c4a5..b20903d68 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -37,12 +37,18 @@ #include "midi_device.h" //--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf) { + (void)itf; +} + +//--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ typedef struct { + uint8_t rhport; uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the @@ -51,134 +57,97 @@ typedef struct { midi_driver_stream_t stream_read; /*------------- From this point, data is not cleared by bus reset -------------*/ - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; + // Endpoint stream + struct { + tu_edpt_stream_t tx; + tu_edpt_stream_t rx; - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; - #endif + uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; + } ep_stream; } midid_interface_t; -#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff) +#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, ep_stream) + +static midid_interface_t _midid_itf[CFG_TUD_MIDI]; // Endpoint Transfer buffer -CFG_TUD_MEM_SECTION static struct { +typedef struct { TUD_EPBUF_DEF(epin, CFG_TUD_MIDI_EP_BUFSIZE); TUD_EPBUF_DEF(epout, CFG_TUD_MIDI_EP_BUFSIZE); -} _midid_epbuf[CFG_TUD_MIDI]; +} midid_epbuf_t; + +CFG_TUD_MEM_SECTION static midid_epbuf_t _midid_epbuf[CFG_TUD_MIDI]; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static midid_interface_t _midid_itf[CFG_TUD_MIDI]; - bool tud_midi_n_mounted (uint8_t itf) { - midid_interface_t* midi = &_midid_itf[itf]; - return midi->ep_in && midi->ep_out; -} - -static void _prep_out_transaction(uint8_t idx) { - const uint8_t rhport = 0; - midid_interface_t* p_midi = &_midid_itf[idx]; - uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= CFG_TUD_MIDI_EP_BUFSIZE, ); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_midi->rx_ff); - - if ( available >= CFG_TUD_MIDI_EP_BUFSIZE ) { - usbd_edpt_xfer(rhport, p_midi->ep_out, _midid_epbuf[idx].epout, CFG_TUD_MIDI_EP_BUFSIZE); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_midi->ep_out); - } -} - + midid_interface_t *p_midi = &_midid_itf[itf]; -//--------------------------------------------------------------------+ -// Weak stubs: invoked if no strong implementation is available -//--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf) { - (void) itf; + const bool tx_opened = tu_edpt_stream_is_opened(&p_midi->ep_stream.tx); + const bool rx_opened = tu_edpt_stream_is_opened(&p_midi->ep_stream.rx); + return tx_opened && rx_opened; } //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) -{ +uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { (void) cable_num; - - midid_interface_t* midi = &_midid_itf[itf]; - const midi_driver_stream_t* stream = &midi->stream_read; + const midid_interface_t *p_midi = &_midid_itf[itf]; + const midi_driver_stream_t *stream = &p_midi->stream_read; + const tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; // when using with packet API stream total & index are both zero - return tu_fifo_count(&midi->rx_ff) + (uint8_t) (stream->total - stream->index); + return tu_edpt_stream_read_available(ep_str) + (uint8_t)(stream->total - stream->index); } -uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) -{ +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void *buffer, uint32_t bufsize) { (void) cable_num; - TU_VERIFY(bufsize, 0); - - uint8_t* buf8 = (uint8_t*) buffer; + TU_VERIFY(buffer != NULL && bufsize > 0, 0); - midid_interface_t* midi = &_midid_itf[itf]; - midi_driver_stream_t* stream = &midi->stream_read; + uint8_t *buf8 = (uint8_t *)buffer; + midid_interface_t *p_midi = &_midid_itf[itf]; + midi_driver_stream_t *stream = &p_midi->stream_read; uint32_t total_read = 0; - while( bufsize ) - { + while (bufsize > 0) { // Get new packet from fifo, then set packet expected bytes - if ( stream->total == 0 ) - { - // return if there is no more data from fifo - if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; + if (stream->total == 0) { + if (!tud_midi_n_packet_read(itf, stream->buffer)) { + return total_read; // return if there is no more data from fifo + } - uint8_t const code_index = stream->buffer[0] & 0x0f; + const uint8_t code_index = stream->buffer[0] & 0x0f; // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) - { + switch (code_index) { case MIDI_CIN_MISC: case MIDI_CIN_CABLE_EVENT: // These are reserved and unused, possibly issue somewhere, skip this packet return 0; - break; case MIDI_CIN_SYSEX_END_1BYTE: case MIDI_CIN_1BYTE_DATA: stream->total = 1; - break; + break; case MIDI_CIN_SYSCOM_2BYTE : case MIDI_CIN_SYSEX_END_2BYTE : case MIDI_CIN_PROGRAM_CHANGE : case MIDI_CIN_CHANNEL_PRESSURE : stream->total = 2; - break; + break; default: stream->total = 3; - break; + break; } } // Copy data up to bufsize - uint8_t const count = (uint8_t) tu_min32(stream->total - stream->index, bufsize); + const uint8_t count = (uint8_t)tu_min32((uint32_t)(stream->total - stream->index), bufsize); // Skip the header (1st byte) in the buffer TU_VERIFY(0 == tu_memcpy_s(buf8, bufsize, stream->buffer + 1 + stream->index, count)); @@ -189,8 +158,7 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui bufsize -= count; // complete current event packet, reset stream - if ( stream->total == stream->index ) - { + if (stream->total == stream->index) { stream->index = 0; stream->total = 0; } @@ -199,150 +167,107 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui return total_read; } -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_out); +bool tud_midi_n_packet_read(uint8_t itf, uint8_t packet[4]) { + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str)); + return 4 == tu_edpt_stream_read(p_midi->rhport, ep_str, packet, 4); +} + +uint32_t tud_midi_n_packet_read_n(uint8_t itf, uint8_t packets[], uint32_t max_packets) { + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); - const uint32_t num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); - _prep_out_transaction(itf); - return (num_read == 4); + const uint32_t num_read = tu_edpt_stream_read(p_midi->rhport, ep_str, packets, 4u * max_packets); + return num_read >> 2u; } //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ - -static uint32_t write_flush(uint8_t idx) { - midid_interface_t* midi = &_midid_itf[idx]; - - if (!tu_fifo_count(&midi->tx_ff)) { - return 0; // No data to send - } - - const uint8_t rhport = 0; - - // skip if previous transfer not complete - TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, _midid_epbuf[idx].epin, CFG_TUD_MIDI_EP_BUFSIZE); - - if (count) { - TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, _midid_epbuf[idx].epin, count), 0 ); - return count; - }else { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, midi->ep_in); - return 0; - } -} - -uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t* buffer, uint32_t bufsize) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in, 0); - - midi_driver_stream_t* stream = &midi->stream_write; +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t *buffer, uint32_t bufsize) { + midid_interface_t *p_midi = &_midid_itf[itf]; + midi_driver_stream_t *stream = &p_midi->stream_write; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); uint32_t i = 0; - while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) - { + while (i < bufsize) { + if (tu_edpt_stream_write_available(p_midi->rhport, ep_str) < 4) { + break; + } + const uint8_t data = buffer[i]; i++; - if ( stream->index == 0 ) - { + if (stream->index == 0) { //------------- New event packet -------------// const uint8_t msg = data >> 4; - stream->index = 2; + stream->index = 2; stream->buffer[1] = data; // Check to see if we're still in a SysEx transmit. - if ( ((stream->buffer[0]) & 0xF) == MIDI_CIN_SYSEX_START ) - { - if ( data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); - stream->total = 2; - } - else - { + if (((stream->buffer[0]) & 0xF) == MIDI_CIN_SYSEX_START) { + if (data == MIDI_STATUS_SYSEX_END) { + stream->buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); + stream->total = 2; + } else { stream->total = 4; } - } - else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) - { + } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { // Channel Voice Messages - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 4; - } - else if ( msg == 0xC || msg == 0xD) - { + stream->buffer[0] = (uint8_t)((cable_num << 4) | msg); + stream->total = 4; + } else if (msg == 0xC || msg == 0xD) { // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 3; - } - else if ( msg == 0xf ) - { + stream->buffer[0] = (uint8_t)((cable_num << 4) | msg); + stream->total = 3; + } else if (msg == 0xf) { // System message - if ( data == MIDI_STATUS_SYSEX_START ) - { + if (data == MIDI_STATUS_SYSEX_START) { stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } - else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) - { + stream->total = 4; + } else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) { stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } - else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) - { + stream->total = 3; + } else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) { stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } - else - { + stream->total = 4; + } else { stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; + stream->total = 2; } stream->buffer[0] |= (uint8_t)(cable_num << 4); - } - else - { + } else { // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); + stream->buffer[0] = (uint8_t)(cable_num << 4 | 0xf); stream->buffer[2] = 0; stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; + stream->total = 2; // index already set to 2 } - } - else - { + } else { //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, i); stream->buffer[stream->index] = data; stream->index++; // See if this byte ends a SysEx. - if ( (stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); - stream->total = stream->index; + if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { + stream->buffer[0] = (uint8_t)((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); + stream->total = stream->index; } } // Send out packet - if ( stream->index == stream->total ) - { + if (stream->index == stream->total) { // zeroes unused bytes for (uint8_t idx = stream->total; idx < 4; idx++) { stream->buffer[idx] = 0; } - const uint16_t count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); + const uint32_t count = tu_edpt_stream_write(p_midi->rhport, ep_str, stream->buffer, 4); // complete current event packet, reset stream stream->index = stream->total = 0; @@ -352,25 +277,37 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t* } } - write_flush(itf); + (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); return i; } bool tud_midi_n_packet_write (uint8_t itf, const uint8_t packet[4]) { - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in); + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str)); - if (tu_fifo_remaining(&midi->tx_ff) < 4) { - return false; - } - - tu_fifo_write_n(&midi->tx_ff, packet, 4); - write_flush(itf); + TU_VERIFY(tu_edpt_stream_write_available(p_midi->rhport, ep_str) >= 4); + TU_VERIFY(tu_edpt_stream_write(p_midi->rhport, ep_str, packet, 4) > 0); + (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); return true; } +uint32_t tud_midi_n_packet_write_n(uint8_t itf, const uint8_t packets[], uint32_t n_packets) { + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); + + uint32_t n_bytes = tu_edpt_stream_write_available(p_midi->rhport, ep_str); + n_bytes = tu_min32(tu_align4(n_bytes), n_packets << 2u); + + const uint32_t n_write = tu_edpt_stream_write(p_midi->rhport, ep_str, packets, n_bytes); + (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); + + return n_write >> 2u; +} + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ @@ -378,72 +315,64 @@ void midid_init(void) { tu_memclr(_midid_itf, sizeof(_midid_itf)); for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) { - midid_interface_t* midi = &_midid_itf[i]; - - // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. + midid_interface_t *p_midi = &_midid_itf[i]; + midid_epbuf_t *p_epbuf = &_midid_epbuf[i]; - #if CFG_FIFO_MUTEX - osal_mutex_t mutex_rd = osal_mutex_create(&midi->rx_ff_mutex); - osal_mutex_t mutex_wr = osal_mutex_create(&midi->tx_ff_mutex); - TU_ASSERT(mutex_wr != NULL && mutex_wr != NULL, ); + tu_edpt_stream_init( + &p_midi->ep_stream.rx, false, false, false, p_midi->ep_stream.rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, + p_epbuf->epout, CFG_TUD_MIDI_EP_BUFSIZE); - tu_fifo_config_mutex(&midi->rx_ff, NULL, mutex_rd); - tu_fifo_config_mutex(&midi->tx_ff, mutex_wr, NULL); - #endif + tu_edpt_stream_init( + &p_midi->ep_stream.tx, false, true, false, p_midi->ep_stream.tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, p_epbuf->epin, + CFG_TUD_MIDI_EP_BUFSIZE); } } bool midid_deinit(void) { - #if CFG_FIFO_MUTEX - for(uint8_t i=0; i<CFG_TUD_MIDI; i++) { - midid_interface_t* midi = &_midid_itf[i]; - osal_mutex_t mutex_rd = midi->rx_ff.mutex_rd; - osal_mutex_t mutex_wr = midi->tx_ff.mutex_wr; - - if (mutex_rd) { - osal_mutex_delete(mutex_rd); - tu_fifo_config_mutex(&midi->rx_ff, NULL, NULL); - } - - if (mutex_wr) { - osal_mutex_delete(mutex_wr); - tu_fifo_config_mutex(&midi->tx_ff, NULL, NULL); - } + for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) { + midid_interface_t *p_midi = &_midid_itf[i]; + tu_edpt_stream_deinit(&p_midi->ep_stream.rx); + tu_edpt_stream_deinit(&p_midi->ep_stream.tx); } - #endif - return true; } -void midid_reset(uint8_t rhport) -{ - (void) rhport; +void midid_reset(uint8_t rhport) { + (void)rhport; + for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) { + midid_interface_t *p_midi = &_midid_itf[i]; + tu_memclr(p_midi, ITF_MEM_RESET_SIZE); + + tu_edpt_stream_clear(&p_midi->ep_stream.rx); + tu_edpt_stream_close(&p_midi->ep_stream.rx); + + tu_edpt_stream_clear(&p_midi->ep_stream.tx); + tu_edpt_stream_close(&p_midi->ep_stream.tx); + } +} - for(uint8_t i=0; i<CFG_TUD_MIDI; i++) - { - midid_interface_t* midi = &_midid_itf[i]; - tu_memclr(midi, ITF_MEM_RESET_SIZE); - tu_fifo_clear(&midi->rx_ff); - tu_fifo_clear(&midi->tx_ff); +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_midi_itf(uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUD_MIDI; idx++) { + const midid_interface_t *p_midi = &_midid_itf[idx]; + if (ep_addr == p_midi->ep_stream.rx.ep_addr || ep_addr == p_midi->ep_stream.tx.ep_addr) { + return idx; + } } + return TUSB_INDEX_INVALID_8; } -uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) { - uint16_t drv_len = 0; - uint8_t const * p_desc = (uint8_t const *)desc_itf; +uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint16_t max_len) { + const uint8_t *p_desc = (const uint8_t *)desc_itf; + const uint8_t *desc_end = p_desc + max_len; // 1st Interface is Audio Control v1 (optional) if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { - drv_len = tu_desc_len(desc_itf); p_desc = tu_desc_next(desc_itf); // Skip Class Specific descriptors - while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + while (tu_desc_in_bounds(p_desc, desc_end) && TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) { + p_desc = tu_desc_next(p_desc); } } @@ -451,59 +380,48 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint1 TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); const tusb_desc_interface_t* desc_midi = (const tusb_desc_interface_t*) p_desc; - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, + 0); - // Find available interface - midid_interface_t * p_midi = NULL; - uint8_t idx; - for(idx=0; idx<CFG_TUD_MIDI; idx++) { - if ( _midid_itf[idx].ep_in == 0 && _midid_itf[idx].ep_out == 0 ) { - p_midi = &_midid_itf[idx]; - break; - } - } - TU_ASSERT(p_midi); + uint8_t idx = find_midi_itf(0); // find unused interface + TU_ASSERT(idx < CFG_TUD_MIDI, 0); + midid_interface_t *p_midi = &_midid_itf[idx]; + p_midi->rhport = rhport; p_midi->itf_num = desc_midi->bInterfaceNumber; (void) p_midi->itf_num; - // next descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); // Find and open endpoint descriptors - uint8_t found_endpoints = 0; - while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT(usbd_edpt_open(rhport, (const tusb_desc_endpoint_t*) p_desc), 0); - uint8_t ep_addr = ((const tusb_desc_endpoint_t*) p_desc)->bEndpointAddress; + uint8_t found_ep = 0; + while ((found_ep < desc_midi->bNumEndpoints) && tu_desc_in_bounds(p_desc, desc_end)) { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); + const uint8_t ep_addr = ((const tusb_desc_endpoint_t *)p_desc)->bEndpointAddress; - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - p_midi->ep_in = ep_addr; + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + tu_edpt_stream_t *stream_tx = &p_midi->ep_stream.tx; + tu_edpt_stream_open(stream_tx, desc_ep); + tu_edpt_stream_clear(stream_tx); } else { - p_midi->ep_out = ep_addr; + tu_edpt_stream_t *stream_rx = &p_midi->ep_stream.rx; + tu_edpt_stream_open(stream_rx, desc_ep); + tu_edpt_stream_clear(stream_rx); + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare to receive data } - // Class Specific MIDI Stream endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - found_endpoints += 1; + p_desc = tu_desc_next(p_desc); // skip CS Endpoint descriptor + found_ep++; } - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); } - // Prepare for incoming data - _prep_out_transaction(idx); - - return drv_len; + return (uint16_t)(p_desc - (const uint8_t *)desc_itf); } // Invoked when a control transfer occurred on an interface of this class @@ -514,44 +432,31 @@ bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_req return false; // driver doesn't support any request yet } -bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) rhport; - - uint8_t idx; - midid_interface_t* p_midi; +bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void)result; - // Identify which interface to use - for (idx = 0; idx < CFG_TUD_MIDI; idx++) { - p_midi = &_midid_itf[idx]; - if ((ep_addr == p_midi->ep_out) || (ep_addr == p_midi->ep_in)) { - break; - } - } + uint8_t idx = find_midi_itf(ep_addr); TU_ASSERT(idx < CFG_TUD_MIDI); + midid_interface_t *p_midi = &_midid_itf[idx]; - // receive new data - if (ep_addr == p_midi->ep_out) { - tu_fifo_write_n(&p_midi->rx_ff, _midid_epbuf[idx].epout, (uint16_t)xferred_bytes); + tu_edpt_stream_t *ep_st_rx = &p_midi->ep_stream.rx; + tu_edpt_stream_t *ep_st_tx = &p_midi->ep_stream.tx; - // invoke receive callback if available - tud_midi_rx_cb(idx); - - // prepare for next - // TODO for now ep_out is not used by public API therefore there is no race condition, - // and does not need to claim like ep_in - _prep_out_transaction(idx); - } else if (ep_addr == p_midi->ep_in) { - if (0 == write_flush(idx)) { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if (!tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE))) { - if (usbd_edpt_claim(rhport, p_midi->ep_in)) { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); - } - } + if (ep_addr == ep_st_rx->ep_addr) { + // Received new data: put into stream's fifo + if (result == XFER_RESULT_SUCCESS) { + tu_edpt_stream_read_xfer_complete(ep_st_rx, xferred_bytes); + tud_midi_rx_cb(idx); // invoke callback } + tu_edpt_stream_read_xfer(rhport, ep_st_rx); // prepare for next data + } else if (ep_addr == ep_st_tx->ep_addr && result == XFER_RESULT_SUCCESS) { + // sent complete: try to send more if possible + if (0 == tu_edpt_stream_write_xfer(rhport, ep_st_tx)) { + // If there is no data left, a ZLP should be sent if needed + (void)tu_edpt_stream_write_zlp_if_needed(rhport, ep_st_tx, xferred_bytes); + } + } else { + return false; } return true; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index c2c6e9859..ddbc2f9f0 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MIDI_DEVICE_H_ -#define _TUSB_MIDI_DEVICE_H_ +#ifndef TUSB_MIDI_DEVICE_H_ +#define TUSB_MIDI_DEVICE_H_ #include "class/audio/audio.h" #include "midi.h" @@ -36,21 +36,21 @@ #if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE + #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE #endif #ifndef CFG_TUD_MIDI_EP_BUFSIZE - #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus - extern "C" { +extern "C" { #endif -/** \addtogroup MIDI_Serial Serial - * @{ - * \defgroup MIDI_Serial_Device Device - * @{ */ +//--------------------------------------------------------------------+ +// Application Callback API (optional) +//--------------------------------------------------------------------+ +void tud_midi_rx_cb(uint8_t itf); //--------------------------------------------------------------------+ // Application API (Multiple Interfaces) @@ -58,117 +58,77 @@ //--------------------------------------------------------------------+ // Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); +bool tud_midi_n_mounted(uint8_t itf); // Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); - -// Read byte stream (legacy) -uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); - -// Write byte Stream (legacy) -uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); - -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num); -//--------------------------------------------------------------------+ -// Application API (Single Interface) -//--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write (uint8_t const packet[4]); - -//------------- Deprecated API name -------------// -// TODO remove after 0.10.0 release - -TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_stream_read(buffer, bufsize); -} +// Read byte stream (legacy) +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void *buffer, uint32_t bufsize); -TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") -static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_stream_write(cable_num, buffer, bufsize); -} +// Write byte Stream (legacy) +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t *buffer, uint32_t bufsize); +// Read an event 4-byte packet +bool tud_midi_n_packet_read(uint8_t itf, uint8_t packet[4]); -TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") -static inline bool tud_midi_send(uint8_t packet[4]) -{ - return tud_midi_packet_write(packet); -} +// Read multiple event packets, return number of read packets +uint32_t tud_midi_n_packet_read_n(uint8_t itf, uint8_t packets[], uint32_t max_packets); -TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") -static inline bool tud_midi_receive(uint8_t packet[4]) -{ - return tud_midi_packet_read(packet); -} +// Write an event 4-byte packet +bool tud_midi_n_packet_write(uint8_t itf, const uint8_t packet[4]); -//--------------------------------------------------------------------+ -// Application Callback API (optional) -//--------------------------------------------------------------------+ -void tud_midi_rx_cb(uint8_t itf); +// Write multiple event packets, return number of written packets +uint32_t tud_midi_n_packet_write_n(uint8_t itf, const uint8_t packets[], uint32_t n_packets); //--------------------------------------------------------------------+ -// Inline Functions +// Application API (Single Interface) //--------------------------------------------------------------------+ - -static inline bool tud_midi_mounted (void) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tud_midi_mounted(void) { return tud_midi_n_mounted(0); } -static inline uint32_t tud_midi_available (void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_available(void) { return tud_midi_n_available(0, 0); } -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_stream_read(void *buffer, uint32_t bufsize) { return tud_midi_n_stream_read(0, 0, buffer, bufsize); } -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t +tud_midi_stream_write(uint8_t cable_num, const uint8_t *buffer, uint32_t bufsize) { return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); } -static inline bool tud_midi_packet_read (uint8_t packet[4]) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tud_midi_packet_read(uint8_t packet[4]) { return tud_midi_n_packet_read(0, packet); } -static inline bool tud_midi_packet_write (uint8_t const packet[4]) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_packet_read_n(uint8_t packets[], uint32_t max_packets) { + return tud_midi_n_packet_read_n(0, packets, max_packets); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_midi_packet_write(const uint8_t packet[4]) { return tud_midi_n_packet_write(0, packet); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_packet_write_n(const uint8_t packets[], uint32_t n_packets) { + return tud_midi_n_packet_write_n(0, packets, n_packets); +} + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midid_init (void); -bool midid_deinit (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void midid_init(void); +bool midid_deinit(void); +void midid_reset(uint8_t rhport); +uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t *request); +bool midid_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus - } +} #endif -#endif /* _TUSB_MIDI_DEVICE_H_ */ - -/** @} */ -/** @} */ +#endif diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index e6ace316c..07062875c 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -59,9 +59,6 @@ typedef struct { uint8_t iInterface; uint8_t itf_count; // number of interface including Audio Control + MIDI streaming - uint8_t ep_in; // IN endpoint address - uint8_t ep_out; // OUT endpoint address - uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value @@ -147,8 +144,6 @@ void midih_close(uint8_t daddr) { TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); tuh_midi_umount_cb(idx); - p_midi->ep_in = 0; - p_midi->ep_out = 0; p_midi->bInterfaceNumber = 0; p_midi->rx_cable_count = 0; p_midi->tx_cable_count = 0; @@ -169,23 +164,25 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr); TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; + tu_edpt_stream_t *ep_str_rx = &p_midi->ep_stream.rx; + tu_edpt_stream_t *ep_str_tx = &p_midi->ep_stream.tx; - if (ep_addr == p_midi->ep_stream.rx.ep_addr) { + if (ep_addr == ep_str_rx->ep_addr) { // receive new data, put it into FIFO and invoke callback if available // Note: some devices send back all zero packets even if there is no data ready - if (xferred_bytes && !tu_mem_is_zero(p_midi->ep_stream.rx.ep_buf, xferred_bytes)) { - tu_edpt_stream_read_xfer_complete(&p_midi->ep_stream.rx, xferred_bytes); + if (xferred_bytes && !tu_mem_is_zero(ep_str_rx->ep_buf, xferred_bytes)) { + tu_edpt_stream_read_xfer_complete(ep_str_rx, xferred_bytes); tuh_midi_rx_cb(idx, xferred_bytes); } - tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for next transfer - } else if (ep_addr == p_midi->ep_stream.tx.ep_addr) { + tu_edpt_stream_read_xfer(dev_addr, ep_str_rx); // prepare for next transfer + } else if (ep_addr == ep_str_tx->ep_addr) { tuh_midi_tx_cb(idx, xferred_bytes); - if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi->ep_stream.tx)) { + if (0 == tu_edpt_stream_write_xfer(dev_addr, ep_str_tx)) { // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - tu_edpt_stream_write_zlp_if_needed(dev_addr, &p_midi->ep_stream.tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(dev_addr, ep_str_tx, xferred_bytes); } } @@ -220,11 +217,11 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d // driver after parsing the audio control interface and then resume parsing // the streaming audio interface. if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { - TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(audio_desc_cs_ac_interface_t)); + TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(midi10_desc_cs_ac_interface_t)); p_desc = tu_desc_next(p_desc); TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && - tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_HEADER); + tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_HEADER); desc_cb.desc_audio_control = desc_itf; p_desc = tu_desc_next(p_desc); @@ -295,21 +292,20 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc; TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); + tu_edpt_stream_t *ep_stream; if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { - p_midi->ep_out = p_ep->bEndpointAddress; p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack; desc_cb.desc_epout = p_ep; - - TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); - tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep); + ep_stream = &p_midi->ep_stream.tx; } else { - p_midi->ep_in = p_ep->bEndpointAddress; p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack; - desc_cb.desc_epin = p_ep; - - TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); - tu_edpt_stream_open(&p_midi->ep_stream.rx, p_ep); + desc_cb.desc_epin = p_ep; + ep_stream = &p_midi->ep_stream.rx; } + TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); + tu_edpt_stream_open(ep_stream, p_ep); + tu_edpt_stream_clear(ep_stream); + break; } @@ -379,8 +375,14 @@ bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { desc->bDescriptorType = TUSB_DESC_INTERFACE; desc->bInterfaceNumber = p_midi->bInterfaceNumber; - desc->bAlternateSetting = 0; - desc->bNumEndpoints = (uint8_t)((p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0)); + desc->bAlternateSetting = 0; + desc->bNumEndpoints = 0; + if (tu_edpt_stream_is_opened(&p_midi->ep_stream.tx)) { + desc->bNumEndpoints++; + } + if (tu_edpt_stream_is_opened(&p_midi->ep_stream.rx)) { + desc->bNumEndpoints++; + } desc->bInterfaceClass = TUSB_CLASS_AUDIO; desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; desc->bInterfaceProtocol = 0; diff --git a/src/class/msc/msc.h b/src/class/msc/msc.h index b2b44eac4..3b5d4a855 100644 --- a/src/class/msc/msc.h +++ b/src/class/msc/msc.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MSC_H_ -#define _TUSB_MSC_H_ +#ifndef TUSB_MSC_H_ +#define TUSB_MSC_H_ #include "common/tusb_common.h" @@ -398,4 +398,4 @@ TU_VERIFY_STATIC(sizeof(scsi_write10_t) == 10, "size is not correct"); } #endif -#endif /* _TUSB_MSC_H_ */ +#endif /* TUSB_MSC_H_ */ diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index b0eafd5da..15bfafc35 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -83,7 +83,7 @@ typedef struct { uint8_t add_sense_code; uint8_t add_sense_qualifier; - uint8_t pending_io; // pending async IO + bool pending_io; // pending async IO }mscd_interface_t; static mscd_interface_t _mscd_itf; @@ -92,6 +92,8 @@ CFG_TUD_MEM_SECTION static struct { TUD_EPBUF_DEF(buf, CFG_TUD_MSC_EP_BUFSIZE); } _mscd_epbuf; +TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE >= 64, "CFG_TUD_MSC_EP_BUFSIZE must be at least 64"); + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -107,19 +109,19 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) { return tu_bit_test(dir, 7); } -static inline bool send_csw(mscd_interface_t* p_msc) { +TU_ATTR_ALWAYS_INLINE static inline bool send_csw(mscd_interface_t* p_msc) { // Data residue is always = host expect - actual transferred uint8_t rhport = p_msc->rhport; p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; p_msc->stage = MSC_STAGE_STATUS_SENT; - memcpy(_mscd_epbuf.buf, &p_msc->csw, sizeof(msc_csw_t)); - return usbd_edpt_xfer(rhport, p_msc->ep_in , _mscd_epbuf.buf, sizeof(msc_csw_t)); + memcpy(_mscd_epbuf.buf, &p_msc->csw, sizeof(msc_csw_t)); //-V1086 + return usbd_edpt_xfer(rhport, p_msc->ep_in , _mscd_epbuf.buf, sizeof(msc_csw_t), false); } -static inline bool prepare_cbw(mscd_interface_t* p_msc) { +TU_ATTR_ALWAYS_INLINE static inline bool prepare_cbw(mscd_interface_t* p_msc) { uint8_t rhport = p_msc->rhport; p_msc->stage = MSC_STAGE_CMD; - return usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, sizeof(msc_cbw_t)); + return usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, sizeof(msc_cbw_t), false); } static void fail_scsi_op(mscd_interface_t* p_msc, uint8_t status) { @@ -133,7 +135,7 @@ static void fail_scsi_op(mscd_interface_t* p_msc, uint8_t status) { // failed but sense key is not set: default to Illegal Request if (p_msc->sense_key == 0) { - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + (void) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); } // If there is data stage and not yet complete, stall it @@ -146,18 +148,18 @@ static void fail_scsi_op(mscd_interface_t* p_msc, uint8_t status) { } } -static inline uint32_t rdwr10_get_lba(uint8_t const command[]) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t rdwr10_get_lba(uint8_t const command[]) { // use offsetof to avoid pointer to the odd/unaligned address const uint32_t lba = tu_unaligned_read32(command + offsetof(scsi_write10_t, lba)); return tu_ntohl(lba); // lba is in Big Endian } -static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) { uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); return tu_ntohs(block_count); } -static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) { // first extract block count in the command uint16_t const block_count = rdwr10_get_blockcount(cbw); if (block_count == 0) { @@ -171,7 +173,7 @@ static uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) { uint16_t const block_count = rdwr10_get_blockcount(cbw); if (cbw->total_bytes == 0) { - if (block_count) { + if (block_count > 0) { TU_LOG_DRV(" SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); status = MSC_CSW_STATUS_PHASE_ERROR; } else { @@ -190,6 +192,8 @@ static uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) { } else if (cbw->total_bytes / block_count == 0) { TU_LOG_DRV(" Computed block size = 0. SCSI case 7 Hi < Di (READ10) or case 13 Ho < Do (WRIT10)\r\n"); status = MSC_CSW_STATUS_PHASE_ERROR; + } else { + // nothing to do } } @@ -309,7 +313,7 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u TU_ATTR_ALWAYS_INLINE static inline void set_sense_medium_not_present(uint8_t lun) { // default sense is NOT READY, MEDIUM NOT PRESENT - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); + (void) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); } static void proc_async_io_done(void *bytes_io) { @@ -318,7 +322,7 @@ static void proc_async_io_done(void *bytes_io) { const int32_t nbytes = (int32_t) (intptr_t) bytes_io; const uint8_t cmd = p_msc->cbw.command[0]; - p_msc->pending_io = 0; + p_msc->pending_io = false; switch (cmd) { case SCSI_CMD_READ_10: proc_read_io_data(p_msc, nbytes); @@ -328,7 +332,7 @@ static void proc_async_io_done(void *bytes_io) { proc_write_io_data(p_msc, (uint32_t) nbytes, nbytes); break; - default: break; + default: break; // nothing to do } // send status if stage is transitioned to STATUS @@ -429,6 +433,8 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_ASSERT(prepare_cbw(p_msc)); } } + } else { + // nothing to do } } @@ -451,7 +457,7 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_VERIFY(request->wValue == 0 && request->wLength == 1); uint8_t maxlun = tud_msc_get_maxlun_cb(); - TU_VERIFY(maxlun); + TU_VERIFY(maxlun != 0); maxlun--; // MAX LUN is minus 1 by specs tud_control_xfer(rhport, request, &maxlun, 1); break; @@ -510,7 +516,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if (status != MSC_CSW_STATUS_PASSED) { fail_scsi_op(p_msc, status); - } else if (p_cbw->total_bytes) { + } else if (p_cbw->total_bytes > 0) { if (SCSI_CMD_READ_10 == p_cbw->command[0]) { proc_read10_cmd(p_msc); } else { @@ -531,7 +537,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } else { // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first // but it is OK to just receive data then responded with failed status - TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, (uint16_t) p_msc->total_len)); + TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, (uint16_t) p_msc->total_len, false)); } } else { // First process if it is a built-in commands @@ -547,7 +553,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_LOG_DRV(" SCSI unsupported or failed command\r\n"); fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else if (resplen == 0) { - if (p_cbw->total_bytes) { + if (p_cbw->total_bytes > 0) { // 6.7 The 13 Cases: case 4 (Hi > Dn) // TU_LOG_DRV(" SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); @@ -563,7 +569,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } else { // cannot return more than host expect p_msc->total_len = tu_min32((uint32_t)resplen, p_cbw->total_bytes); - TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) p_msc->total_len)); + TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) p_msc->total_len, false)); } } } @@ -647,7 +653,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } break; - default: break; + default: break; // nothing to do } if (p_msc->stage == MSC_STAGE_STATUS) { @@ -683,9 +689,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ } break; - case SCSI_CMD_START_STOP_UNIT: + case SCSI_CMD_START_STOP_UNIT: { resplen = 0; - scsi_start_stop_unit_t const* start_stop = (scsi_start_stop_unit_t const*)scsi_cmd; if (!tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject)) { // Failed status response @@ -697,10 +702,10 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ } } break; + } - case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: { resplen = 0; - scsi_prevent_allow_medium_removal_t const* prevent_allow = (scsi_prevent_allow_medium_removal_t const*)scsi_cmd; if (!tud_msc_prevent_allow_medium_removal_cb(lun, prevent_allow->prohibit_removal, prevent_allow->control)) { // Failed status response @@ -712,7 +717,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ } } break; - + } case SCSI_CMD_READ_CAPACITY_10: { uint32_t block_count; @@ -740,8 +745,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = sizeof(read_capa10); TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &read_capa10, (size_t) resplen)); } + break; } - break; case SCSI_CMD_READ_FORMAT_CAPACITY: { scsi_read_format_capacity_data_t read_fmt_capa = { @@ -772,8 +777,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = sizeof(read_fmt_capa); TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &read_fmt_capa, (size_t) resplen)); } + break; } - break; case SCSI_CMD_INQUIRY: { scsi_inquiry_resp_t *inquiry_rsp = (scsi_inquiry_resp_t *) buffer; @@ -789,8 +794,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ tud_msc_inquiry_cb(lun, inquiry_rsp->vendor_id, inquiry_rsp->product_id, inquiry_rsp->product_rev); resplen = sizeof(scsi_inquiry_resp_t); } + break; } - break; case SCSI_CMD_MODE_SENSE_6: { scsi_mode_sense6_resp_t mode_resp = { @@ -807,8 +812,8 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = sizeof(mode_resp); TU_VERIFY(0 == tu_memcpy_s(buffer, bufsize, &mode_resp, (size_t) resplen)); + break; } - break; case SCSI_CMD_REQUEST_SENSE: { scsi_sense_fixed_resp_t sense_rsp = { @@ -828,9 +833,9 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ resplen = tud_msc_request_sense_cb(lun, buffer, (uint16_t)bufsize); // Clear sense data after copy - tud_msc_set_sense(lun, 0, 0, 0); + (void) tud_msc_set_sense(lun, 0, 0, 0); + break; } - break; default: resplen = -1; break; @@ -842,6 +847,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ static void proc_read10_cmd(mscd_interface_t* p_msc) { msc_cbw_t const* p_cbw = &p_msc->cbw; uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); // already verified non-zero + TU_VERIFY(block_sz != 0, ); // Adjust lba & offset with transferred bytes uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); uint32_t const offset = p_msc->xferred_len % block_sz; @@ -849,10 +855,10 @@ static void proc_read10_cmd(mscd_interface_t* p_msc) { // remaining bytes capped at class buffer int32_t nbytes = (int32_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len); - p_msc->pending_io = 1; + p_msc->pending_io = true; nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes); if (nbytes != TUD_MSC_RET_ASYNC) { - p_msc->pending_io = 0; + p_msc->pending_io = false; proc_read_io_data(p_msc, nbytes); } } @@ -860,7 +866,7 @@ static void proc_read10_cmd(mscd_interface_t* p_msc) { static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { const uint8_t rhport = p_msc->rhport; if (nbytes > 0) { - TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),); + TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes, false),); } else { // nbytes is status switch (nbytes) { @@ -876,19 +882,19 @@ static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); break; - default: break; + default: break; // nothing to do } } } static void proc_write10_cmd(mscd_interface_t* p_msc) { msc_cbw_t const* p_cbw = &p_msc->cbw; - bool writable = tud_msc_is_writable_cb(p_cbw->lun); + const bool writable = tud_msc_is_writable_cb(p_cbw->lun); if (!writable) { // Not writable, complete this SCSI op with error // Sense = Write protected - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); + (void) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); return; } @@ -896,22 +902,23 @@ static void proc_write10_cmd(mscd_interface_t* p_msc) { // remaining bytes capped at class buffer uint16_t nbytes = (uint16_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len); // Write10 callback will be called later when usb transfer complete - TU_ASSERT(usbd_edpt_xfer(p_msc->rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes),); + TU_ASSERT(usbd_edpt_xfer(p_msc->rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes, false),); } // process new data arrived from WRITE10 static void proc_write10_host_data(mscd_interface_t* p_msc, uint32_t xferred_bytes) { msc_cbw_t const* p_cbw = &p_msc->cbw; uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); // already verified non-zero + TU_VERIFY(block_sz != 0, ); // Adjust lba & offset with transferred bytes uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); uint32_t const offset = p_msc->xferred_len % block_sz; - p_msc->pending_io = 1; + p_msc->pending_io = true; int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes); if (nbytes != TUD_MSC_RET_ASYNC) { - p_msc->pending_io = 0; + p_msc->pending_io = false; proc_write_io_data(p_msc, xferred_bytes, nbytes); } } @@ -927,7 +934,7 @@ static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); break; - default: break; + default: break; // nothing to do } } else { if ((uint32_t)nbytes < xferred_bytes) { diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 7d898e988..21e24971b 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MSC_DEVICE_H_ -#define _TUSB_MSC_DEVICE_H_ +#ifndef TUSB_MSC_DEVICE_H_ +#define TUSB_MSC_DEVICE_H_ #include "common/tusb_common.h" #include "msc.h" @@ -167,4 +167,4 @@ bool mscd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t ev } #endif -#endif /* _TUSB_MSC_DEVICE_H_ */ +#endif /* TUSB_MSC_DEVICE_H_ */ diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index eb69ae400..daff345c5 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -123,7 +123,10 @@ bool tuh_msc_mounted(uint8_t dev_addr) { bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in) && !usbh_edpt_busy(dev_addr, p_msc->ep_out); + TU_VERIFY(p_msc->mounted); + const bool epin_busy = usbh_edpt_busy(dev_addr, p_msc->ep_in); + const bool epout_busy = usbh_edpt_busy(dev_addr, p_msc->ep_out); + return !epin_busy && !epout_busy; } //--------------------------------------------------------------------+ @@ -152,7 +155,7 @@ bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, p_msc->stage = MSC_STAGE_CMD; if (!usbh_edpt_xfer(daddr, p_msc->ep_out, (uint8_t*) &epbuf->cbw, sizeof(msc_cbw_t))) { - usbh_edpt_release(daddr, p_msc->ep_out); + (void) usbh_edpt_release(daddr, p_msc->ep_out); return false; } @@ -191,7 +194,7 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons .cmd_code = SCSI_CMD_INQUIRY, .alloc_length = sizeof(scsi_inquiry_resp_t) }; - memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); + memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); //-V1086 return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } @@ -225,7 +228,7 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void* response, .cmd_code = SCSI_CMD_REQUEST_SENSE, .alloc_length = 18 }; - memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); + memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); //-V1086 return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } @@ -247,7 +250,7 @@ bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void* buffer, uint32_t lba, u .lba = tu_htonl(lba), .block_count = tu_htons(block_count) }; - memcpy(cbw.command, &cmd_read10, cbw.cmd_len); + memcpy(cbw.command, &cmd_read10, cbw.cmd_len); //-V1086 return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg); } @@ -269,7 +272,7 @@ bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const* buffer, uint32_t .lba = tu_htonl(lba), .block_count = tu_htons(block_count) }; - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); + memcpy(cbw.command, &cmd_write10, cbw.cmd_len); //-V1086 return tuh_msc_scsi_command(dev_addr, &cbw, (void*) (uintptr_t) buffer, complete_cb, arg); } @@ -338,8 +341,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes)); break; } - - TU_ATTR_FALLTHROUGH; // fallthrough to status stage + TU_ATTR_FALLTHROUGH; // fallthrough to data stage case MSC_STAGE_DATA: // Status stage @@ -350,20 +352,19 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 case MSC_STAGE_STATUS: // SCSI op is complete p_msc->stage = MSC_STAGE_IDLE; - - if (p_msc->complete_cb) { + if (p_msc->complete_cb != NULL) { tuh_msc_complete_data_t const cb_data = { .cbw = cbw, .csw = csw, .scsi_data = p_msc->buffer, .user_arg = p_msc->complete_arg }; - p_msc->complete_cb(dev_addr, &cb_data); + (void) p_msc->complete_cb(dev_addr, &cb_data); } break; - // unknown state default: + // unknown state break; } @@ -501,7 +502,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_dat // Capacity response field: Block size and Last LBA are both Big-Endian scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) (uintptr_t) enum_buf; - p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1; + p_msc->capacity[cbw->lun].block_count = (uint32_t) (tu_ntohl(resp->last_lba) + 1u); p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size); // Mark enumeration is complete diff --git a/src/class/mtp/mtp.h b/src/class/mtp/mtp.h new file mode 100644 index 000000000..236cf98e0 --- /dev/null +++ b/src/class/mtp/mtp.h @@ -0,0 +1,888 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ennebi Elettronica (https://ennebielettronica.com) + * + * 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 TUSB_MTP_H_ +#define TUSB_MTP_H_ + +#include "common/tusb_common.h" + +#if (CFG_TUD_ENABLED && CFG_TUD_MTP) + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Media Transfer Protocol Class Constant +//--------------------------------------------------------------------+ + +// Media Transfer Protocol Subclass +typedef enum { + MTP_SUBCLASS_STILL_IMAGE = 1 +} mtp_subclass_type_t; + +// MTP Protocol. +typedef enum { + MTP_PROTOCOL_PIMA_15470 = 1, ///< Picture Transfer Protocol (PIMA 15470) +} mtp_protocol_type_t; + +// PTP/MTP protocol phases +typedef enum { + MTP_PHASE_COMMAND = 0, + MTP_PHASE_DATA, + MTP_PHASE_RESPONSE, + MTP_PHASE_ERROR +} mtp_phase_type_t; + +// PTP/MTP Class requests, PIMA 15740-2000: D.5.2 +typedef enum { + MTP_REQ_CANCEL = 0x64, + MTP_REQ_GET_EXT_EVENT_DATA = 0x65, + MTP_REQ_RESET = 0x66, + MTP_REQ_GET_DEVICE_STATUS = 0x67, +} mtp_class_request_t; + +// PTP/MTP Container type +typedef enum { + MTP_CONTAINER_TYPE_UNDEFINED = 0, + MTP_CONTAINER_TYPE_COMMAND_BLOCK = 1, + MTP_CONTAINER_TYPE_DATA_BLOCK = 2, + MTP_CONTAINER_TYPE_RESPONSE_BLOCK = 3, + MTP_CONTAINER_TYPE_EVENT_BLOCK = 4, +} mtp_container_type_t; + +// MTP 1.1 Appendix A: Object formats +typedef enum { + // ---- Base formats ---- + MTP_OBJ_FORMAT_UNDEFINED = 0x3000u, // Undefined object + MTP_OBJ_FORMAT_ASSOCIATION = 0x3001u, // Association (for example, a folder) + MTP_OBJ_FORMAT_SCRIPT = 0x3002u, // Device model-specific script + MTP_OBJ_FORMAT_EXECUTABLE = 0x3003u, // Device model-specific binary executable + MTP_OBJ_FORMAT_TEXT = 0x3004u, // Text file + MTP_OBJ_FORMAT_HTML = 0x3005u, // Hypertext Markup Language file (text) + MTP_OBJ_FORMAT_DPOF = 0x3006u, // Digital Print Order Format file (text) + MTP_OBJ_FORMAT_AIFF = 0x3007u, // Audio clip (AIFF) + MTP_OBJ_FORMAT_WAV = 0x3008u, // Audio clip (WAV) + MTP_OBJ_FORMAT_MP3 = 0x3009u, // MPEG-1 Layer III audio (ISO/IEC 13818-3) + MTP_OBJ_FORMAT_AVI = 0x300Au, // Video clip (AVI) + MTP_OBJ_FORMAT_MPEG = 0x300Bu, // Video clip (MPEG) + MTP_OBJ_FORMAT_ASF = 0x300Cu, // Microsoft Advanced Streaming Format (video) + + // ---- Image formats ---- + MTP_OBJ_FORMAT_UNDEFINED_IMAGE = 0x3800u, // Undefined image object + MTP_OBJ_FORMAT_EXIF_JPEG = 0x3801u, // Exchangeable Image Format, JEIDA standard + MTP_OBJ_FORMAT_TIFF_EP = 0x3802u, // Tag Image File Format for Electronic Photography + MTP_OBJ_FORMAT_FLASHPIX = 0x3803u, // Structured Storage Image Format (FlashPix) + MTP_OBJ_FORMAT_BMP = 0x3804u, // Microsoft Windows Bitmap file + MTP_OBJ_FORMAT_CIFF = 0x3805u, // Canon Camera Image File Format + MTP_OBJ_FORMAT_UNDEFINED_3806 = 0x3806u, // Reserved / Undefined + MTP_OBJ_FORMAT_GIF = 0x3807u, // Graphics Interchange Format + MTP_OBJ_FORMAT_JFIF = 0x3808u, // JPEG File Interchange Format + MTP_OBJ_FORMAT_CD = 0x3809u, // PhotoCD Image Pac + MTP_OBJ_FORMAT_PICT = 0x380Au, // Quickdraw Image Format + MTP_OBJ_FORMAT_PNG = 0x380Bu, // Portable Network Graphics + MTP_OBJ_FORMAT_UNDEFINED_380C = 0x380Cu, // Reserved / Undefined + MTP_OBJ_FORMAT_TIFF = 0x380Du, // Tag Image File Format (baseline) + MTP_OBJ_FORMAT_TIFF_IT = 0x380Eu, // Tag Image File Format for IT (graphic arts) + MTP_OBJ_FORMAT_JP2 = 0x380Fu, // JPEG2000 Baseline File Format + MTP_OBJ_FORMAT_JPX = 0x3810u, // JPEG2000 Extended File Format + + // ---- Firmware & misc ---- + MTP_OBJ_FORMAT_UNDEFINED_FIRMWARE = 0xB802u, // Undefined Firmware + MTP_OBJ_FORMAT_WBMP = 0xB803u, // Wireless Application Protocol Bitmap Format (.wbmp) + MTP_OBJ_FORMAT_WINDOWS_IMAGE = 0xB881u, // Windows Image Format + MTP_OBJ_FORMAT_JPEGXR = 0xB804u, // JPEG XR (.hdp, .jxr, .wdp) + + // ---- Audio formats ---- + MTP_OBJ_FORMAT_UNDEFINED_AUDIO = 0xB900u, // Undefined audio object + MTP_OBJ_FORMAT_WMA = 0xB901u, // Windows Media Audio + MTP_OBJ_FORMAT_OGG = 0xB902u, // OGG container + MTP_OBJ_FORMAT_AAC = 0xB903u, // Advanced Audio Coding (.aac) + MTP_OBJ_FORMAT_AUDIBLE = 0xB904u, // Audible format + MTP_OBJ_FORMAT_FLAC = 0xB906u, // Free Lossless Audio Codec + MTP_OBJ_FORMAT_QCELP = 0xB907u, // Qualcomm Code Excited Linear Prediction (.qcp) + MTP_OBJ_FORMAT_AMR = 0xB908u, // Adaptive Multi-Rate audio (.amr) + + // ---- Video formats ---- + MTP_OBJ_FORMAT_UNDEFINED_VIDEO = 0xB980u, // Undefined video object + MTP_OBJ_FORMAT_WMV = 0xB981u, // Windows Media Video + MTP_OBJ_FORMAT_MP4 = 0xB982u, // MP4 Container (ISO 14496-1) + MTP_OBJ_FORMAT_MP2 = 0xB983u, // MPEG-1 Layer II audio + MTP_OBJ_FORMAT_3GP = 0xB984u, // 3GP Container + MTP_OBJ_FORMAT_3G2 = 0xB985u, // 3GPP2 Container + MTP_OBJ_FORMAT_AVCHD = 0xB986u, // AVCHD (MPEG-4 AVC + Dolby Digital) + MTP_OBJ_FORMAT_ATSC_TS = 0xB987u, // ATSC-compliant MPEG-2 Transport Stream + MTP_OBJ_FORMAT_DVB_TS = 0xB988u, // DVB-compliant MPEG-2 Transport Stream + + // ---- Collections ---- + MTP_OBJ_FORMAT_UNDEFINED_COLLECTION = 0xBA00u, // Undefined collection + MTP_OBJ_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM = 0xBA01u, // Abstract Multimedia Album + MTP_OBJ_FORMAT_ABSTRACT_IMAGE_ALBUM = 0xBA02u, // Abstract Image Album + MTP_OBJ_FORMAT_ABSTRACT_AUDIO_ALBUM = 0xBA03u, // Abstract Audio Album + MTP_OBJ_FORMAT_ABSTRACT_VIDEO_ALBUM = 0xBA04u, // Abstract Video Album + MTP_OBJ_FORMAT_ABSTRACT_AV_PLAYLIST = 0xBA05u, // Abstract Audio & Video Playlist + MTP_OBJ_FORMAT_ABSTRACT_CONTACT_GROUP = 0xBA06u, // Abstract Contact Group + MTP_OBJ_FORMAT_ABSTRACT_MESSAGE_FOLDER = 0xBA07u, // Abstract Message Folder + MTP_OBJ_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION = 0xBA08u, // Abstract Chaptered Production + MTP_OBJ_FORMAT_ABSTRACT_AUDIO_PLAYLIST = 0xBA09u, // Abstract Audio Playlist + MTP_OBJ_FORMAT_ABSTRACT_VIDEO_PLAYLIST = 0xBA0Au, // Abstract Video Playlist + MTP_OBJ_FORMAT_ABSTRACT_MEDIACAST = 0xBA0Bu, // Abstract Mediacast (RSS enclosure) + + // ---- Playlist formats ---- + MTP_OBJ_FORMAT_WPL_PLAYLIST = 0xBA10u, // Windows Media Player Playlist (.wpl) + MTP_OBJ_FORMAT_M3U_PLAYLIST = 0xBA11u, // M3U Playlist + MTP_OBJ_FORMAT_MPL_PLAYLIST = 0xBA12u, // MPL Playlist + MTP_OBJ_FORMAT_ASX_PLAYLIST = 0xBA13u, // ASX Playlist + MTP_OBJ_FORMAT_PLS_PLAYLIST = 0xBA14u, // PLS Playlist + + // ---- Document formats ---- + MTP_OBJ_FORMAT_UNDEFINED_DOC = 0xBA80u, // Undefined Document + MTP_OBJ_FORMAT_ABSTRACT_DOC = 0xBA81u, // Abstract Document + MTP_OBJ_FORMAT_XML_DOC = 0xBA82u, // XML Document + MTP_OBJ_FORMAT_DOC = 0xBA83u, // Microsoft Word Document + MTP_OBJ_FORMAT_MHT_DOC = 0xBA84u, // MHT Compiled HTML Document + MTP_OBJ_FORMAT_XLS = 0xBA85u, // Microsoft Excel Spreadsheet + MTP_OBJ_FORMAT_PPT = 0xBA86u, // Microsoft PowerPoint Presentation + + // ---- Messaging ---- + MTP_OBJ_FORMAT_UNDEFINED_MSG = 0xBB00u, // Undefined Message + MTP_OBJ_FORMAT_ABSTRACT_MSG = 0xBB01u, // Abstract Message + + // ---- Bookmarks ---- + MTP_OBJ_FORMAT_UNDEFINED_BOOKMARK = 0xBB10u, // Undefined Bookmark + MTP_OBJ_FORMAT_ABSTRACT_BOOKMARK = 0xBB11u, // Abstract Bookmark + + // ---- Appointments ---- + MTP_OBJ_FORMAT_UNDEFINED_APPT = 0xBB20u, // Undefined Appointment + MTP_OBJ_FORMAT_ABSTRACT_APPT = 0xBB21u, // Abstract Appointment + MTP_OBJ_FORMAT_VCALENDAR1 = 0xBB22u, // vCalendar 1.0 + + // ---- Tasks ---- + MTP_OBJ_FORMAT_UNDEFINED_TASK = 0xBB40u, // Undefined Task + MTP_OBJ_FORMAT_ABSTRACT_TASK = 0xBB41u, // Abstract Task + MTP_OBJ_FORMAT_ICALENDAR = 0xBB42u, // iCalendar + + // ---- Notes ---- + MTP_OBJ_FORMAT_UNDEFINED_NOTE = 0xBB60u, // Undefined Note + MTP_OBJ_FORMAT_ABSTRACT_NOTE = 0xBB61u, // Abstract Note + + // ---- Contacts ---- + MTP_OBJ_FORMAT_UNDEFINED_CONTACT= 0xBB80u, // Undefined Contact + MTP_OBJ_FORMAT_ABSTRACT_CONTACT = 0xBB81u, // Abstract Contact + MTP_OBJ_FORMAT_VCARD2 = 0xBB82u, // vCard 2.1 + MTP_OBJ_FORMAT_VCARD3 = 0xBB83u, // vCard 3.0 +} mtp_object_formats_t; + +// MTP 1.1 Appendix B: Object Properties +typedef enum { + MTP_OBJ_PROP_STORAGE_ID = 0xDC01u, // StorageID + MTP_OBJ_PROP_OBJECT_FORMAT = 0xDC02u, // Object Format + MTP_OBJ_PROP_PROTECTION_STATUS = 0xDC03u, // Protection Status + MTP_OBJ_PROP_OBJECT_SIZE = 0xDC04u, // Object Size + MTP_OBJ_PROP_ASSOCIATION_TYPE = 0xDC05u, // Association Type + MTP_OBJ_PROP_ASSOCIATION_DESC = 0xDC06u, // Association Description + MTP_OBJ_PROP_OBJECT_FILE_NAME = 0xDC07u, // Object File Name + MTP_OBJ_PROP_DATE_CREATED = 0xDC08u, // Date Created + MTP_OBJ_PROP_DATE_MODIFIED = 0xDC09u, // Date Modified + MTP_OBJ_PROP_KEYWORDS = 0xDC0Au, // Keywords + MTP_OBJ_PROP_PARENT_OBJECT = 0xDC0Bu, // Parent Object + MTP_OBJ_PROP_ALLOWED_FOLDER_CONTENTS = 0xDC0Cu, // Allowed Folder Contents + MTP_OBJ_PROP_HIDDEN = 0xDC0Du, // Hidden + MTP_OBJ_PROP_SYSTEM_OBJECT = 0xDC0Eu, // System Object + // 0xDC0F-0xDC40 is reserved + + MTP_OBJ_PROP_PERSISTENT_UID = 0xDC41u, // Persistent Unique Object Identifier + MTP_OBJ_PROP_SYNC_ID = 0xDC42u, // SyncID + MTP_OBJ_PROP_PROPERTY_BAG = 0xDC43u, // Property Bag + MTP_OBJ_PROP_NAME = 0xDC44u, // Name + MTP_OBJ_PROP_CREATED_BY = 0xDC45u, // Created By + MTP_OBJ_PROP_ARTIST = 0xDC46u, // Artist + MTP_OBJ_PROP_DATE_AUTHORED = 0xDC47u, // Date Authored + MTP_OBJ_PROP_DESCRIPTION = 0xDC48u, // Description + MTP_OBJ_PROP_URL_REFERENCE = 0xDC49u, // URL Reference + MTP_OBJ_PROP_LANGUAGE_LOCALE = 0xDC4Au, // Language-Locale + MTP_OBJ_PROP_COPYRIGHT_INFO = 0xDC4Bu, // Copyright Information + MTP_OBJ_PROP_SOURCE = 0xDC4Cu, // Source + MTP_OBJ_PROP_ORIGIN_LOCATION = 0xDC4Du, // Origin Location + MTP_OBJ_PROP_DATE_ADDED = 0xDC4Eu, // Date Added + MTP_OBJ_PROP_NON_CONSUMABLE = 0xDC4Fu, // Non-Consumable + MTP_OBJ_PROP_CORRUPT_UNPLAYABLE = 0xDC50u, // Corrupt/Unplayable + MTP_OBJ_PROP_PRODUCER_SERIAL_NUMBER = 0xDC51u, // ProducerSerialNumber + // 0xDC52-0xDC80 is reserved + + MTP_OBJ_PROP_REP_SAMPLE_FORMAT = 0xDC81u, // Representative Sample Format + MTP_OBJ_PROP_REP_SAMPLE_SIZE = 0xDC82u, // Representative Sample Size + MTP_OBJ_PROP_REP_SAMPLE_HEIGHT = 0xDC83u, // Representative Sample Height + MTP_OBJ_PROP_REP_SAMPLE_WIDTH = 0xDC84u, // Representative Sample Width + MTP_OBJ_PROP_REP_SAMPLE_DURATION = 0xDC85u, // Representative Sample Duration + MTP_OBJ_PROP_REP_SAMPLE_DATA = 0xDC86u, // Representative Sample Data + MTP_OBJ_PROP_WIDTH = 0xDC87u, // Width + MTP_OBJ_PROP_HEIGHT = 0xDC88u, // Height + MTP_OBJ_PROP_DURATION = 0xDC89u, // Duration + MTP_OBJ_PROP_RATING = 0xDC8Au, // Rating + MTP_OBJ_PROP_TRACK = 0xDC8Bu, // Track + MTP_OBJ_PROP_GENRE = 0xDC8Cu, // Genre + MTP_OBJ_PROP_CREDITS = 0xDC8Du, // Credits + MTP_OBJ_PROP_LYRICS = 0xDC8Eu, // Lyrics + MTP_OBJ_PROP_SUBSCRIPTION_CONTENT_ID = 0xDC8Fu, // Subscription Content ID + MTP_OBJ_PROP_PRODUCED_BY = 0xDC90u, // Produced By + MTP_OBJ_PROP_USE_COUNT = 0xDC91u, // Use Count + MTP_OBJ_PROP_SKIP_COUNT = 0xDC92u, // Skip Count + MTP_OBJ_PROP_LAST_ACCESSED = 0xDC93u, // Last Accessed + MTP_OBJ_PROP_PARENTAL_RATING = 0xDC94u, // Parental Rating + MTP_OBJ_PROP_META_GENRE = 0xDC95u, // Meta Genre + MTP_OBJ_PROP_COMPOSER = 0xDC96u, // Composer + MTP_OBJ_PROP_EFFECTIVE_RATING = 0xDC97u, // Effective Rating + MTP_OBJ_PROP_SUBTITLE = 0xDC98u, // Subtitle + MTP_OBJ_PROP_ORIGINAL_RELEASE_DATE = 0xDC99u, // Original Release Date + MTP_OBJ_PROP_ALBUM_NAME = 0xDC9Au, // Album Name + MTP_OBJ_PROP_ALBUM_ARTIST = 0xDC9Bu, // Album Artist + MTP_OBJ_PROP_MOOD = 0xDC9Cu, // Mood + MTP_OBJ_PROP_DRM_STATUS = 0xDC9Du, // DRM Status + MTP_OBJ_PROP_SUB_DESCRIPTION = 0xDC9Eu, // Sub Description + // 0xDC9F-0xDCD0 is reserved + + MTP_OBJ_PROP_IS_CROPPED = 0xDCD1u, // Is Cropped + MTP_OBJ_PROP_IS_COLOUR_CORRECTED = 0xDCD2u, // Is Colour Corrected + MTP_OBJ_PROP_IMAGE_BIT_DEPTH = 0xDCD3u, // Image Bit Depth + MTP_OBJ_PROP_FNUMBER = 0xDCD4u, // Fnumber (aperture ×100) + MTP_OBJ_PROP_EXPOSURE_TIME = 0xDCD5u, // Exposure Time (sec ×10,000) + MTP_OBJ_PROP_EXPOSURE_INDEX = 0xDCD6u, // Exposure Index (ISO) + // 0xDCD7-0xDCDF is reserved + + MTP_OBJ_PROP_DISPLAY_NAME = 0xDCE0u, // Display Name + MTP_OBJ_PROP_BODY_TEXT = 0xDCE1u, // Body Text + MTP_OBJ_PROP_SUBJECT = 0xDCE2u, // Subject + MTP_OBJ_PROP_PRIORITY = 0xDCE3u, // Priority + // 0xDCE4-0xDCFF is reserved + + MTP_OBJ_PROP_GIVEN_NAME = 0xDD00u, // Given Name + MTP_OBJ_PROP_MIDDLE_NAMES = 0xDD01u, // Middle Names + MTP_OBJ_PROP_FAMILY_NAME = 0xDD02u, // Family Name + MTP_OBJ_PROP_PREFIX = 0xDD03u, // Prefix + MTP_OBJ_PROP_SUFFIX = 0xDD04u, // Suffix + MTP_OBJ_PROP_PHONETIC_GIVEN_NAME = 0xDD05u, // Phonetic Given Name + MTP_OBJ_PROP_PHONETIC_FAMILY_NAME = 0xDD06u, // Phonetic Family Name + MTP_OBJ_PROP_EMAIL_PRIMARY = 0xDD07u, // Email Primary + MTP_OBJ_PROP_EMAIL_PERSONAL_1 = 0xDD08u, // Email Personal 1 + MTP_OBJ_PROP_EMAIL_PERSONAL_2 = 0xDD09u, // Email Personal 2 + MTP_OBJ_PROP_EMAIL_BUSINESS_1 = 0xDD0Au, // Email Business 1 + MTP_OBJ_PROP_EMAIL_BUSINESS_2 = 0xDD0Bu, // Email Business 2 + MTP_OBJ_PROP_EMAIL_OTHERS = 0xDD0Cu, // Email Others + MTP_OBJ_PROP_PHONE_PRIMARY = 0xDD0Du, // Phone Number Primary + MTP_OBJ_PROP_PHONE_PERSONAL_1 = 0xDD0Eu, // Phone Number Personal + MTP_OBJ_PROP_PHONE_PERSONAL_2 = 0xDD0Fu, // Phone Number Personal 2 + MTP_OBJ_PROP_PHONE_BUSINESS_1 = 0xDD10u, // Phone Number Business + MTP_OBJ_PROP_PHONE_BUSINESS_2 = 0xDD11u, // Phone Number Business 2 + MTP_OBJ_PROP_PHONE_MOBILE_1 = 0xDD12u, // Phone Number Mobile + MTP_OBJ_PROP_PHONE_MOBILE_2 = 0xDD13u, // Phone Number Mobile 2 + MTP_OBJ_PROP_FAX_PRIMARY = 0xDD14u, // Fax Number Primary + MTP_OBJ_PROP_FAX_PERSONAL = 0xDD15u, // Fax Number Personal + MTP_OBJ_PROP_FAX_BUSINESS = 0xDD16u, // Fax Number Business + MTP_OBJ_PROP_PAGER_NUMBER = 0xDD17u, // Pager Number + MTP_OBJ_PROP_PHONE_OTHERS = 0xDD18u, // Phone Number Others + MTP_OBJ_PROP_WEB_PRIMARY = 0xDD19u, // Primary Web Address + MTP_OBJ_PROP_WEB_PERSONAL = 0xDD1Au, // Personal Web Address + MTP_OBJ_PROP_WEB_BUSINESS = 0xDD1Bu, // Business Web Address + MTP_OBJ_PROP_IM_ADDRESS_1 = 0xDD1Cu, // Instant Messenger Address + MTP_OBJ_PROP_IM_ADDRESS_2 = 0xDD1Du, // Instant Messenger Address 2 + MTP_OBJ_PROP_IM_ADDRESS_3 = 0xDD1Eu, // Instant Messenger Address 3 + MTP_OBJ_PROP_ADDR_PERSONAL_FULL = 0xDD1Fu, // Postal Address Personal Full + MTP_OBJ_PROP_ADDR_PERSONAL_LINE1 = 0xDD20u, // Postal Address Personal Line 1 + MTP_OBJ_PROP_ADDR_PERSONAL_LINE2 = 0xDD21u, // Postal Address Personal Line 2 + MTP_OBJ_PROP_ADDR_PERSONAL_CITY = 0xDD22u, // Postal Address Personal City + MTP_OBJ_PROP_ADDR_PERSONAL_REGION = 0xDD23u, // Postal Address Personal Region + MTP_OBJ_PROP_ADDR_PERSONAL_POSTAL_CODE = 0xDD24u, // Postal Address Personal Postal Code + MTP_OBJ_PROP_ADDR_PERSONAL_COUNTRY = 0xDD25u, // Postal Address Personal Country + MTP_OBJ_PROP_ADDR_BUSINESS_FULL = 0xDD26u, // Postal Address Business Full + MTP_OBJ_PROP_ADDR_BUSINESS_LINE1 = 0xDD27u, // Postal Address Business Line 1 + MTP_OBJ_PROP_ADDR_BUSINESS_LINE2 = 0xDD28u, // Postal Address Business Line 2 + MTP_OBJ_PROP_ADDR_BUSINESS_CITY = 0xDD29u, // Postal Address Business City + MTP_OBJ_PROP_ADDR_BUSINESS_REGION = 0xDD2Au, // Postal Address Business Region + MTP_OBJ_PROP_ADDR_BUSINESS_POSTAL_CODE = 0xDD2Bu, // Postal Address Business Postal Code + MTP_OBJ_PROP_ADDR_BUSINESS_COUNTRY = 0xDD2Cu, // Postal Address Business Country + MTP_OBJ_PROP_ADDR_OTHER_FULL = 0xDD2Du, // Postal Address Other Full + MTP_OBJ_PROP_ADDR_OTHER_LINE1 = 0xDD2Eu, // Postal Address Other Line 1 + MTP_OBJ_PROP_ADDR_OTHER_LINE2 = 0xDD2Fu, // Postal Address Other Line 2 + MTP_OBJ_PROP_ADDR_OTHER_CITY = 0xDD30u, // Postal Address Other City + MTP_OBJ_PROP_ADDR_OTHER_REGION = 0xDD31u, // Postal Address Other Region + MTP_OBJ_PROP_ADDR_OTHER_POSTAL_CODE = 0xDD32u, // Postal Address Other Postal Code + MTP_OBJ_PROP_ADDR_OTHER_COUNTRY = 0xDD33u, // Postal Address Other Country + MTP_OBJ_PROP_ORGANIZATION_NAME = 0xDD34u, // Organization Name + MTP_OBJ_PROP_PHONETIC_ORG_NAME = 0xDD35u, // Phonetic Organization Name + MTP_OBJ_PROP_ROLE = 0xDD36u, // Role + MTP_OBJ_PROP_BIRTHDATE = 0xDD37u, // Birthdate + // 0xDD38-0xDD3F is reserved + + MTP_OBJ_PROP_MESSAGE_TO = 0xDD40u, // Message To + MTP_OBJ_PROP_MESSAGE_CC = 0xDD41u, // Message CC + MTP_OBJ_PROP_MESSAGE_BCC = 0xDD42u, // Message BCC + MTP_OBJ_PROP_MESSAGE_READ = 0xDD43u, // Message Read + MTP_OBJ_PROP_MESSAGE_RECEIVED_TIME = 0xDD44u, // Message Received Time + MTP_OBJ_PROP_MESSAGE_SENDER = 0xDD45u, // Message Sender + // 0xDD46-0xDD4F is reserved + + MTP_OBJ_PROP_ACTIVITY_BEGIN_TIME = 0xDD50u, // Activity Begin Time + MTP_OBJ_PROP_ACTIVITY_END_TIME = 0xDD51u, // Activity End Time + MTP_OBJ_PROP_ACTIVITY_LOCATION = 0xDD52u, // Activity Location + // 0xDD53 is reserved + MTP_OBJ_PROP_ACTIVITY_REQUIRED_ATTENDEES= 0xDD54u, // Activity Required Attendees + MTP_OBJ_PROP_ACTIVITY_OPTIONAL_ATTENDEES= 0xDD55u, // Activity Optional Attendees + MTP_OBJ_PROP_ACTIVITY_RESOURCES = 0xDD56u, // Activity Resources + MTP_OBJ_PROP_ACTIVITY_ACCEPTED = 0xDD57u, // Activity Accepted + MTP_OBJ_PROP_ACTIVITY_TENTATIVE = 0xDD58u, // Activity Tentative + MTP_OBJ_PROP_ACTIVITY_DECLINED = 0xDD59u, // Activity Declined + MTP_OBJ_PROP_ACTIVITY_REMINDER_TIME = 0xDD5Au, // Activity Reminder Time + MTP_OBJ_PROP_ACTIVITY_OWNER = 0xDD5Bu, // Activity Owner + MTP_OBJ_PROP_ACTIVITY_STATUS = 0xDD5Cu, // Activity Status + MTP_OBJ_PROP_OWNER = 0xDD5Du, // Owner + MTP_OBJ_PROP_EDITOR = 0xDD5Eu, // Editor + MTP_OBJ_PROP_WEBMASTER = 0xDD5Fu, // Webmaster + + MTP_OBJ_PROP_URL_SOURCE = 0xDD60u, // URL Source + MTP_OBJ_PROP_URL_DESTINATION = 0xDD61u, // URL Destination + MTP_OBJ_PROP_TIME_BOOKMARK = 0xDD62u, // Time Bookmark + MTP_OBJ_PROP_OBJECT_BOOKMARK = 0xDD63u, // Object Bookmark + MTP_OBJ_PROP_BYTE_BOOKMARK = 0xDD64u, // Byte Bookmark + // 0xDD65-0xDD6F is reserved + + MTP_OBJ_PROP_LAST_BUILD_DATE = 0xDD70u, // Last Build Date + MTP_OBJ_PROP_TIME_TO_LIVE = 0xDD71u, // Time to Live (minutes) + MTP_OBJ_PROP_MEDIA_GUID = 0xDD72u, // Media GUID + // 0xDD73-0xDDFF is reserved + + // media encoding + MTP_OBJ_PROP_TOTAL_BITRATE = 0xDE91u, // Total BitRate + MTP_OBJ_PROP_BITRATE_TYPE = 0xDE92u, // Bitrate Type + MTP_OBJ_PROP_SAMPLE_RATE = 0xDE93u, // Sample Rate + MTP_OBJ_PROP_NUM_CHANNELS = 0xDE94u, // Number Of Channels + MTP_OBJ_PROP_AUDIO_BITDEPTH = 0xDE95u, // Audio BitDepth + // 0xDE96 is reserved + MTP_OBJ_PROP_SCAN_TYPE = 0xDE97u, // Scan Type + // 0xDE98 is reserved + MTP_OBJ_PROP_AUDIO_WAVE_CODEC = 0xDE99u, // Audio WAVE Codec + MTP_OBJ_PROP_AUDIO_BITRATE = 0xDE9Au, // Audio BitRate + MTP_OBJ_PROP_VIDEO_FOURCC_CODEC = 0xDE9Bu, // Video FourCC Codec + MTP_OBJ_PROP_VIDEO_BITRATE = 0xDE9Cu, // Video BitRate + MTP_OBJ_PROP_FRAMES_PER_KSEC = 0xDE9Du, // Frames Per Thousand Seconds + MTP_OBJ_PROP_KEYFRAME_DISTANCE = 0xDE9Eu, // KeyFrame Distance (ms) + MTP_OBJ_PROP_BUFFER_SIZE = 0xDE9Fu, // Buffer Size + MTP_OBJ_PROP_ENCODING_QUALITY = 0xDEA0u, // Encoding Quality + MTP_OBJ_PROP_ENCODING_PROFILE = 0xDEA1u // Encoding Profile +} mtp_object_properties_t; + + +// MTP 1.1 Appendeix C: Device Properties +typedef enum { + MTP_DEV_PROP_UNDEFINED = 0x5000u, + MTP_DEV_PROP_BATTERY_LEVEL = 0x5001u, + MTP_DEV_PROP_FUNCTIONAL_MODE = 0x5002u, + MTP_DEV_PROP_IMAGE_SIZE = 0x5003u, + MTP_DEV_PROP_COMPRESSION_SETTING = 0x5004u, + MTP_DEV_PROP_WHITE_BALANCE = 0x5005u, + MTP_DEV_PROP_RGB_GAIN = 0x5006u, + MTP_DEV_PROP_F_NUMBER = 0x5007u, + MTP_DEV_PROP_FOCAL_LENGTH = 0x5008u, + MTP_DEV_PROP_FOCUS_DISTANCE = 0x5009u, + MTP_DEV_PROP_FOCUS_MODE = 0x500Au, + MTP_DEV_PROP_EXPOSURE_METERING_MODE = 0x500Bu, + MTP_DEV_PROP_FLASH_MODE = 0x500Cu, + MTP_DEV_PROP_EXPOSURE_TIME = 0x500Du, + MTP_DEV_PROP_EXPOSURE_PROGRAM_MODE = 0x500Eu, + MTP_DEV_PROP_EXPOSURE_INDEX = 0x500Fu, + MTP_DEV_PROP_EXPOSURE_BIAS_COMPENSATION = 0x5010u, + MTP_DEV_PROP_DATE_TIME = 0x5011u, + MTP_DEV_PROP_CAPTURE_DELAY = 0x5012u, + MTP_DEV_PROP_STILL_CAPTURE_MODE = 0x5013u, + MTP_DEV_PROP_CONTRAST = 0x5014u, + MTP_DEV_PROP_SHARPNESS = 0x5015u, + MTP_DEV_PROP_DIGITAL_ZOOM = 0x5016u, + MTP_DEV_PROP_EFFECT_MODE = 0x5017u, + MTP_DEV_PROP_BURST_NUMBER = 0x5018u, + MTP_DEV_PROP_BURST_INTERVAL = 0x5019u, + MTP_DEV_PROP_TIMELAPSE_NUMBER = 0x501Au, + MTP_DEV_PROP_TIMELAPSE_INTERVAL = 0x501Bu, + MTP_DEV_PROP_FOCUS_METERING_MODE = 0x501Cu, + MTP_DEV_PROP_UPLOAD_URL = 0x501Du, + MTP_DEV_PROP_ARTIST = 0x501Eu, + MTP_DEV_PROP_COPYRIGHT_INFO = 0x501Fu, + MTP_DEV_PROP_SYNCHRONIZTION_PARTNER = 0xD401, + MTP_DEV_PROP_DEVICE_FRIENDLY_NAME = 0xD402u, + MTP_DEV_PROP_VOLUME = 0xD403u, + MTP_DEV_PROP_SUPPORTED_FORMATS_ORDERED = 0xD404u, + MTP_DEV_PROP_DEVICE_ICON = 0xD405u, + MTP_DEV_PROP_SECTION_INITIATOR_VERSION_INFO = 0xD406u, + MTP_DEV_PROP_PERCEIVED_DEVICE_TYPE = 0xD407u, + MTP_DEV_PROP_PLAYBACK_RATE = 0xD410u, + MTP_DEV_PROP_PLAYBACK_OBJECT = 0xD411u, + MTP_DEV_PROP_PLAYBACK_CONTAINER_INDEX = 0xD412u, +} mtp_event_properties_t; + +// MTP 1.1 Appendix D: Operations +typedef enum { + MTP_OP_UNDEFINED = 0x1000u, + MTP_OP_GET_DEVICE_INFO = 0x1001u, + MTP_OP_OPEN_SESSION = 0x1002u, + MTP_OP_CLOSE_SESSION = 0x1003u, + MTP_OP_GET_STORAGE_IDS = 0x1004u, + MTP_OP_GET_STORAGE_INFO = 0x1005u, + MTP_OP_GET_NUM_OBJECTS = 0x1006u, + MTP_OP_GET_OBJECT_HANDLES = 0x1007u, + MTP_OP_GET_OBJECT_INFO = 0x1008u, + MTP_OP_GET_OBJECT = 0x1009u, + MTP_OP_GET_THUMB = 0x100Au, + MTP_OP_DELETE_OBJECT = 0x100Bu, + MTP_OP_SEND_OBJECT_INFO = 0x100Cu, + MTP_OP_SEND_OBJECT = 0x100Du, + MTP_OP_INITIATE_CAPTURE = 0x100Eu, + MTP_OP_FORMAT_STORE = 0x100Fu, + MTP_OP_RESET_DEVICE = 0x1010u, + MTP_OP_SELF_TEST = 0x1011u, + MTP_OP_SET_OBJECT_PROTECTION = 0x1012u, + MTP_OP_POWER_DOWN = 0x1013u, + MTP_OP_GET_DEVICE_PROP_DESC = 0x1014u, + MTP_OP_GET_DEVICE_PROP_VALUE = 0x1015u, + MTP_OP_SET_DEVICE_PROP_VALUE = 0x1016u, + MTP_OP_RESET_DEVICE_PROP_VALUE = 0x1017u, + MTP_OP_TERMINATE_OPEN_CAPTURE = 0x1018u, + MTP_OP_MOVE_OBJECT = 0x1019u, + MTP_OP_COPY_OBJECT = 0x101Au, + MTP_OP_GET_PARTIAL_OBJECT = 0x101Bu, + MTP_OP_INITIATE_OPEN_CAPTURE = 0x101Bu, + MTP_OP_GET_OBJECT_PROPS_SUPPORTED = 0x9801u, + MTP_OP_GET_OBJECT_PROP_DESC = 0x9802u, + MTP_OP_GET_OBJECT_PROP_VALUE = 0x9803u, + MTP_OP_SET_OBJECT_PROP_VALUE = 0x9804u, + MTP_OP_GET_OBJECT_PROPLIST = 0x9805u, + MTP_OP_GET_OBJECT_PROP_REFERENCES = 0x9810u, + + MTP_OP_GET_SERVICE_IDS = 0x9301u, + MTP_OP_GET_SERVICE_INFO = 0x9302u, + MTP_OP_GET_SERVICE_CAPABILITIES = 0x9303u, + MTP_OP_GET_SERVICE_PROP_DESC = 0x9304u, + + // Appendix E: Enhanced Operations + MTP_OP_GET_OBJECT_PROP_LIST = 0x9805u, + MTP_OP_SET_OBJECT_PROP_LIST = 0x9806u, + MTP_OP_GET_INTERDEPENDENT_PROP_DESC = 0x9807u, + MTP_OP_SEND_OBJECT_PROP_LIST = 0x9808u, +} mtp_operation_code_t; + +// Appendix F: Responses +typedef enum { + MTP_RESP_UNDEFINED = 0x2000u, + MTP_RESP_OK = 0x2001u, + MTP_RESP_GENERAL_ERROR = 0x2002u, + MTP_RESP_SESSION_NOT_OPEN = 0x2003u, + MTP_RESP_INVALID_TRANSACTION_ID = 0x2004u, + MTP_RESP_OPERATION_NOT_SUPPORTED = 0x2005u, + MTP_RESP_PARAMETER_NOT_SUPPORTED = 0x2006u, + MTP_RESP_INCOMPLETE_TRANSFER = 0x2007u, + MTP_RESP_INVALID_STORAGE_ID = 0x2008u, + MTP_RESP_INVALID_OBJECT_HANDLE = 0x2009u, + MTP_RESP_DEVICE_PROP_NOT_SUPPORTED = 0x200Au, + MTP_RESP_INVALID_OBJECT_FORMAT_CODE = 0x200Bu, + MTP_RESP_STORE_FULL = 0x200Cu, + MTP_RESP_OBJECT_WRITE_PROTECTED = 0x200Du, + MPT_RESC_STORE_READ_ONLY = 0x200Eu, + MTP_RESP_ACCESS_DENIED = 0x200Fu, + MTP_RESP_NO_THUMBNAIL_PRESENT = 0x2010u, + MTP_RESP_SELF_TEST_FAILED = 0x2011u, + MTP_RESP_PARTIAL_DELETION = 0x2012u, + MTP_RESP_STORE_NOT_AVAILABLE = 0x2013u, + MTP_RESP_SPECIFICATION_BY_FORMAT_UNSUPPORTED = 0x2014u, + MTP_RESP_NO_VALID_OBJECTINFO = 0x2015u, + MTP_RESP_INVALID_CODE_FORMAT = 0x2016u, + MTP_RESP_UNKNOWN_VENDOR_CODE = 0x2017u, + MTP_RESP_CAPTURE_ALREADY_TERMINATED = 0x2018u, + MTP_RESP_DEVICE_BUSY = 0x2019u, + MTP_RESP_INVALID_PARENT_OBJECT = 0x201Au, + MTP_RESP_INVALID_DEVICE_PROP_FORMAT = 0x201Bu, + MTP_RESP_INVALID_DEVICE_PROP_VALUE = 0x201Cu, + MTP_RESP_INVALID_PARAMETER = 0x201Du, + MTP_RESP_SESSION_ALREADY_OPEN = 0x201Eu, + MTP_RESP_TRANSACTION_CANCELLED = 0x201Fu, + MTP_RESP_SPEC_OF_DESTINATION_UNSUPPORTED = 0x2020u, + + MTP_RESP_INVALID_OBJECT_PROP_CODE = 0xA801u, + MTP_RESP_INVALID_OBJECT_PROP_FORMAT = 0xA802u, + MTP_RESP_INVALID_OBJECT_PROP_VALUE = 0xA803u, + MTP_RESP_INVALID_OBJECT_REFERENCE = 0xA804u, + MTP_RESP_GROUP_NOT_SUPPORTED = 0xA805u, + MTP_RESP_INVALID_DATASET = 0xA806u, + MTP_RESP_SPEC_BY_GROUP_UNSUPPORTED = 0xA807u, + MTP_RESP_SPEC_BY_DEPTH_UNSUPPORTED = 0xA808u, + MTP_RESP_OBJECT_TOO_LARGE = 0xA809u, + MTP_RESP_OBJECT_PROP_NOT_SUPPORTED = 0xA80Au, +} mtp_response_t; + +// Appendix G: Events +typedef enum { + MTP_EVENT_UNDEFINED = 0x4000, + MTP_EVENT_CANCEL_TRANSACTION = 0x4001, + MTP_EVENT_OBJECT_ADDED = 0x4002, + MTP_EVENT_OBJECT_REMOVED = 0x4003, + MTP_EVENT_STORE_ADDED = 0x4004, + MTP_EVENT_STORE_REMOVED = 0x4005, + MTP_EVENT_DEVICE_PROP_CHANGED = 0x4006, + MTP_EVENT_OBJECT_INFO_CHANGED = 0x4007, + MTP_EVENT_DEVICE_INFO_CHANGED = 0x4008, + MTP_EVENT_REQUEST_OBJECT_TRANSFER = 0x4009, + MTP_EVENT_STORE_FULL = 0x400Au, + MTP_EVENT_DEVICE_RESET = 0x400Bu, + MTP_EVENT_STORAGE_INFO_CHANGED = 0x400Cu, + MTP_EVENT_CAPTURE_COMPLETE = 0x400Du, + MTP_EVENT_UNREPORTED_STATUS = 0x400Eu, + MTP_EVENT_OBJECT_PROP_CHANGED = 0xC801u, + MTP_EVENT_OBJECT_PROP_DESC_CHANGED = 0xC802u, + MTP_EVENT_OBJECT_REFERENCES_CHANGED = 0xC803u, +} mtp_event_code_t; + +// Datatypes +typedef enum { + MTP_DATA_TYPE_UNDEFINED = 0x0000u, + // scalars + MTP_DATA_TYPE_INT8 = 0x0001u, + MTP_DATA_TYPE_UINT8 = 0x0002u, + MTP_DATA_TYPE_INT16 = 0x0003u, + MTP_DATA_TYPE_UINT16 = 0x0004u, + MTP_DATA_TYPE_INT32 = 0x0005u, + MTP_DATA_TYPE_UINT32 = 0x0006u, + MTP_DATA_TYPE_INT64 = 0x0007u, + MTP_DATA_TYPE_UINT64 = 0x0008u, + MTP_DATA_TYPE_INT128 = 0x0009u, + MTP_DATA_TYPE_UINT128 = 0x000Au, + // array + MTP_DATA_TYPE_AINT8 = 0x4001u, + MTP_DATA_TYPE_AUINT8 = 0x4002u, + MTP_DATA_TYPE_AINT16 = 0x4003u, + MTP_DATA_TYPE_AUINT16 = 0x4004u, + MTP_DATA_TYPE_AINT32 = 0x4005u, + MTP_DATA_TYPE_AUINT32 = 0x4006u, + MTP_DATA_TYPE_AINT64 = 0x4007u, + MTP_DATA_TYPE_AUINT64 = 0x4008u, + MTP_DATA_TYPE_AINT128 = 0x4009u, + MTP_DATA_TYPE_AUINT128 = 0x400Au, + MTP_DATA_TYPE_STR = 0xFFFFu, +} mtp_data_type_t; + +// Get/Set +typedef enum { + MTP_MODE_GET = 0x00u, + MTP_MODE_GET_SET = 0x01u, +} mtp_mode_get_set_t; + +typedef enum { + MTP_STORAGE_TYPE_UNDEFINED = 0x0000u, + MTP_STORAGE_TYPE_FIXED_ROM = 0x0001u, + MTP_STORAGE_TYPE_REMOVABLE_ROM = 0x0002u, + MTP_STORAGE_TYPE_FIXED_RAM = 0x0003u, + MTP_STORAGE_TYPE_REMOVABLE_RAM = 0x0004u, +} mtp_storage_type_t; + +typedef enum { + MTP_FILESYSTEM_TYPE_UNDEFINED = 0x0000u, + MTP_FILESYSTEM_TYPE_GENERIC_FLAT = 0x0001u, + MTP_FILESYSTEM_TYPE_GENERIC_HIERARCHICAL = 0x0002u, + MTP_FILESYSTEM_TYPE_DCF = 0x0003u, +} mtp_filesystem_type_t; + +typedef enum { + MTP_ACCESS_CAPABILITY_READ_WRITE = 0x0000u, + MTP_ACCESS_CAPABILITY_READ_ONLY_WITHOUT_OBJECT_DELETION = 0x0001u, + MTP_ACCESS_CAPABILITY_READ_ONLY_WITH_OBJECT_DELETION = 0x0002u, +} mtp_access_capability_t; + +typedef enum { + MTP_PROTECTION_STATUS_NO_PROTECTION = 0x0000u, + MTP_PROTECTION_STATUS_READ_ONLY = 0x0001u, + MTP_PROTECTION_STATUS_READ_ONLY_DATA = 0x8002u, + MTP_PROTECTION_NON_TRANSFERABLE_DATA = 0x8003u, +} mtp_protection_status_t; + +typedef enum { + MTP_ASSOCIATION_UNDEFINED = 0x0000u, + MTP_ASSOCIATION_GENERIC_FOLDER = 0x0001u, + MTP_ASSOCIATION_ALBUM = 0x0002u, + MTP_ASSOCIATION_TIME_SEQUENCE = 0x0003u, + MTP_ASSOCIATION_HORIZONTAL_PANORAMIC = 0x0004u, + MTP_ASSOCIATION_VERTICAL_PANORAMIC = 0x0005u, + MTP_ASSOCIATION_2D_PANORAMIC = 0x0006u, + MTP_ASSOCIATION_ANCILLARY_DATA = 0x0007u, +} mtp_association_t; + +//--------------------------------------------------------------------+ +// Data structures +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED { + uint32_t len; + uint16_t type; + uint16_t code; + uint32_t transaction_id; +} mtp_container_header_t; +TU_VERIFY_STATIC(sizeof(mtp_container_header_t) == 12, "size is not correct"); + +typedef struct TU_ATTR_PACKED { + mtp_container_header_t header; + uint32_t params[5]; +} mtp_container_command_t; +TU_VERIFY_STATIC(sizeof(mtp_container_command_t) == 32, "size is not correct"); + +// PTP/MTP Generic container +typedef struct TU_ATTR_PACKED { + mtp_container_header_t header; + uint8_t payload[(CFG_TUD_MTP_EP_BUFSIZE - sizeof(mtp_container_header_t))]; +} mtp_generic_container_t; + +typedef struct { + mtp_container_header_t* header; + union { + uint8_t* payload; + uint16_t* payload16; + uint32_t* payload32; + }; + uint32_t payload_bytes; // available bytes for read/write +} mtp_container_info_t; + +typedef struct TU_ATTR_PACKED { + uint16_t code; + uint32_t session_id; + uint32_t transaction_id; + uint32_t params[3]; +} mtp_event_t; +TU_VERIFY_STATIC(sizeof(mtp_event_t) == 22, "size is not correct"); + +#define mtp_string_t(_nchars) \ + struct TU_ATTR_PACKED { \ + uint8_t count; /* in characters including null */ \ + uint16_t utf16[_nchars]; \ + } + +#define mtp_array_t(_type, _count) \ + struct TU_ATTR_PACKED { \ + uint32_t count; \ + _type arr[_count];\ + } + +#define mtp_aint8_t(_count) mtp_array_t(int8_t, _count) +#define mtp_auint16_t(_count) mtp_array_t(uint16_t, _count) +#define mtp_auint32_t(_count) mtp_array_t(uint32_t, _count) +#define mtp_auint64_t(_count) mtp_array_t(uint64_t, _count) + +#define MTP_STORAGE_INFO_STRUCT(_storage_desc_chars, _volume_id_chars) \ + struct TU_ATTR_PACKED { \ + uint16_t storage_type; \ + uint16_t filesystem_type; \ + uint16_t access_capability; \ + uint64_t max_capacity_in_bytes; \ + uint64_t free_space_in_bytes; \ + uint32_t free_space_in_objects; \ + mtp_string_t(_storage_desc_chars) storage_description; \ + mtp_string_t(_volume_id_chars) volume_identifier; \ + } + +// Object Info Dataset without dynamic string: filename, date_created, date_modified, keywords +typedef struct TU_ATTR_PACKED { + uint32_t storage_id; + uint16_t object_format; + uint16_t protection_status; + uint32_t object_compressed_size; + uint16_t thumb_format; + uint32_t thumb_compressed_size; + uint32_t thumb_pix_width; + uint32_t thumb_pix_height; + uint32_t image_pix_width; + uint32_t image_pix_height; + uint32_t image_bit_depth; + uint32_t parent_object; // 0: root + uint16_t association_type; + uint32_t association_desc; + uint32_t sequence_number; + // mtp_string_t() filename + // mtp_string_t() date_created + // mtp_string_t() date_modified + // mtp_string_t() keywords +} mtp_object_info_header_t; + +// Device property desc up to get/set +typedef struct TU_ATTR_PACKED { + uint16_t device_property_code; + uint16_t datatype; + uint8_t get_set; +} mtp_device_prop_desc_header_t; + +// The following fields will be dynamically added to the struct at runtime: +// - wstring factory_def_value; +// - wstring current_value_len; +// - uint8_t form_flag; + +// no form +#define MTP_DEVICE_PROPERTIES_STRUCT(_type) \ + struct TU_ATTR_PACKED { \ + uint16_t device_property_code; \ + uint16_t datatype; \ + uint8_t get_set; \ + _type factory_default; \ + _type current_value; \ + uint8_t form_flag; /* 0: none, 1: range, 2: enum */ \ + }; + +typedef struct TU_ATTR_PACKED { + uint16_t code; + uint32_t transaction_id; +} mtp_request_reset_cancel_data_t; +TU_VERIFY_STATIC(sizeof(mtp_request_reset_cancel_data_t) == 6, "size is not correct"); + +//--------------------------------------------------------------------+ +// Container helper function +// return number of bytes added +//--------------------------------------------------------------------+ + +// return payload buffer for next write +TU_ATTR_ALWAYS_INLINE static inline uint8_t* mtp_container_payload_ptr(mtp_container_info_t* p_container) { + // only 1st packet include header + uint32_t pos = p_container->header->len - sizeof(mtp_container_header_t); + while (pos > CFG_TUD_MTP_EP_BUFSIZE) { + pos -= CFG_TUD_MTP_EP_BUFSIZE; + } + return p_container->payload + pos; +} + +// only add_raw does partial copy +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_raw(mtp_container_info_t* p_container, const void* data, uint32_t len) { + uint8_t* buf = mtp_container_payload_ptr(p_container); + const uint32_t added_len = tu_min32(len, CFG_TUD_MTP_EP_BUFSIZE - p_container->header->len); + if (added_len > 0) { + memcpy(buf, data, added_len); + } + p_container->header->len += len; // always increase len, even partial copy + return added_len; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_array(mtp_container_info_t* p_container, uint8_t scalar_size, uint32_t count, const void* data) { + const uint32_t added_len = 4 + count * scalar_size; + TU_ASSERT(p_container->header->len + added_len < CFG_TUD_MTP_EP_BUFSIZE, 0); + uint8_t* buf = p_container->payload + p_container->header->len - sizeof(mtp_container_header_t); + + tu_unaligned_write32(buf, count); + p_container->header->len += 4; + buf += 4; + + memcpy(buf, data, count * scalar_size); + p_container->header->len += count * scalar_size; + + return added_len; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_string(mtp_container_info_t* p_container, uint16_t* utf16) { + uint8_t count = 0; + while (utf16[count] != 0u) { + count++; + } + const uint32_t added_len = 1u + (uint32_t) count * 2u; + TU_ASSERT(p_container->header->len + added_len < CFG_TUD_MTP_EP_BUFSIZE, 0); + uint8_t* buf = p_container->payload + p_container->header->len - sizeof(mtp_container_header_t); + + *buf++ = count; + p_container->header->len++; + + memcpy(buf, utf16, 2u * (uint32_t) count); + p_container->header->len += 2u * count; + + return added_len; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_cstring(mtp_container_info_t* p_container, const char* str) { + const uint8_t len = (uint8_t) (strlen(str) + 1); // include null + TU_ASSERT(p_container->header->len + 1 + 2 * len < CFG_TUD_MTP_EP_BUFSIZE, 0); + uint8_t* buf = p_container->payload + p_container->header->len - sizeof(mtp_container_header_t); + + if (len == 1) { + // empty string (null only): single zero byte + *buf = 0; + p_container->header->len++; + return 1u; + } else { + *buf++ = len; + p_container->header->len++; + + for (uint8_t i = 0; i < len; i++) { + buf[0] = str[i]; + buf[1] = 0; + buf += 2; + p_container->header->len += 2; + } + return 1u + 2u * len; + } +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_uint8(mtp_container_info_t* p_container, uint8_t data) { + return mtp_container_add_raw(p_container, &data, 1); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_uint16(mtp_container_info_t* p_container, uint16_t data) { + return mtp_container_add_raw(p_container, &data, 2); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_uint32(mtp_container_info_t* p_container, uint32_t data) { + return mtp_container_add_raw(p_container, &data, 4); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_uint64(mtp_container_info_t* p_container, uint64_t data) { + return mtp_container_add_raw(p_container, &data, 8); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_uint128(mtp_container_info_t* p_container, const void* data) { + return mtp_container_add_raw(p_container, data, 16); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_auint8(mtp_container_info_t* p_container, uint32_t count, const uint8_t* data) { + return mtp_container_add_array(p_container, sizeof(uint8_t), count, data); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_auint16(mtp_container_info_t* p_container, uint32_t count, const uint16_t* data) { + return mtp_container_add_array(p_container, sizeof(uint16_t), count, data); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_auint32(mtp_container_info_t* p_container, uint32_t count, const uint32_t* data) { + return mtp_container_add_array(p_container, sizeof(uint32_t), count, data); +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_get_string(uint8_t* buf, uint16_t utf16[]) { + size_t nchars = *buf++; + memcpy(utf16, buf, 2u * nchars); + return 1u + 2u * nchars; +} + +#ifdef __cplusplus + } +#endif + +#endif +#endif diff --git a/src/class/mtp/mtp_device.c b/src/class/mtp/mtp_device.c new file mode 100644 index 000000000..764019e42 --- /dev/null +++ b/src/class/mtp/mtp_device.c @@ -0,0 +1,540 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ennebi Elettronica (https://ennebielettronica.com) + * + * 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 "tusb_option.h" + +#if (CFG_TUD_ENABLED && CFG_TUD_MTP) + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "device/dcd.h" +#include "device/usbd.h" +#include "device/usbd_pvt.h" + +#include "mtp_device.h" + +// Level where CFG_TUSB_DEBUG must be at least for this driver is logged +#ifndef CFG_TUD_MTP_LOG_LEVEL + #define CFG_TUD_MTP_LOG_LEVEL CFG_TUD_LOG_LEVEL +#endif + +#define TU_LOG_DRV(...) TU_LOG(CFG_TUD_MTP_LOG_LEVEL, __VA_ARGS__) + +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK bool tud_mtp_request_cancel_cb(tud_mtp_request_cb_data_t* cb_data) { + (void) cb_data; + return false; +} +TU_ATTR_WEAK bool tud_mtp_request_device_reset_cb(tud_mtp_request_cb_data_t* cb_data) { + (void) cb_data; + return false; +} +TU_ATTR_WEAK int32_t tud_mtp_request_get_extended_event_cb(tud_mtp_request_cb_data_t* cb_data) { + (void) cb_data; + return -1; +} +TU_ATTR_WEAK int32_t tud_mtp_request_get_device_status_cb(tud_mtp_request_cb_data_t* cb_data) { + (void) cb_data; + return -1; +} +TU_ATTR_WEAK bool tud_mtp_request_vendor_cb(tud_mtp_request_cb_data_t* cb_data) { + (void) cb_data; + return false; +} +TU_ATTR_WEAK int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t * cb_data) { + (void) cb_data; + return -1; +} +TU_ATTR_WEAK int32_t tud_mtp_data_xfer_cb(tud_mtp_cb_data_t* cb_data) { + (void) cb_data; + return -1; +} +TU_ATTR_WEAK int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data) { + (void) cb_data; + return -1; +} +TU_ATTR_WEAK int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) { + (void) cb_data; + return -1; +} + +//--------------------------------------------------------------------+ +// STRUCT +//--------------------------------------------------------------------+ +typedef struct { + uint8_t rhport; + uint8_t itf_num; + uint8_t ep_in; + uint8_t ep_out; + uint8_t ep_event; + + // Bulk Only Transfer (BOT) Protocol + uint8_t phase; + + uint32_t total_len; + uint32_t xferred_len; + + uint32_t session_id; + mtp_container_command_t command; + mtp_container_header_t io_header; + + TU_ATTR_ALIGNED(4) uint8_t control_buf[CFG_TUD_MTP_EP_CONTROL_BUFSIZE]; +} mtpd_interface_t; + +typedef struct { + TUD_EPBUF_DEF(buf, CFG_TUD_MTP_EP_BUFSIZE); + TUD_EPBUF_TYPE_DEF(mtp_event_t, buf_event); +} mtpd_epbuf_t; + +//--------------------------------------------------------------------+ +// INTERNAL FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static mtpd_interface_t _mtpd_itf; +CFG_TUD_MEM_SECTION static mtpd_epbuf_t _mtpd_epbuf; + +static void preprocess_cmd(mtpd_interface_t* p_mtp, tud_mtp_cb_data_t* cb_data); + +//--------------------------------------------------------------------+ +// Debug +//--------------------------------------------------------------------+ +#if CFG_TUSB_DEBUG >= CFG_TUD_MTP_LOG_LEVEL + +TU_ATTR_UNUSED static tu_lookup_entry_t const _mpt_op_lookup[] = { +{.key = MTP_OP_UNDEFINED , .data = "Undefined" } , +{.key = MTP_OP_GET_DEVICE_INFO , .data = "GetDeviceInfo" } , +{.key = MTP_OP_OPEN_SESSION , .data = "OpenSession" } , +{.key = MTP_OP_CLOSE_SESSION , .data = "CloseSession" } , +{.key = MTP_OP_GET_STORAGE_IDS , .data = "GetStorageIDs" } , +{.key = MTP_OP_GET_STORAGE_INFO , .data = "GetStorageInfo" } , +{.key = MTP_OP_GET_NUM_OBJECTS , .data = "GetNumObjects" } , +{.key = MTP_OP_GET_OBJECT_HANDLES , .data = "GetObjectHandles" } , +{.key = MTP_OP_GET_OBJECT_INFO , .data = "GetObjectInfo" } , +{.key = MTP_OP_GET_OBJECT , .data = "GetObject" } , +{.key = MTP_OP_GET_THUMB , .data = "GetThumb" } , +{.key = MTP_OP_DELETE_OBJECT , .data = "DeleteObject" } , +{.key = MTP_OP_SEND_OBJECT_INFO , .data = "SendObjectInfo" } , +{.key = MTP_OP_SEND_OBJECT , .data = "SendObject" } , +{.key = MTP_OP_INITIATE_CAPTURE , .data = "InitiateCapture" } , +{.key = MTP_OP_FORMAT_STORE , .data = "FormatStore" } , +{.key = MTP_OP_RESET_DEVICE , .data = "ResetDevice" } , +{.key = MTP_OP_SELF_TEST , .data = "SelfTest" } , +{.key = MTP_OP_SET_OBJECT_PROTECTION , .data = "SetObjectProtection" } , +{.key = MTP_OP_POWER_DOWN , .data = "PowerDown" } , +{.key = MTP_OP_GET_DEVICE_PROP_DESC , .data = "GetDevicePropDesc" } , +{.key = MTP_OP_GET_DEVICE_PROP_VALUE , .data = "GetDevicePropValue" } , +{.key = MTP_OP_SET_DEVICE_PROP_VALUE , .data = "SetDevicePropValue" } , +{.key = MTP_OP_RESET_DEVICE_PROP_VALUE , .data = "ResetDevicePropValue" } , +{.key = MTP_OP_TERMINATE_OPEN_CAPTURE , .data = "TerminateOpenCapture" } , +{.key = MTP_OP_MOVE_OBJECT , .data = "MoveObject" } , +{.key = MTP_OP_COPY_OBJECT , .data = "CopyObject" } , +{.key = MTP_OP_GET_PARTIAL_OBJECT , .data = "GetPartialObject" } , +{.key = MTP_OP_INITIATE_OPEN_CAPTURE , .data = "InitiateOpenCapture" } , +{.key = MTP_OP_GET_OBJECT_PROPS_SUPPORTED , .data = "GetObjectPropsSupported" } , +{.key = MTP_OP_GET_OBJECT_PROP_DESC , .data = "GetObjectPropDesc" } , +{.key = MTP_OP_GET_OBJECT_PROP_VALUE , .data = "GetObjectPropValue" } , +{.key = MTP_OP_SET_OBJECT_PROP_VALUE , .data = "SetObjectPropValue" } , +{.key = MTP_OP_GET_OBJECT_PROPLIST , .data = "GetObjectPropList" } , +{.key = MTP_OP_GET_OBJECT_PROP_REFERENCES , .data = "GetObjectPropReferences" } , +{.key = MTP_OP_GET_SERVICE_IDS , .data = "GetServiceIDs" } , +{.key = MTP_OP_GET_SERVICE_INFO , .data = "GetServiceInfo" } , +{.key = MTP_OP_GET_SERVICE_CAPABILITIES , .data = "GetServiceCapabilities" } , +{.key = MTP_OP_GET_SERVICE_PROP_DESC , .data = "GetServicePropDesc" } , +{.key = MTP_OP_GET_OBJECT_PROP_LIST , .data = "GetObjectPropList" } , +{.key = MTP_OP_SET_OBJECT_PROP_LIST , .data = "SetObjectPropList" } , +{.key = MTP_OP_GET_INTERDEPENDENT_PROP_DESC , .data = "GetInterdependentPropDesc" } , +{.key = MTP_OP_SEND_OBJECT_PROP_LIST , .data = "SendObjectPropList" } +}; + +TU_ATTR_UNUSED static tu_lookup_table_t const _mtp_op_table = { + .count = TU_ARRAY_SIZE(_mpt_op_lookup), + .items = _mpt_op_lookup +}; + +TU_ATTR_UNUSED static const char* _mtp_phase_str[] = { + "Command", + "Data", + "Response", + "Error" +}; + +#endif + + +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ +static bool prepare_new_command(mtpd_interface_t* p_mtp) { + p_mtp->phase = MTP_PHASE_COMMAND; + return usbd_edpt_xfer(p_mtp->rhport, p_mtp->ep_out, _mtpd_epbuf.buf, CFG_TUD_MTP_EP_BUFSIZE, false); +} + +static bool mtpd_data_xfer(mtp_container_info_t* p_container, uint8_t ep_addr) { + mtpd_interface_t* p_mtp = &_mtpd_itf; + if (p_mtp->phase == MTP_PHASE_COMMAND) { + // 1st data block: header + payload + p_mtp->phase = MTP_PHASE_DATA; + p_mtp->xferred_len = 0; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + p_mtp->total_len = p_container->header->len; + p_container->header->type = MTP_CONTAINER_TYPE_DATA_BLOCK; + p_container->header->transaction_id = p_mtp->command.header.transaction_id; + p_mtp->io_header = *p_container->header; // save header for subsequent data + } else { + // OUT transfer: total length is at least max packet size + p_mtp->total_len = tu_max32(p_container->header->len, CFG_TUD_MTP_EP_BUFSIZE); + } + } else { + // subsequent data block: payload only + TU_ASSERT(p_mtp->phase == MTP_PHASE_DATA); + } + + const uint16_t xact_len = (uint16_t) tu_min32(p_mtp->total_len - p_mtp->xferred_len, CFG_TUD_MTP_EP_BUFSIZE); + if (xact_len) { + // already transferred all bytes in header's length. Application make an unnecessary extra call + TU_VERIFY(usbd_edpt_claim(p_mtp->rhport, ep_addr)); + TU_ASSERT(usbd_edpt_xfer(p_mtp->rhport, ep_addr, _mtpd_epbuf.buf, xact_len, false)); + } + return true; +} + +bool tud_mtp_data_send(mtp_container_info_t* p_container) { + return mtpd_data_xfer(p_container, _mtpd_itf.ep_in); +} + +bool tud_mtp_data_receive(mtp_container_info_t* p_container) { + return mtpd_data_xfer(p_container, _mtpd_itf.ep_out); +} + +bool tud_mtp_response_send(mtp_container_info_t* p_container) { + mtpd_interface_t* p_mtp = &_mtpd_itf; + p_mtp->phase = MTP_PHASE_RESPONSE; + p_container->header->type = MTP_CONTAINER_TYPE_RESPONSE_BLOCK; + p_container->header->transaction_id = p_mtp->command.header.transaction_id; + TU_VERIFY(usbd_edpt_claim(p_mtp->rhport, p_mtp->ep_in)); + return usbd_edpt_xfer(p_mtp->rhport, p_mtp->ep_in, _mtpd_epbuf.buf, (uint16_t) p_container->header->len, false); +} + +bool tud_mtp_mounted(void) { + mtpd_interface_t* p_mtp = &_mtpd_itf; + return p_mtp->ep_out != 0 && p_mtp->ep_in != 0; +} + +bool tud_mtp_event_send(mtp_event_t* event) { + mtpd_interface_t* p_mtp = &_mtpd_itf; + TU_VERIFY(p_mtp->ep_event != 0); + _mtpd_epbuf.buf_event = *event; + TU_VERIFY(usbd_edpt_claim(p_mtp->rhport, p_mtp->ep_event)); // Claim the endpoint + return usbd_edpt_xfer(p_mtp->rhport, p_mtp->ep_event, (uint8_t*) &_mtpd_epbuf.buf_event, sizeof(mtp_event_t), false); +} + +//--------------------------------------------------------------------+ +// USBD Driver API +//--------------------------------------------------------------------+ +void mtpd_init(void) { + tu_memclr(&_mtpd_itf, sizeof(mtpd_interface_t)); +} + +bool mtpd_deinit(void) { + return true; // nothing to do +} + +void mtpd_reset(uint8_t rhport) { + (void) rhport; + tu_memclr(&_mtpd_itf, sizeof(mtpd_interface_t)); +} + +uint16_t mtpd_open(uint8_t rhport, tusb_desc_interface_t const* itf_desc, uint16_t max_len) { + // only support PIMA 15470 protocol + TU_VERIFY(TUSB_CLASS_IMAGE == itf_desc->bInterfaceClass && + MTP_SUBCLASS_STILL_IMAGE == itf_desc->bInterfaceSubClass && + MTP_PROTOCOL_PIMA_15470 == itf_desc->bInterfaceProtocol, 0); + + // mtp driver length is fixed + const uint16_t mtpd_itf_size = sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t); + + // Max length must be at least 1 interface + 3 endpoints + TU_ASSERT(itf_desc->bNumEndpoints == 3 && max_len >= mtpd_itf_size); + mtpd_interface_t* p_mtp = &_mtpd_itf; + tu_memclr(p_mtp, sizeof(mtpd_interface_t)); + p_mtp->rhport = rhport; + p_mtp->itf_num = itf_desc->bInterfaceNumber; + + // Open interrupt IN endpoint + const tusb_desc_endpoint_t* ep_desc = (const tusb_desc_endpoint_t*) tu_desc_next(itf_desc); + TU_ASSERT(ep_desc->bDescriptorType == TUSB_DESC_ENDPOINT && ep_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT, 0); + TU_ASSERT(usbd_edpt_open(rhport, ep_desc), 0); + p_mtp->ep_event = ep_desc->bEndpointAddress; + + // Open endpoint pair + TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(ep_desc), 2, TUSB_XFER_BULK, &p_mtp->ep_out, &p_mtp->ep_in), 0); + TU_ASSERT(prepare_new_command(p_mtp), 0); + + return mtpd_itf_size; +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool mtpd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) { + mtpd_interface_t* p_mtp = &_mtpd_itf; + tud_mtp_request_cb_data_t cb_data = { + .idx = 0, + .stage = stage, + .session_id = p_mtp->session_id, + .request = request, + .buf = p_mtp->control_buf, + .bufsize = tu_le16toh(request->wLength), + }; + + switch (request->bRequest) { + case MTP_REQ_CANCEL: + TU_LOG_DRV(" MTP request: Cancel\n"); + if (stage == CONTROL_STAGE_SETUP) { + return tud_control_xfer(rhport, request, p_mtp->control_buf, CFG_TUD_MTP_EP_CONTROL_BUFSIZE); + } else if (stage == CONTROL_STAGE_ACK) { + return tud_mtp_request_cancel_cb(&cb_data); + } + break; + + case MTP_REQ_GET_EXT_EVENT_DATA: + TU_LOG_DRV(" MTP request: Get Extended Event Data\n"); + if (stage == CONTROL_STAGE_SETUP) { + const int32_t len = tud_mtp_request_get_extended_event_cb(&cb_data); + TU_VERIFY(len > 0); + return tud_control_xfer(rhport,request, p_mtp->control_buf, (uint16_t) len); + } + break; + + case MTP_REQ_RESET: + TU_LOG_DRV(" MTP request: Device Reset\n"); + // used by the host to return the Still Image Capture Device to the Idle state after the Bulk-pipe has stalled + if (stage == CONTROL_STAGE_SETUP) { + // clear stalled + if (usbd_edpt_stalled(rhport, p_mtp->ep_out)) { + usbd_edpt_clear_stall(rhport, p_mtp->ep_out); + } + if (usbd_edpt_stalled(rhport, p_mtp->ep_in)) { + usbd_edpt_clear_stall(rhport, p_mtp->ep_in); + } + } else if (stage == CONTROL_STAGE_ACK) { + prepare_new_command(p_mtp); + return tud_mtp_request_device_reset_cb(&cb_data); + } + break; + + case MTP_REQ_GET_DEVICE_STATUS: { + TU_LOG_DRV(" MTP request: Get Device Status\n"); + if (stage == CONTROL_STAGE_SETUP) { + const int32_t len = tud_mtp_request_get_device_status_cb(&cb_data); + TU_VERIFY(len > 0); + return tud_control_xfer(rhport, request, p_mtp->control_buf, (uint16_t) len); + } + break; + } + + default: + return tud_mtp_request_vendor_cb(&cb_data); + } + + return true; +} + +// Transfer on bulk endpoints +bool mtpd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { + if (ep_addr == _mtpd_itf.ep_event) { + // nothing to do + return true; + } + + mtpd_interface_t* p_mtp = &_mtpd_itf; + mtp_generic_container_t* p_container = (mtp_generic_container_t*) _mtpd_epbuf.buf; + +#if CFG_TUSB_DEBUG >= CFG_TUD_MTP_LOG_LEVEL + tu_lookup_find(&_mtp_op_table, p_mtp->command.header.code); + TU_LOG_DRV(" MTP %s: %s phase\r\n", (const char *) tu_lookup_find(&_mtp_op_table, p_mtp->command.header.code), + _mtp_phase_str[p_mtp->phase]); +#endif + + const mtp_container_info_t headered_packet = { + .header = &p_container->header, + .payload = p_container->payload, + .payload_bytes = CFG_TUD_MTP_EP_BUFSIZE - sizeof(mtp_container_header_t) + }; + + const mtp_container_info_t headerless_packet = { + .header = &p_mtp->io_header, + .payload = _mtpd_epbuf.buf, + .payload_bytes = CFG_TUD_MTP_EP_BUFSIZE + }; + + tud_mtp_cb_data_t cb_data; + cb_data.idx = 0; + cb_data.phase = p_mtp->phase; + cb_data.session_id = p_mtp->session_id; + cb_data.command_container = &p_mtp->command; + cb_data.io_container = headered_packet; + cb_data.total_xferred_bytes = 0; + cb_data.xfer_result = event; + + switch (p_mtp->phase) { + case MTP_PHASE_COMMAND: { + // received new command + TU_VERIFY(ep_addr == p_mtp->ep_out && p_container->header.type == MTP_CONTAINER_TYPE_COMMAND_BLOCK); + memcpy(&p_mtp->command, p_container, sizeof(mtp_container_command_t)); // save new command + p_container->header.len = sizeof(mtp_container_header_t); // default container to header only + preprocess_cmd(p_mtp, &cb_data); + if (tud_mtp_command_received_cb(&cb_data) < 0) { + p_mtp->phase = MTP_PHASE_ERROR; + } + break; + } + + case MTP_PHASE_DATA: { + const uint16_t bulk_mps = (tud_speed_get() == TUSB_SPEED_HIGH) ? 512 : 64; + p_mtp->xferred_len += xferred_bytes; + cb_data.total_xferred_bytes = p_mtp->xferred_len; + + bool is_complete = false; + // complete if ZLP or short packet or overflow + if (xferred_bytes == 0 || // ZLP + (xferred_bytes & (bulk_mps - 1)) || // short packet + p_mtp->xferred_len > p_mtp->total_len) { + is_complete = true; + } + + if (ep_addr == p_mtp->ep_in) { + // Data In + if (is_complete) { + cb_data.io_container.header->len = sizeof(mtp_container_header_t); + tud_mtp_data_complete_cb(&cb_data); + } else { + // 2nd+ packet: payload only + cb_data.io_container = headerless_packet; + tud_mtp_data_xfer_cb(&cb_data); + } + } else { + // Data Out + if (p_mtp->xferred_len == xferred_bytes) { + // 1st OUT packet: header + payload + p_mtp->io_header = p_container->header; // save header for subsequent transaction + cb_data.io_container.payload_bytes = xferred_bytes - sizeof(mtp_container_header_t); + } else { + // 2nd+ packet: payload only + cb_data.io_container = headerless_packet; + cb_data.io_container.payload_bytes = xferred_bytes; + } + tud_mtp_data_xfer_cb(&cb_data); + + if (is_complete) { + // back to header + payload for response + cb_data.io_container = headered_packet; + cb_data.io_container.header->len = sizeof(mtp_container_header_t); + tud_mtp_data_complete_cb(&cb_data); + } + } + break; + } + + case MTP_PHASE_RESPONSE: + // response phase is complete -> prepare for new command + TU_ASSERT(ep_addr == p_mtp->ep_in); + tud_mtp_response_complete_cb(&cb_data); + prepare_new_command(p_mtp); + break; + + case MTP_PHASE_ERROR: + // handled after switch, supposedly to be empty + break; + default: return false; + } + + if (p_mtp->phase == MTP_PHASE_ERROR) { + // stall both IN & OUT endpoints + usbd_edpt_stall(rhport, p_mtp->ep_out); + usbd_edpt_stall(rhport, p_mtp->ep_in); + } + + return true; +} + + +//--------------------------------------------------------------------+ +// MTPD Internal functionality +//--------------------------------------------------------------------+ + +// pre-processed commands +void preprocess_cmd(mtpd_interface_t* p_mtp, tud_mtp_cb_data_t* cb_data) { + switch (p_mtp->command.header.code) { + case MTP_OP_GET_DEVICE_INFO: { + tud_mtp_device_info_t dev_info = { + .standard_version = 100, + .mtp_vendor_extension_id = 6, // MTP specs say 0xFFFFFFFF but libMTP check for value 6 + .mtp_version = 100, + .mtp_extensions = { + .count = sizeof(CFG_TUD_MTP_DEVICEINFO_EXTENSIONS), + .utf16 = { 0 } + }, + .functional_mode = 0x0000, + .supported_operations = { + .count = TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS), + .arr = { CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS } + }, + .supported_events = { + .count = TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS), + .arr = { CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS } + }, + .supported_device_properties = { + .count = TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES), + .arr = { CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES } + }, + .capture_formats = { + .count = TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS), + .arr = { CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS } + }, + .playback_formats = { + .count = TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS), + .arr = { CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS } + } + }; + + for (uint8_t i=0; i < dev_info.mtp_extensions.count; i++) { + dev_info.mtp_extensions.utf16[i] = (uint16_t)CFG_TUD_MTP_DEVICEINFO_EXTENSIONS[i]; + } + + mtp_container_add_raw(&cb_data->io_container, &dev_info, sizeof(tud_mtp_device_info_t)); + break; + } + + default: + break; + } +} + +#endif diff --git a/src/class/mtp/mtp_device.h b/src/class/mtp/mtp_device.h new file mode 100644 index 000000000..a33f1dc08 --- /dev/null +++ b/src/class/mtp/mtp_device.h @@ -0,0 +1,169 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ennebi Elettronica (https://ennebielettronica.com) + * + * 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 IN0 + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_MTP_DEVICE_H_ +#define TUSB_MTP_DEVICE_H_ + +#include "common/tusb_common.h" +#include "mtp.h" + +#if (CFG_TUD_ENABLED && CFG_TUD_MTP) + +#ifdef __cplusplus + extern "C" { +#endif + +// callback data for Bulk Only Transfer (BOT) protocol +typedef struct { + uint8_t idx; // mtp instance + uint8_t phase; // current phase + uint32_t session_id; + + const mtp_container_command_t* command_container; + mtp_container_info_t io_container; + + tusb_xfer_result_t xfer_result; + uint32_t total_xferred_bytes; // number of bytes transferred so far in this phase +} tud_mtp_cb_data_t; + +// callback data for Control requests +typedef struct { + uint8_t idx; + uint8_t stage; // control stage + + // buffer for data stage + uint16_t bufsize; + uint8_t* buf; + + const tusb_control_request_t* request; + + uint32_t session_id; +} tud_mtp_request_cb_data_t; + +// Number of supported operations, events, device properties, capture formats, playback formats +// and max number of characters for strings manufacturer, model, device_version, serial_number +#define MTP_DEVICE_INFO_STRUCT(_extension_nchars, _op_count, _event_count, _devprop_count, _capture_count, _playback_count) \ + struct TU_ATTR_PACKED { \ + uint16_t standard_version; \ + uint32_t mtp_vendor_extension_id; \ + uint16_t mtp_version; \ + mtp_string_t(_extension_nchars) mtp_extensions; \ + uint16_t functional_mode; \ + mtp_auint16_t(_op_count) supported_operations; \ + mtp_auint16_t(_event_count) supported_events; \ + mtp_auint16_t(_devprop_count) supported_device_properties; \ + mtp_auint16_t(_capture_count) capture_formats; \ + mtp_auint16_t(_playback_count) playback_formats; \ + /* string fields will be added using append function */ \ + } + +typedef MTP_DEVICE_INFO_STRUCT( //-V2586 [MISRA-C-18.7] Flexible array members should not be declared + sizeof(CFG_TUD_MTP_DEVICEINFO_EXTENSIONS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS), + TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES), + TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS) +) tud_mtp_device_info_t; + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// check if mtp interface is mounted +bool tud_mtp_mounted(void); + +// send data phase +bool tud_mtp_data_send(mtp_container_info_t* p_container); + +// receive data phase +bool tud_mtp_data_receive(mtp_container_info_t* p_container); + +// send response +bool tud_mtp_response_send(mtp_container_info_t* p_container); + +// send event notification on event endpoint +bool tud_mtp_event_send(mtp_event_t* event); + +//--------------------------------------------------------------------+ +// Control request Callbacks +//--------------------------------------------------------------------+ + +// Invoked when received Cancel request. Data is available in callback data's buffer +// return false to stall the request +bool tud_mtp_request_cancel_cb(tud_mtp_request_cb_data_t* cb_data); + +// Invoked when received Device Reset request +// return false to stall the request +bool tud_mtp_request_device_reset_cb(tud_mtp_request_cb_data_t* cb_data); + +// Invoked when received Get Extended Event request. Application fill callback data's buffer for response +// return negative to stall the request +int32_t tud_mtp_request_get_extended_event_cb(tud_mtp_request_cb_data_t* cb_data); + +// Invoked when received Get DeviceStatus request. Application fill callback data's buffer for response +// return negative to stall the request +int32_t tud_mtp_request_get_device_status_cb(tud_mtp_request_cb_data_t* cb_data); + +// Invoked when received vendor-specific request not in the above standard MTP requests +// return false to stall the request +bool tud_mtp_request_vendor_cb(tud_mtp_request_cb_data_t* cb_data); + +//--------------------------------------------------------------------+ +// Bulk only protocol Callbacks +//--------------------------------------------------------------------+ + +// Invoked when new command is received. Application fill the cb_data->io_container and call tud_mtp_data_send() or +// tud_mtp_response_send() for Data or Response phase. +// Return negative to stall the endpoints +int32_t tud_mtp_command_received_cb(tud_mtp_cb_data_t * cb_data); + +// Invoked when a data packet is transferred. If data spans over multiple packets, application can use +// total_xferred_bytes and io_container's payload_bytes to determine the offset and remaining bytes to be transferred. +// Return negative to stall the endpoints +int32_t tud_mtp_data_xfer_cb(tud_mtp_cb_data_t* cb_data); + +// Invoked when all bytes in DATA phase is complete. A response packet is expected +// Return negative to stall the endpoints +int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data); + +// Invoked when response phase is complete +// Return negative to stall the endpoints +int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void mtpd_init (void); +bool mtpd_deinit (void); +void mtpd_reset (uint8_t rhport); +uint16_t mtpd_open (uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len); +bool mtpd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const *p_request); +bool mtpd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); + +#ifdef __cplusplus + } +#endif + +#endif +#endif diff --git a/src/class/net/ecm_rndis_device.c b/src/class/net/ecm_rndis_device.c index 299eb97c8..eaa82c187 100644 --- a/src/class/net/ecm_rndis_device.c +++ b/src/class/net/ecm_rndis_device.c @@ -35,8 +35,6 @@ #include "net_device.h" #include "rndis_protocol.h" -extern void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */ - #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t) #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0 @@ -84,12 +82,12 @@ static bool can_xmit; static bool ecm_link_is_up = true; // Store link state for ECM mode void tud_network_recv_renew(void) { - usbd_edpt_xfer(0, _netd_itf.ep_out, _netd_epbuf.rx, NETD_PACKET_SIZE); + usbd_edpt_xfer(0, _netd_itf.ep_out, _netd_epbuf.rx, NETD_PACKET_SIZE, false); } static void do_in_xfer(uint8_t *buf, uint16_t len) { can_xmit = false; - usbd_edpt_xfer(0, _netd_itf.ep_in, buf, len); + usbd_edpt_xfer(0, _netd_itf.ep_in, buf, len, false); } void netd_report(uint8_t *buf, uint16_t len) { @@ -102,7 +100,7 @@ void netd_report(uint8_t *buf, uint16_t len) { } memcpy(_netd_epbuf.notify, buf, len); - usbd_edpt_xfer(rhport, _netd_itf.ep_notif, _netd_epbuf.notify, len); + usbd_edpt_xfer(rhport, _netd_itf.ep_notif, _netd_epbuf.notify, len, false); } //--------------------------------------------------------------------+ diff --git a/src/class/net/ncm.h b/src/class/net/ncm.h index 0245a87f2..8989fe0b4 100644 --- a/src/class/net/ncm.h +++ b/src/class/net/ncm.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_NCM_H_ -#define _TUSB_NCM_H_ +#ifndef TUSB_NCM_H_ +#define TUSB_NCM_H_ #include "common/tusb_common.h" diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 02833c5f1..3e19b5f3a 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -50,10 +50,6 @@ #if (CFG_TUD_ENABLED && CFG_TUD_NCM) -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> - #include "device/usbd.h" #include "device/usbd_pvt.h" @@ -205,7 +201,7 @@ static void notification_xmit(uint8_t rhport, bool force_next) { uint16_t notif_len = sizeof(notify_speed_change.header) + notify_speed_change.header.wLength; ncm_epbuf.epnotif = notify_speed_change; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t*) &ncm_epbuf.epnotif, notif_len); + usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t*) &ncm_epbuf.epnotif, notif_len, false); ncm_interface.notification_xmit_state = NOTIFICATION_CONNECTED; ncm_interface.notification_xmit_is_running = true; @@ -227,7 +223,7 @@ static void notification_xmit(uint8_t rhport, bool force_next) { uint16_t notif_len = sizeof(notify_connected.header) + notify_connected.header.wLength; ncm_epbuf.epnotif = notify_connected; - usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_epbuf.epnotif, notif_len); + usbd_edpt_xfer(rhport, ncm_interface.ep_notif, (uint8_t *) &ncm_epbuf.epnotif, notif_len, false); ncm_interface.notification_xmit_state = NOTIFICATION_DONE; ncm_interface.notification_xmit_is_running = true; @@ -331,7 +327,7 @@ static bool xmit_insert_required_zlp(uint8_t rhport, uint32_t xferred_bytes) { TU_LOG_DRV("xmit_insert_required_zlp! (%u)\n", (unsigned) xferred_bytes); // start transmission of the ZLP - usbd_edpt_xfer(rhport, ncm_interface.ep_in, NULL, 0); + usbd_edpt_xfer(rhport, ncm_interface.ep_in, NULL, 0, false); return true; } // xmit_insert_required_zlp @@ -377,7 +373,7 @@ static void xmit_start_if_possible(uint8_t rhport) { } // Kick off an endpoint transfer - usbd_edpt_xfer(0, ncm_interface.ep_in, ncm_interface.xmit_tinyusb_ntb->data, ncm_interface.xmit_tinyusb_ntb->nth.wBlockLength); + usbd_edpt_xfer(0, ncm_interface.ep_in, ncm_interface.xmit_tinyusb_ntb->data, ncm_interface.xmit_tinyusb_ntb->nth.wBlockLength, false); } // xmit_start_if_possible /** @@ -526,7 +522,7 @@ static void recv_try_to_start_new_reception(uint8_t rhport) { // initiate transfer TU_LOG_DRV(" start reception\n"); - bool r = usbd_edpt_xfer(rhport, ncm_interface.ep_out, ncm_interface.recv_tinyusb_ntb->data, CFG_TUD_NCM_OUT_NTB_MAX_SIZE); + bool r = usbd_edpt_xfer(rhport, ncm_interface.ep_out, ncm_interface.recv_tinyusb_ntb->data, CFG_TUD_NCM_OUT_NTB_MAX_SIZE, false); if (!r) { recv_put_ntb_into_free_list(ncm_interface.recv_tinyusb_ntb); ncm_interface.recv_tinyusb_ntb = NULL; diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index fff2623b7..96c03fd61 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_NET_DEVICE_H_ -#define _TUSB_NET_DEVICE_H_ +#ifndef TUSB_NET_DEVICE_H_ +#define TUSB_NET_DEVICE_H_ #include <stdint.h> #include "class/cdc/cdc.h" @@ -56,6 +56,13 @@ typedef enum #endif //--------------------------------------------------------------------+ +// Implemented by Application +//--------------------------------------------------------------------+ +#if CFG_TUD_ECM_RNDIS +extern void rndis_class_set_handler(uint8_t *data, int size); +#endif + +//--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ @@ -107,4 +114,4 @@ void netd_report (uint8_t *buf, uint16_t len); } #endif -#endif /* _TUSB_NET_DEVICE_H_ */ +#endif /* TUSB_NET_DEVICE_H_ */ diff --git a/src/class/usbtmc/usbtmc.h b/src/class/usbtmc/usbtmc.h index 327de087c..3bf5e1a17 100644 --- a/src/class/usbtmc/usbtmc.h +++ b/src/class/usbtmc/usbtmc.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBTMC_H__ -#define _TUSB_USBTMC_H__ +#ifndef TUSB_USBTMC_H__ +#define TUSB_USBTMC_H__ #include "common/tusb_common.h" diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index 3f6bedd4c..4b0bb01ec 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -261,7 +261,7 @@ bool tud_usbtmc_transmit_dev_msg_data( bool stateChanged = atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) packetLen)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) packetLen, false)); return true; } @@ -273,7 +273,7 @@ bool tud_usbtmc_transmit_notification_data(const void *data, size_t len) { TU_VERIFY(usbd_edpt_busy(usbtmc_state.rhport, usbtmc_state.ep_int_in)); TU_VERIFY(tu_memcpy_s(usbtmc_epbuf.epnotif, CFG_TUD_USBTMC_INT_EP_SIZE, data, len) == 0); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_epbuf.epnotif, (uint16_t) len)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_epbuf.epnotif, (uint16_t) len, false)); return true; } @@ -396,7 +396,7 @@ bool tud_usbtmc_start_bus_read(void) { default: return false; } - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_epbuf.epout, (uint16_t) usbtmc_state.ep_bulk_out_wMaxPacketSize)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_epbuf.epout, (uint16_t) usbtmc_state.ep_bulk_out_wMaxPacketSize, false)); return true; } @@ -567,7 +567,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint if (usbtmc_state.transfer_size_remaining >= USBTMCD_BUFFER_SIZE) { // Copy buffer to ensure alignment correctness memcpy(usbtmc_epbuf.epin, usbtmc_state.devInBuffer, USBTMCD_BUFFER_SIZE); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, USBTMCD_BUFFER_SIZE)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, USBTMCD_BUFFER_SIZE, false)); usbtmc_state.devInBuffer += USBTMCD_BUFFER_SIZE; usbtmc_state.transfer_size_remaining -= USBTMCD_BUFFER_SIZE; usbtmc_state.transfer_size_sent += USBTMCD_BUFFER_SIZE; @@ -578,7 +578,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint usbtmc_state.transfer_size_sent += packetLen; usbtmc_state.transfer_size_remaining = 0; usbtmc_state.devInBuffer = NULL; - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) packetLen)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) packetLen, false)); if (((packetLen % usbtmc_state.ep_bulk_in_wMaxPacketSize) != 0) || (packetLen == 0)) { usbtmc_state.state = STATE_TX_SHORTED; } @@ -587,7 +587,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint case STATE_ABORTING_BULK_IN: // need to send short packet (ZLP?) - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) 0u)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) 0u, false)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; return true; @@ -713,7 +713,7 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request criticalLeave(); if (usbtmc_state.transfer_size_sent == 0) { // Send short packet, nothing is in the buffer yet - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) 0u)); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) 0u, false)); usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; } TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); @@ -841,7 +841,7 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request }, .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status))}; // Must be queued before control request response sent (USB488v1.0 4.3.1.2) - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void *) &intMsg, sizeof(intMsg)); + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void *) &intMsg, sizeof(intMsg), false); } } else { rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 27724b194..7da4d2239 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -202,8 +202,9 @@ void vendord_reset(uint8_t rhport) { vendord_interface_t* p_itf = &_vendord_itf[i]; tu_memclr(p_itf, ITF_MEM_RESET_SIZE); tu_edpt_stream_clear(&p_itf->rx.stream); - tu_edpt_stream_clear(&p_itf->tx.stream); tu_edpt_stream_close(&p_itf->rx.stream); + + tu_edpt_stream_clear(&p_itf->tx.stream); tu_edpt_stream_close(&p_itf->tx.stream); } } @@ -233,16 +234,18 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - // open endpoint stream, skip if already opened + // open endpoint stream, skip if already opened (multiple IN/OUT endpoints) if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - if (p_vendor->tx.stream.ep_addr == 0) { - tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep); - tud_vendor_n_write_flush(itf); + tu_edpt_stream_t *stream_tx = &p_vendor->tx.stream; + if (stream_tx->ep_addr == 0) { + tu_edpt_stream_open(stream_tx, desc_ep); + tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data } } else { - if (p_vendor->rx.stream.ep_addr == 0) { - tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep); - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data + tu_edpt_stream_t *stream_rx = &p_vendor->rx.stream; + if (stream_rx->ep_addr == 0) { + tu_edpt_stream_open(stream_rx, desc_ep); + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare for incoming data } } } diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 5fe4fc9ff..5376f3917 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_VENDOR_DEVICE_H_ -#define _TUSB_VENDOR_DEVICE_H_ +#ifndef TUSB_VENDOR_DEVICE_H_ +#define TUSB_VENDOR_DEVICE_H_ #include "common/tusb_common.h" @@ -141,4 +141,4 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, u } #endif -#endif /* _TUSB_VENDOR_DEVICE_H_ */ +#endif /* TUSB_VENDOR_DEVICE_H_ */ diff --git a/src/class/vendor/vendor_host.h b/src/class/vendor/vendor_host.h index acfebe7a4..00e3c3402 100644 --- a/src/class/vendor/vendor_host.h +++ b/src/class/vendor/vendor_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_VENDOR_HOST_H_ -#define _TUSB_VENDOR_HOST_H_ +#ifndef TUSB_VENDOR_HOST_H_ +#define TUSB_VENDOR_HOST_H_ #include "common/tusb_common.h" @@ -64,4 +64,4 @@ void cush_close(uint8_t dev_addr); } #endif -#endif /* _TUSB_VENDOR_HOST_H_ */ +#endif /* TUSB_VENDOR_HOST_H_ */ diff --git a/src/class/video/video.h b/src/class/video/video.h index f348e187b..5bdf4b840 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -219,11 +219,11 @@ typedef enum { uint8_t baInterfaceNr[_nitf]; \ } -typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t; -typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t; -typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t; -typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t; -typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t; +typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t; //-V2586 incorrectly detected as flexible array typedef struct TU_ATTR_PACKED { uint8_t bLength; diff --git a/src/class/video/video_device.c b/src/class/video/video_device.c index 5c00cc358..b2375def9 100644 --- a/src/class/video/video_device.c +++ b/src/class/video/video_device.c @@ -103,7 +103,7 @@ typedef struct TU_ATTR_PACKED { uint8_t index_vc; /* index of bound video control interface */ uint8_t index_vs; /* index from the video control interface */ struct { - uint16_t beg; /* Offset of the begging of video streaming interface descriptor */ + uint16_t beg; /* Offset of the beginning of video streaming interface descriptor */ uint16_t end; /* Offset of the end of video streaming interface descriptor */ uint16_t cur; /* Offset of the current settings */ uint16_t ep[2]; /* Offset of endpoint descriptors. 0: streaming, 1: still capture */ @@ -214,6 +214,12 @@ TU_ATTR_WEAK int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, return VIDEO_ERROR_NONE; } +TU_ATTR_WEAK void tud_video_prepare_payload_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, tud_video_payload_request_t* request) { + (void) ctl_idx; + (void) stm_idx; + (void) request; +} + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -244,9 +250,13 @@ static inline uint8_t _desc_ep_addr(void const *desc) { * @return instance */ static videod_streaming_interface_t* _get_instance_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { videod_interface_t *ctl = &_videod_itf[ctl_idx]; - if (!ctl->beg) return NULL; + if (!ctl->beg) { + return NULL; + } videod_streaming_interface_t *stm = &_videod_streaming_itf[ctl->stm[stm_idx]]; - if (!stm->desc.beg) return NULL; + if (!stm->desc.beg) { + return NULL; + } return stm; } @@ -255,7 +265,9 @@ static tusb_desc_vc_itf_t const* _get_desc_vc(videod_interface_t const *self) { } static tusb_desc_vs_itf_t const* _get_desc_vs(videod_streaming_interface_t const *self) { - if (!self->desc.cur) return NULL; + if (!self->desc.cur) { + return NULL; + } uint8_t const *desc = _videod_itf[self->index_vc].beg; return (tusb_desc_vs_itf_t const*)(desc + self->desc.cur); } @@ -366,8 +378,12 @@ static void const* _find_desc_ep(void const *beg, void const *end) { for (void const *cur = beg; cur < end; cur = tu_desc_next(cur)) { uint_fast8_t desc_type = tu_desc_type(cur); - if (TUSB_DESC_ENDPOINT == desc_type) return cur; - if (TUSB_DESC_INTERFACE == desc_type) break; + if (TUSB_DESC_ENDPOINT == desc_type) { + return cur; + } + if (TUSB_DESC_INTERFACE == desc_type) { + break; + } } return end; } @@ -453,8 +469,10 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); uint_fast8_t fmtnum = param->bFormatIndex; TU_ASSERT(vs && fmtnum <= vs->stm.bNumFormats); - if (!fmtnum) { - if (1 < vs->stm.bNumFormats) return true; /* Need to negotiate all variables. */ + if (0 == fmtnum) { + if (1 < vs->stm.bNumFormats) { + return true; /* Need to negotiate all variables. */ + } fmtnum = 1; param->bFormatIndex = 1; } @@ -492,8 +510,10 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm uint_fast8_t frmnum = param->bFrameIndex; TU_ASSERT(frmnum <= fmt->bNumFrameDescriptors); - if (!frmnum) { - if (1 < fmt->bNumFrameDescriptors) return true; + if (0 == frmnum) { + if (1 < fmt->bNumFrameDescriptors) { + return true; + } frmnum = 1; param->bFrameIndex = 1; } @@ -502,7 +522,7 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm /* Set the parameters determined by the frame */ uint_fast32_t frame_size = param->dwMaxVideoFrameSize; - if (!frame_size) { + if (0 == frame_size) { switch (fmt->bDescriptorSubType) { case VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED: frame_size = (uint_fast32_t)frm->wWidth * frm->wHeight * fmt->uncompressed.bBitsPerPixel / 8; @@ -522,7 +542,7 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm } uint_fast32_t interval = param->dwFrameInterval; - if (!interval) { + if (0 == interval) { if ((1 < frm->uncompressed.bFrameIntervalType) || ((0 == frm->uncompressed.bFrameIntervalType) && (frm->uncompressed.dwFrameInterval[1] != frm->uncompressed.dwFrameInterval[0]))) { @@ -532,7 +552,7 @@ static bool _update_streaming_parameters(videod_streaming_interface_t const *stm param->dwFrameInterval = interval; } uint_fast32_t interval_ms = interval / 10000; - TU_ASSERT(interval_ms); + TU_ASSERT(interval_ms != 0); uint_fast32_t payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; if (CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE < payload_size) { payload_size = CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE; @@ -550,7 +570,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * video_probe_and_commit_control_t *param) { uint_fast8_t const fmtnum = param->bFormatIndex; - if (!fmtnum) { + if (0 == fmtnum) { switch (request) { case VIDEO_REQUEST_GET_MAX: if (_get_desc_vs(stm)) @@ -581,7 +601,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * } uint_fast8_t frmnum = param->bFrameIndex; - if (!frmnum) { + if (0 == frmnum) { tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); TU_ASSERT(vs); void const *end = _end_of_streaming_descriptor(vs); @@ -637,7 +657,7 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * return true; } - if (!param->dwFrameInterval) { + if (0 == param->dwFrameInterval) { tusb_desc_vs_itf_t const *vs = _get_desc_vs(stm); TU_ASSERT(vs); void const *end = _end_of_streaming_descriptor(vs); @@ -686,12 +706,12 @@ static bool _negotiate_streaming_parameters(videod_streaming_interface_t const * default: return false; } param->dwFrameInterval = interval; - if (!interval) { + if (0 == interval) { param->dwMaxPayloadTransferSize = 0; } else { uint_fast32_t frame_size = param->dwMaxVideoFrameSize; uint_fast32_t payload_size; - if (!interval_ms) { + if (0 == interval_ms) { payload_size = frame_size + 2; } else { payload_size = (frame_size + interval_ms - 1) / interval_ms + 2; @@ -719,7 +739,7 @@ static bool _close_vc_itf(uint8_t rhport, videod_interface_t *self) /* The end of the video control interface descriptor. */ void const *end = _end_of_control_descriptor(vc); - if (vc->std.bNumEndpoints) { + if (vc->std.bNumEndpoints != 0) { /* Find the notification endpoint descriptor. */ cur = _find_desc(cur, end, TUSB_DESC_ENDPOINT); TU_ASSERT(cur < end); @@ -757,7 +777,7 @@ static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t cur += vc->std.bLength + vc->ctl.bLength; TU_LOG_DRV(" bNumEndpoints %d\r\n", vc->std.bNumEndpoints); /* Open the notification endpoint if it exist. */ - if (vc->std.bNumEndpoints) { + if (vc->std.bNumEndpoints != 0) { /* Support for 1 endpoint only. */ TU_VERIFY(1 == vc->std.bNumEndpoints); /* Find the notification endpoint descriptor. */ @@ -843,7 +863,7 @@ static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint stm->desc.ep[i] = (uint16_t) (cur - desc); TU_LOG_DRV(" open EP%02x\r\n", _desc_ep_addr(cur)); } - if (altnum) { + if (altnum != 0) { stm->state = VS_STATE_STREAMING; } TU_LOG_DRV(" done\r\n"); @@ -860,7 +880,16 @@ static uint_fast16_t _prepare_in_payload(videod_streaming_interface_t *stm, uint } TU_ASSERT(pkt_len >= hdr_len); uint_fast16_t data_len = pkt_len - hdr_len; - memcpy(&ep_buf[hdr_len], stm->buffer + stm->offset, data_len); + if (stm->buffer) { + memcpy(&ep_buf[hdr_len], stm->buffer + stm->offset, data_len); + } else { + tud_video_payload_request_t rqst = { + .buf = &ep_buf[hdr_len], + .length = data_len, + .offset = stm->offset + }; + tud_video_prepare_payload_cb(stm->index_vc, stm->index_vs, &rqst); + } stm->offset += data_len; remaining -= data_len; if (!remaining) { @@ -929,16 +958,14 @@ static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, &self->power_mode, sizeof(self->power_mode)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get_set, sizeof(_cap_get_set)), VIDEO_ERROR_UNKNOWN); } @@ -951,15 +978,13 @@ static int handle_video_ctl_cs_req(uint8_t rhport, uint8_t stage, case VIDEO_VC_CTL_REQUEST_ERROR_CODE: switch (request->bRequest) { case VIDEO_REQUEST_GET_CUR: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(tud_control_xfer(rhport, request, &self->error_code, sizeof(uint8_t)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_INFO: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(tud_control_xfer(rhport, request, (uint8_t*)(uintptr_t) &_cap_get, sizeof(_cap_get)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; @@ -986,7 +1011,7 @@ static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, case TUSB_REQ_TYPE_CLASS: { uint_fast8_t entity_id = TU_U16_HIGH(request->wIndex); - if (!entity_id) { + if (0 == entity_id) { return handle_video_ctl_cs_req(rhport, stage, request, ctl_idx); } else { TU_VERIFY(_find_desc_entity(_get_desc_vc(&_videod_itf[ctl_idx]), entity_id), VIDEO_ERROR_INVALID_REQUEST); @@ -1001,14 +1026,12 @@ static int handle_video_ctl_req(uint8_t rhport, uint8_t stage, static int handle_video_stm_std_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ + uint_fast8_t stm_idx) { TU_LOG_DRV("\r\n"); videod_streaming_interface_t *self = &_videod_streaming_itf[stm_idx]; switch (request->bRequest) { case TUSB_REQ_GET_INTERFACE: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_VERIFY(1 == request->wLength, VIDEO_ERROR_UNKNOWN); tusb_desc_vs_itf_t const *vs = _get_desc_vs(self); TU_VERIFY(vs, VIDEO_ERROR_UNKNOWN); @@ -1075,12 +1098,14 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, } else if (stage == CONTROL_STAGE_DATA) { TU_VERIFY(_update_streaming_parameters(stm, &stm->probe_commit_payload), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); + } else { + // nothing to do } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_CUR: if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(request->wLength != 0, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; @@ -1090,7 +1115,7 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, case VIDEO_REQUEST_GET_RES: case VIDEO_REQUEST_GET_DEF: if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(request->wLength != 0, VIDEO_ERROR_UNKNOWN); video_probe_and_commit_control_t tmp = stm->probe_commit_payload; TU_VERIFY(_negotiate_streaming_parameters(stm, request->bRequest, &tmp), VIDEO_ERROR_INVALID_VALUE_WITHIN_RANGE); TU_VERIFY(tud_control_xfer(rhport, request, &tmp, sizeof(tmp)), VIDEO_ERROR_UNKNOWN); @@ -1137,12 +1162,14 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, hdr->bHeaderLength = sizeof(*hdr); hdr->bmHeaderInfo = 0; } + } else { + // nothing to do } return VIDEO_ERROR_NONE; case VIDEO_REQUEST_GET_CUR: if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(request->wLength, VIDEO_ERROR_UNKNOWN); + TU_VERIFY(request->wLength != 0, VIDEO_ERROR_UNKNOWN); TU_VERIFY(tud_control_xfer(rhport, request, &stm->probe_commit_payload, sizeof(video_probe_and_commit_control_t)), VIDEO_ERROR_UNKNOWN); } return VIDEO_ERROR_NONE; @@ -1185,14 +1212,15 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage, static int handle_video_stm_req(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request, - uint_fast8_t stm_idx) -{ + uint_fast8_t stm_idx) { switch (request->bmRequestType_bit.type) { case TUSB_REQ_TYPE_STANDARD: return handle_video_stm_std_req(rhport, stage, request, stm_idx); case TUSB_REQ_TYPE_CLASS: - if (TU_U16_HIGH(request->wIndex)) return VIDEO_ERROR_INVALID_REQUEST; + if (0 != TU_U16_HIGH(request->wIndex)) { + return VIDEO_ERROR_INVALID_REQUEST; + } return handle_video_stm_cs_req(rhport, stage, request, stm_idx); default: return VIDEO_ERROR_INVALID_REQUEST; @@ -1203,11 +1231,12 @@ static int handle_video_stm_req(uint8_t rhport, uint8_t stage, // APPLICATION API //--------------------------------------------------------------------+ -bool tud_video_n_connected(uint_fast8_t ctl_idx) -{ +bool tud_video_n_connected(uint_fast8_t ctl_idx) { TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, 0); - if (stm) return true; + if (stm != NULL) { + return true; + } return false; } @@ -1216,15 +1245,21 @@ bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); - if (!stm || !stm->desc.ep[0]) return false; - if (stm->state == VS_STATE_PROBING) return false; + if (NULL == stm || 0 == stm->desc.ep[0]) { + return false; + } + if (stm->state == VS_STATE_PROBING) { + return false; + } -#ifdef TUP_DCD_EDPT_ISO_ALLOC + #ifdef TUP_DCD_EDPT_ISO_ALLOC uint8_t const *desc = _videod_itf[stm->index_vc].beg; uint_fast16_t ofs_ep = stm->desc.ep[0]; tusb_desc_endpoint_t const *ep = (tusb_desc_endpoint_t const*)(desc + ofs_ep); if (ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { - if (stm->state == VS_STATE_COMMITTED) return false; + if (stm->state == VS_STATE_COMMITTED) { + return false; + } } #endif @@ -1235,25 +1270,36 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu TU_ASSERT(ctl_idx < CFG_TUD_VIDEO); TU_ASSERT(stm_idx < CFG_TUD_VIDEO_STREAMING); - if (!buffer || !bufsize) return false; + if (0 == bufsize) { + return false; + } + videod_streaming_interface_t *stm = _get_instance_streaming(ctl_idx, stm_idx); videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[ctl_idx]; - if (!stm || !stm->desc.ep[0] || stm->buffer) return false; - if (stm->state == VS_STATE_PROBING) return false; + if (NULL == stm || 0 == stm->desc.ep[0] || stm->bufsize) { + return false; + } + if (stm->state == VS_STATE_PROBING) { + return false; + } /* Find EP address */ uint8_t const *desc = _videod_itf[stm->index_vc].beg; uint8_t ep_addr = 0; for (uint_fast8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { uint_fast16_t ofs_ep = stm->desc.ep[i]; - if (!ofs_ep) continue; + if (0 == ofs_ep) { + continue; + } ep_addr = _desc_ep_addr(desc + ofs_ep); break; } - if (!ep_addr) return false; + if (0 == ep_addr) { + return false; + } - TU_VERIFY( usbd_edpt_claim(0, ep_addr) ); + TU_VERIFY(usbd_edpt_claim(0, ep_addr)); /* update the packet header */ tusb_video_payload_header_t *hdr = (tusb_video_payload_header_t*)stm_epbuf->buf; hdr->FrameID ^= 1; @@ -1262,7 +1308,7 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu stm->buffer = (uint8_t*)buffer; stm->bufsize = bufsize; uint_fast16_t pkt_len = _prepare_in_payload(stm, stm_epbuf->buf); - TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len), 0); + TU_ASSERT( usbd_edpt_xfer(0, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len, false), 0); return true; } @@ -1305,7 +1351,9 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin videod_interface_t *self = NULL; uint8_t ctl_idx; for (ctl_idx = 0; ctl_idx < CFG_TUD_VIDEO; ++ctl_idx) { - if (_videod_itf[ctl_idx].beg) continue; + if (NULL != _videod_itf[ctl_idx].beg) { + continue; + } self = &_videod_itf[ctl_idx]; break; } @@ -1326,7 +1374,9 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin videod_streaming_interface_t *stm = NULL; /* find free streaming interface handle */ for (uint8_t i = 0; i < CFG_TUD_VIDEO_STREAMING; ++i) { - if (_videod_streaming_itf[i].desc.beg) continue; + if (0 != _videod_streaming_itf[i].desc.beg) { + continue; + } stm = &_videod_streaming_itf[i]; self->stm[stm_idx] = i; break; @@ -1354,7 +1404,9 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin } p_desc = tu_desc_next(p_desc); } - if(ep_addr > 0 && ep_size > 0) usbd_edpt_iso_alloc(rhport, ep_addr, ep_size); + if(ep_addr > 0 && ep_size > 0) { + usbd_edpt_iso_alloc(rhport, ep_addr, ep_size); + } #endif if (0 == stm_idx && 1 == bInCollection) { /* If there is only one streaming interface and no alternate settings, @@ -1381,31 +1433,43 @@ bool videod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_ uint_fast8_t itf; for (itf = 0; itf < CFG_TUD_VIDEO; ++itf) { void const *desc = _videod_itf[itf].beg; - if (!desc) continue; - if (itfnum == _desc_itfnum(desc)) break; + if (!desc) { + continue; + } + if (itfnum == _desc_itfnum(desc)) { + break; + } } if (itf < CFG_TUD_VIDEO) { TU_LOG_DRV(" VC[%d]: ", itf); err = handle_video_ctl_req(rhport, stage, request, itf); _videod_itf[itf].error_code = (uint8_t)err; - if (err) return false; + if (0 != err) { + return false; + } return true; } /* Identify which streaming interface to use */ for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { videod_streaming_interface_t *stm = &_videod_streaming_itf[itf]; - if (!stm->desc.beg) continue; + if (0 == stm->desc.beg) { + continue; + } uint8_t const *desc = _videod_itf[stm->index_vc].beg; - if (itfnum == _desc_itfnum(desc + stm->desc.beg)) break; + if (itfnum == _desc_itfnum(desc + stm->desc.beg)) { + break; + } } if (itf < CFG_TUD_VIDEO_STREAMING) { TU_LOG_DRV(" VS[%d]: ", itf); err = handle_video_stm_req(rhport, stage, request, itf); _videod_streaming_itf[itf].error_code = (uint8_t)err; - if (err) return false; + if (err != 0) { + return false; + } return true; } return false; @@ -1421,19 +1485,23 @@ bool videod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 for (itf = 0; itf < CFG_TUD_VIDEO_STREAMING; ++itf) { stm = &_videod_streaming_itf[itf]; uint_fast16_t const ep_ofs = stm->desc.ep[0]; - if (!ep_ofs) continue; + if (0 == ep_ofs) { + continue; + } ctl = &_videod_itf[stm->index_vc]; uint8_t const *desc = ctl->beg; - if (ep_addr == _desc_ep_addr(desc + ep_ofs)) break; + if (ep_addr == _desc_ep_addr(desc + ep_ofs)) { + break; + } } TU_ASSERT(itf < CFG_TUD_VIDEO_STREAMING); videod_streaming_epbuf_t *stm_epbuf = &_videod_streaming_epbuf[itf]; if (stm->offset < stm->bufsize) { /* Claim the endpoint */ - TU_VERIFY( usbd_edpt_claim(rhport, ep_addr), 0); + TU_VERIFY(usbd_edpt_claim(rhport, ep_addr), 0); uint_fast16_t pkt_len = _prepare_in_payload(stm, stm_epbuf->buf); - TU_ASSERT( usbd_edpt_xfer(rhport, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len), 0); + TU_ASSERT(usbd_edpt_xfer(rhport, ep_addr, stm_epbuf->buf, (uint16_t) pkt_len, false), 0); } else { stm->buffer = NULL; stm->bufsize = 0; diff --git a/src/class/video/video_device.h b/src/class/video/video_device.h index 2b41c3bfe..f14555e4f 100644 --- a/src/class/video/video_device.h +++ b/src/class/video/video_device.h @@ -35,6 +35,16 @@ extern "C" { #endif + +//--------------------------------------------------------------------+ +// Payload request +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED { + void* buf; /* Payload buffer to be filled */ + size_t length; /* Length of the requested data in bytes */ + size_t offset; /* Offset within the frame (in bytes) */ +} tud_video_payload_request_t; + //--------------------------------------------------------------------+ // Application API (Multiple Ports) // CFG_TUD_VIDEO > 1 @@ -83,6 +93,16 @@ int tud_video_power_mode_cb(uint_fast8_t ctl_idx, uint8_t power_mod); int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, video_probe_and_commit_control_t const *parameters); +/** Invoked if buffer is set to NULL (allows bufferless on the fly data generation) + * + * @param[in] ctl_idx Destination control interface index + * @param[in] stm_idx Destination streaming interface index + * @param[out] payload_buf Payload storage buffer (target buffer for requested data) + * @param[in] payload_size Size of payload_buf (requested data size) + * @param[in] offset Current byte offset relative to given bufsize from tud_video_n_frame_xfer (framesize) + * @return video_error_code_t */ +void tud_video_prepare_payload_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, tud_video_payload_request_t* request); + //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 9c4699362..f377d5272 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_COMMON_H_ -#define _TUSB_COMMON_H_ +#ifndef TUSB_COMMON_H_ +#define TUSB_COMMON_H_ #ifdef __cplusplus extern "C" { @@ -34,29 +34,38 @@ //--------------------------------------------------------------------+ // Macros Helper //--------------------------------------------------------------------+ -#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) -#define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) -#define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) -#define TU_DIV_CEIL(n, d) (((n) + (d) - 1) / (d)) +#define TU_ARRAY_SIZE(_arr) ( sizeof(_arr) / sizeof(_arr[0]) ) +#define TU_FIELD_SIZE(_type, _field) (sizeof(((_type *)0)->_field)) +#define TU_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) ) +#define TU_MAX(_x, _y) ( ( (_x) > (_y) ) ? (_x) : (_y) ) +#define TU_DIV_CEIL(n, d) (((n) + (d) - 1) / (d)) +#define TU_DIV_ROUND_NEAREST(v, d) (((v) + (d)/2) / (d) ) // round to nearest integer -#define TU_U16(_high, _low) ((uint16_t) (((_high) << 8) | (_low))) -#define TU_U16_HIGH(_u16) ((uint8_t) (((_u16) >> 8) & 0x00ff)) -#define TU_U16_LOW(_u16) ((uint8_t) ((_u16) & 0x00ff)) -#define U16_TO_U8S_BE(_u16) TU_U16_HIGH(_u16), TU_U16_LOW(_u16) -#define U16_TO_U8S_LE(_u16) TU_U16_LOW(_u16), TU_U16_HIGH(_u16) +#define TU_U16(_high, _low) ((uint16_t) ((((uint16_t) (_high)) << 8) | ((uint16_t) (_low)))) +#define TU_U16_HIGH(_u16) ((uint8_t) (((uint16_t) (_u16) >> 8) & 0x00ffu)) +#define TU_U16_LOW(_u16) ((uint8_t) ((uint16_t) (_u16) & 0x00ffu)) +#define U16_TO_U8S_BE(_u16) TU_U16_HIGH(_u16), TU_U16_LOW(_u16) +#define U16_TO_U8S_LE(_u16) TU_U16_LOW(_u16), TU_U16_HIGH(_u16) -#define TU_U32_BYTE3(_u32) ((uint8_t) ((((uint32_t) _u32) >> 24) & 0x000000ff)) // MSB -#define TU_U32_BYTE2(_u32) ((uint8_t) ((((uint32_t) _u32) >> 16) & 0x000000ff)) -#define TU_U32_BYTE1(_u32) ((uint8_t) ((((uint32_t) _u32) >> 8) & 0x000000ff)) -#define TU_U32_BYTE0(_u32) ((uint8_t) (((uint32_t) _u32) & 0x000000ff)) // LSB +#define TU_U24(_high, _mid, _low) ((uint32_t) ((((uint32_t) (_high)) << 16) | (((uint32_t) (_mid)) << 8) | ((uint32_t) (_low)))) +#define TU_U24_HIGH(_u24) ((uint8_t) (((uint32_t) (_u24) >> 16) & 0x0000ffu)) +#define TU_U24_MID(_u24) ((uint8_t) (((uint32_t) (_u24) >> 8) & 0x0000ffu)) +#define TU_U24_LOW(_u24) ((uint8_t) ((uint32_t) (_u24) & 0x0000ffu)) +#define U24_TO_U8S_BE(_u24) TU_U24_HIGH(_u24), TU_U24_MID(_u24), TU_U24_LOW(_u24) +#define U24_TO_U8S_LE(_u24) TU_U24_LOW(_u24), TU_U24_MID(_u24), TU_U24_HIGH(_u24) -#define U32_TO_U8S_BE(_u32) TU_U32_BYTE3(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE0(_u32) -#define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) +#define TU_U32_BYTE3(_u32) ((uint8_t) ((((uint32_t) _u32) >> 24) & 0x000000ff)) // MSB +#define TU_U32_BYTE2(_u32) ((uint8_t) ((((uint32_t) _u32) >> 16) & 0x000000ff)) +#define TU_U32_BYTE1(_u32) ((uint8_t) ((((uint32_t) _u32) >> 8) & 0x000000ff)) +#define TU_U32_BYTE0(_u32) ((uint8_t) (((uint32_t) _u32) & 0x000000ff)) // LSB -#define TU_BIT(n) (1UL << (n)) +#define U32_TO_U8S_BE(_u32) TU_U32_BYTE3(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE0(_u32) +#define U32_TO_U8S_LE(_u32) TU_U32_BYTE0(_u32), TU_U32_BYTE1(_u32), TU_U32_BYTE2(_u32), TU_U32_BYTE3(_u32) + +#define TU_BIT(n) (1UL << (n)) // Generate a mask with bit from high (31) to low (0) set, e.g TU_GENMASK(3, 0) = 0b1111 -#define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) +#define TU_GENMASK(h, l) ( (UINT32_MAX << (l)) & (UINT32_MAX >> (31 - (h))) ) //--------------------------------------------------------------------+ // Includes @@ -68,7 +77,6 @@ #include <inttypes.h> #include <stddef.h> #include <string.h> -#include <stdio.h> // Tinyusb Common Headers #include "tusb_option.h" @@ -103,26 +111,47 @@ extern void* tusb_app_phys_to_virt(void *phys_addr); //--------------------------------------------------------------------+ //------------- Mem -------------// -#define tu_memclr(buffer, size) memset((buffer), 0, (size)) +#define tu_memclr(buffer, size) (void) memset((buffer), 0, (size)) #define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var))) // This is a backport of memset_s from c11 TU_ATTR_ALWAYS_INLINE static inline int tu_memset_s(void *dest, size_t destsz, int ch, size_t count) { - // TODO may check if desst and src is not NULL - if ( count > destsz ) { + // Validate parameters + if (dest == NULL) { return -1; } - memset(dest, ch, count); + + if (count == 0u) { + return 0; + } + + if (count > destsz) { + return -1; + } + + (void) memset(dest, ch, count); return 0; } // This is a backport of memcpy_s from c11 TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) { - // TODO may check if desst and src is not NULL - if ( count > destsz ) { + if (dest == NULL) { return -1; } - memcpy(dest, src, count); + + if (count == 0u) { + return 0; + } + + if (src == NULL) { + return -1; + } + + if (count > destsz) { + return -1; + } + + (void) memcpy(dest, src, count); return 0; } @@ -199,13 +228,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_is_aligned64(uint64_t value) { retur //------------- Mathematics -------------// TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_ceil(uint32_t v, uint32_t d) { return TU_DIV_CEIL(v, d); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_div_round_nearest(uint32_t v, uint32_t d) { return TU_DIV_ROUND_NEAREST(v, d); } + TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_round_up(uint32_t v, uint32_t f) { return tu_div_ceil(v, f) * f; } // log2 of a value is its MSB's position // TODO use clz TODO remove TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_log2(uint32_t value) { uint8_t result = 0; - while (value >>= 1) { result++; } + while ((value >>= 1u) != 0u) { + result++; + } return result; } @@ -251,14 +284,12 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_ // We have to manually pick up bytes since tu_unaligned_uint32_t will still generate unaligned code // NOTE: volatile cast to memory to prevent compiler to optimize and generate unaligned code // TODO Big Endian may need minor changes -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) { volatile uint8_t const* buf8 = (uint8_t const*) mem; return tu_u32(buf8[3], buf8[2], buf8[1], buf8[0]); } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) -{ +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) { volatile uint8_t* buf8 = (uint8_t*) mem; buf8[0] = tu_u32_byte0(value); buf8[1] = tu_u32_byte1(value); @@ -266,20 +297,17 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_ buf8[3] = tu_u32_byte3(value); } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) { volatile uint8_t const* buf8 = (uint8_t const*) mem; return tu_u16(buf8[1], buf8[0]); } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) -{ +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) { volatile uint8_t* buf8 = (uint8_t*) mem; buf8[0] = tu_u16_low(value); buf8[1] = tu_u16_high(value); } - #else // MCU that could access unaligned memory natively @@ -301,35 +329,6 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_ #endif -// To be removed -//------------- Binary constant -------------// -#if defined(__GNUC__) && !defined(__CC_ARM) - -#define TU_BIN8(x) ((uint8_t) (0b##x)) -#define TU_BIN16(b1, b2) ((uint16_t) (0b##b1##b2)) -#define TU_BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4)) - -#else - -// internal macro of B8, B16, B32 -#define _B8__(x) (((x&0x0000000FUL)?1:0) \ - +((x&0x000000F0UL)?2:0) \ - +((x&0x00000F00UL)?4:0) \ - +((x&0x0000F000UL)?8:0) \ - +((x&0x000F0000UL)?16:0) \ - +((x&0x00F00000UL)?32:0) \ - +((x&0x0F000000UL)?64:0) \ - +((x&0xF0000000UL)?128:0)) - -#define TU_BIN8(d) ((uint8_t) _B8__(0x##d##UL)) -#define TU_BIN16(dmsb,dlsb) (((uint16_t)TU_BIN8(dmsb)<<8) + TU_BIN8(dlsb)) -#define TU_BIN32(dmsb,db2,db3,dlsb) \ - (((uint32_t)TU_BIN8(dmsb)<<24) \ - + ((uint32_t)TU_BIN8(db2)<<16) \ - + ((uint32_t)TU_BIN8(db3)<<8) \ - + TU_BIN8(dlsb)) -#endif - //--------------------------------------------------------------------+ // Descriptor helper //--------------------------------------------------------------------+ @@ -355,8 +354,11 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE]; } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_in_bounds(uint8_t const* p_desc, uint8_t const* desc_end) { - return (p_desc < desc_end) && (tu_desc_next(p_desc) <= desc_end); +TU_ATTR_ALWAYS_INLINE static inline bool tu_desc_in_bounds(const uint8_t *p_desc, const uint8_t *desc_end) { + if (p_desc >= desc_end) { + return false; + } + return tu_desc_next(p_desc) <= desc_end; } // find descriptor that match byte1 (type) @@ -372,4 +374,4 @@ uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t b } #endif -#endif /* _TUSB_COMMON_H_ */ +#endif /* TUSB_COMMON_H_ */ diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index 9b33a6f61..7719790d1 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -29,8 +29,8 @@ * \brief Group_Compiler brief * @{ */ -#ifndef _TUSB_COMPILER_H_ -#define _TUSB_COMPILER_H_ +#ifndef TUSB_COMPILER_H_ +#define TUSB_COMPILER_H_ #define TU_TOKEN(x) x #define TU_STRING(x) #x ///< stringify without expand @@ -45,9 +45,9 @@ #define TU_INCLUDE_PATH(_dir,_file) TU_XSTRING( TU_TOKEN(_dir)TU_TOKEN(_file) ) #if defined __COUNTER__ && __COUNTER__ != __COUNTER__ - #define _TU_COUNTER_ __COUNTER__ + #define TU_COUNTER __COUNTER__ #else - #define _TU_COUNTER_ __LINE__ + #define TU_COUNTER __LINE__ #endif // Compile-time Assert @@ -56,9 +56,9 @@ #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define TU_VERIFY_STATIC _Static_assert #elif defined(__CCRX__) - #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(_verify_static_, _TU_COUNTER_)[(const_expr) ? 1 : 0]; + #define TU_VERIFY_STATIC(const_expr, _mess) typedef char TU_XSTRCAT(_verify_static_, TU_COUNTER)[(const_expr) ? 1 : 0]; #else - #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } + #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, TU_COUNTER) = 1/(!!(const_expr)) } #endif /* --------------------- Fuzzing types -------------------------------------- */ @@ -68,28 +68,28 @@ #define tu_static static #endif -// for declaration of reserved field, make use of _TU_COUNTER_ -#define TU_RESERVED TU_XSTRCAT(reserved, _TU_COUNTER_) +// for declaration of reserved field, make use of TU_COUNTER +#define TU_RESERVED TU_XSTRCAT(reserved, TU_COUNTER) #define TU_LITTLE_ENDIAN (0x12u) #define TU_BIG_ENDIAN (0x21u) /*------------------------------------------------------------------*/ /* Count number of arguments of __VA_ARGS__ - * - reference https://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments - * - _GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) - * - _RSEQ_N() is reverse sequential to N to add padding to have + * - reference www.stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments + * - TU_GET_NTH_ARG() takes args >= N (64) but only expand to Nth one (64th) + * - TU_NARG_RSEQ_N() is reverse sequential to N to add padding to have * Nth position is the same as the number of arguments * - ##__VA_ARGS__ is used to deal with 0 paramerter (swallows comma) *------------------------------------------------------------------*/ -#if !defined(__CCRX__) -#define TU_ARGS_NUM(...) _TU_NARG(_0, ##__VA_ARGS__, _RSEQ_N()) +#if defined(__CCRX__) +#define TU_ARGS_NUM(...) TU_NARG_IMPL(_0, __VA_ARGS__, TU_NARG_RSEQ_N()) #else -#define TU_ARGS_NUM(...) _TU_NARG(_0, __VA_ARGS__, _RSEQ_N()) +#define TU_ARGS_NUM(...) TU_NARG_IMPL(_0, ##__VA_ARGS__, TU_NARG_RSEQ_N()) #endif -#define _TU_NARG(...) _GET_NTH_ARG(__VA_ARGS__) -#define _GET_NTH_ARG( \ +#define TU_NARG_IMPL(...) TU_GET_NTH_ARG(__VA_ARGS__) +#define TU_GET_NTH_ARG( \ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ @@ -97,7 +97,7 @@ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63,N,...) N -#define _RSEQ_N() \ +#define TU_NARG_RSEQ_N() \ 62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ @@ -106,17 +106,29 @@ 19,18,17,16,15,14,13,12,11,10, \ 9,8,7,6,5,4,3,2,1,0 -// Apply an macro X to each of the arguments with an separated of choice -#define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(_TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__) +// Apply a macro X to each of the arguments with a separation/delimiter +#define TU_ARGS_APPLY(_X, _s, ...) TU_XSTRCAT(TU_ARGS_APPLY_, TU_ARGS_NUM(__VA_ARGS__))(_X, _s, __VA_ARGS__) -#define _TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1) -#define _TU_ARGS_APPLY_2(_X, _s, _a1, _a2) _X(_a1) _s _X(_a2) -#define _TU_ARGS_APPLY_3(_X, _s, _a1, _a2, _a3) _X(_a1) _s _TU_ARGS_APPLY_2(_X, _s, _a2, _a3) -#define _TU_ARGS_APPLY_4(_X, _s, _a1, _a2, _a3, _a4) _X(_a1) _s _TU_ARGS_APPLY_3(_X, _s, _a2, _a3, _a4) -#define _TU_ARGS_APPLY_5(_X, _s, _a1, _a2, _a3, _a4, _a5) _X(_a1) _s _TU_ARGS_APPLY_4(_X, _s, _a2, _a3, _a4, _a5) -#define _TU_ARGS_APPLY_6(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1) _s _TU_ARGS_APPLY_5(_X, _s, _a2, _a3, _a4, _a5, _a6) -#define _TU_ARGS_APPLY_7(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1) _s _TU_ARGS_APPLY_6(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7) -#define _TU_ARGS_APPLY_8(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1) _s _TU_ARGS_APPLY_7(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7, _a8) +#define TU_ARGS_APPLY_1(_X, _s, _a1) _X(_a1) +#define TU_ARGS_APPLY_2(_X, _s, _a1, _a2) _X(_a1) _s _X(_a2) +#define TU_ARGS_APPLY_3(_X, _s, _a1, _a2, _a3) _X(_a1) _s TU_ARGS_APPLY_2(_X, _s, _a2, _a3) +#define TU_ARGS_APPLY_4(_X, _s, _a1, _a2, _a3, _a4) _X(_a1) _s TU_ARGS_APPLY_3(_X, _s, _a2, _a3, _a4) +#define TU_ARGS_APPLY_5(_X, _s, _a1, _a2, _a3, _a4, _a5) _X(_a1) _s TU_ARGS_APPLY_4(_X, _s, _a2, _a3, _a4, _a5) +#define TU_ARGS_APPLY_6(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1) _s TU_ARGS_APPLY_5(_X, _s, _a2, _a3, _a4, _a5, _a6) +#define TU_ARGS_APPLY_7(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1) _s TU_ARGS_APPLY_6(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7) +#define TU_ARGS_APPLY_8(_X, _s, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1) _s TU_ARGS_APPLY_7(_X, _s, _a2, _a3, _a4, _a5, _a6, _a7, _a8) + +// Apply a macro X to each of the arguments and expand the result with comma +#define TU_ARGS_APPLY_EXPAND(_X, ...) TU_XSTRCAT(TU_ARGS_APPLY_EXPAND_, TU_ARGS_NUM(__VA_ARGS__))(_X, __VA_ARGS__) + +#define TU_ARGS_APPLY_EXPAND_1(_X, _a1) _X(_a1) +#define TU_ARGS_APPLY_EXPAND_2(_X, _a1, _a2) _X(_a1), _X(_a2) +#define TU_ARGS_APPLY_EXPAND_3(_X, _a1, _a2, _a3) _X(_a1), TU_ARGS_APPLY_EXPAND_2(_X, _a2, _a3) +#define TU_ARGS_APPLY_EXPAND_4(_X, _a1, _a2, _a3, _a4) _X(_a1), TU_ARGS_APPLY_EXPAND_3(_X, _a2, _a3, _a4) +#define TU_ARGS_APPLY_EXPAND_5(_X, _a1, _a2, _a3, _a4, _a5) _X(_a1), TU_ARGS_APPLY_EXPAND_4(_X, _a2, _a3, _a4, _a5) +#define TU_ARGS_APPLY_EXPAND_6(_X, _a1, _a2, _a3, _a4, _a5, _a6) _X(_a1), TU_ARGS_APPLY_EXPAND_5(_X, _a2, _a3, _a4, _a5, _a6) +#define TU_ARGS_APPLY_EXPAND_7(_X, _a1, _a2, _a3, _a4, _a5, _a6, _a7) _X(_a1), TU_ARGS_APPLY_EXPAND_6(_X, _a2, _a3, _a4, _a5, _a6, _a7) +#define TU_ARGS_APPLY_EXPAND_8(_X, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) _X(_a1), TU_ARGS_APPLY_EXPAND_7(_X, _a2, _a3, _a4, _a5, _a6, _a7, _a8) //--------------------------------------------------------------------+ // Macro for function default arguments @@ -305,6 +317,6 @@ #error Byte order is undefined #endif -#endif /* _TUSB_COMPILER_H_ */ +#endif /* TUSB_COMPILER_H_ */ /// @} diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 1d0c6f1ad..e0e09f5ce 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DEBUG_H_ -#define _TUSB_DEBUG_H_ +#ifndef TUSB_DEBUG_H_ +#define TUSB_DEBUG_H_ #ifdef __cplusplus extern "C" { @@ -55,11 +55,14 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); extern int CFG_TUSB_DEBUG_PRINTF(const char *format, ...); #define tu_printf CFG_TUSB_DEBUG_PRINTF #else - #define tu_printf printf + #include <stdio.h> + #define tu_printf(...) (void) printf(__VA_ARGS__) #endif -static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { - for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]); +TU_ATTR_ALWAYS_INLINE static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { + for(uint32_t i=0; i<bufsize; i++) { + tu_printf("%02X ", buf[i]); + } tu_printf("\r\n"); } @@ -109,12 +112,16 @@ typedef struct { static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { for(uint16_t i=0; i<p_table->count; i++) { - if (p_table->items[i].key == key) { return p_table->items[i].data; } + if (p_table->items[i].key == key) { + return p_table->items[i].data; + } } // not found return the key value in hex static char not_found[11]; - snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key); + if (snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key) <= 0) { + not_found[0] = 0; + } return not_found; } @@ -130,8 +137,6 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG_FAILED() #endif -// TODO replace all TU_LOGn with TU_LOG(n) - #define TU_LOG0(...) #define TU_LOG0_MEM(...) #define TU_LOG0_BUF(...) @@ -166,4 +171,4 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 } #endif -#endif /* _TUSB_DEBUG_H_ */ +#endif diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index f7679556f..5c9e586fb 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -28,7 +28,7 @@ #include "osal/osal.h" #include "tusb_fifo.h" -#define TU_FIFO_DBG 0 +#define TU_FIFO_DBG 0 // Suppress IAR warning // Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement @@ -38,14 +38,16 @@ #if OSAL_MUTEX_REQUIRED -TU_ATTR_ALWAYS_INLINE static inline void _ff_lock(osal_mutex_t mutex) -{ - if (mutex) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); +TU_ATTR_ALWAYS_INLINE static inline void _ff_lock(osal_mutex_t mutex) { + if (mutex != NULL) { + osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); + } } -TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) -{ - if (mutex) osal_mutex_unlock(mutex); +TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) { + if (mutex != NULL) { + osal_mutex_unlock(mutex); + } } #else @@ -59,27 +61,27 @@ TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) * \brief Write modes intended to allow special read and write functions to be able to * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others */ -typedef enum -{ - TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode +typedef enum { + TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode #ifdef TUP_MEM_CONST_ADDR TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO #endif } tu_fifo_copy_mode_t; -bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) -{ +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable // only if overflow happens once (important for unsupervised DMA applications) - if (depth > 0x8000) return false; + if (depth > 0x8000) { + return false; + } _ff_lock(f->mutex_wr); _ff_lock(f->mutex_rd); - f->buffer = (uint8_t*) buffer; + f->buffer = (uint8_t *)buffer; f->depth = depth; - f->item_size = (uint16_t) (item_size & 0x7FFF); + f->item_size = (uint16_t)(item_size & 0x7FFF); f->overwritable = overwritable; f->rd_idx = 0; f->wr_idx = 0; @@ -98,22 +100,19 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsys.c // TODO generalize with configurable 1 byte or 4 byte each read -static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) -{ - volatile const uint32_t * reg_rx = (volatile const uint32_t *) app_buf; +static void _ff_push_const_addr(uint8_t *ff_buf, const void *app_buf, uint16_t len) { + const volatile uint32_t *reg_rx = (volatile const uint32_t *)app_buf; // Reading full available 32 bit words from const app address uint16_t full_words = len >> 2; - while(full_words--) - { + while (full_words--) { tu_unaligned_write32(ff_buf, *reg_rx); ff_buf += 4; } // Read the remaining 1-3 bytes from const app address - uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { + const uint8_t bytes_rem = len & 0x03; + if (bytes_rem) { uint32_t tmp32 = *reg_rx; memcpy(ff_buf, &tmp32, bytes_rem); } @@ -121,22 +120,19 @@ static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t // Intended to be used to write to hardware USB FIFO in e.g. STM32 // where all data is written to a constant address in full word copies -static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) -{ - volatile uint32_t * reg_tx = (volatile uint32_t *) app_buf; +static void _ff_pull_const_addr(void *app_buf, const uint8_t *ff_buf, uint16_t len) { + volatile uint32_t *reg_tx = (volatile uint32_t *)app_buf; // Write full available 32 bit words to const address uint16_t full_words = len >> 2; - while(full_words--) - { + while (full_words--) { *reg_tx = tu_unaligned_read32(ff_buf); ff_buf += 4; } // Write the remaining 1-3 bytes into const address - uint8_t const bytes_rem = len & 0x03; - if ( bytes_rem ) - { + const uint8_t bytes_rem = len & 0x03; + if (bytes_rem) { uint32_t tmp32 = 0; memcpy(&tmp32, ff_buf, bytes_rem); @@ -146,33 +142,27 @@ static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t #endif // send one item to fifo WITHOUT updating write pointer -static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) -{ +static inline void _ff_push(tu_fifo_t *f, const void *app_buf, uint16_t rel) { memcpy(f->buffer + (rel * f->item_size), app_buf, f->item_size); } // send n items to fifo WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t wr_ptr, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const lin_count = f->depth - wr_ptr; - uint16_t const wrap_count = n - lin_count; +static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, tu_fifo_copy_mode_t copy_mode) { + const uint16_t lin_count = f->depth - wr_ptr; + const uint16_t wrap_count = n - lin_count; - uint16_t lin_bytes = lin_count * f->item_size; + uint16_t lin_bytes = lin_count * f->item_size; uint16_t wrap_bytes = wrap_count * f->item_size; // current buffer of fifo - uint8_t* ff_buf = f->buffer + (wr_ptr * f->item_size); + uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size); - switch (copy_mode) - { + switch (copy_mode) { case TU_FIFO_COPY_INC: - if(n <= lin_count) - { + if (n <= lin_count) { // Linear only - memcpy(ff_buf, app_buf, n*f->item_size); - } - else - { + memcpy(ff_buf, app_buf, n * f->item_size); + } else { // Wrap around // Write data to linear part of buffer @@ -180,19 +170,17 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t // Write data wrapped around // TU_ASSERT(nWrap_bytes <= f->depth, ); - memcpy(f->buffer, ((uint8_t const*) app_buf) + lin_bytes, wrap_bytes); + memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); } break; + #ifdef TUP_MEM_CONST_ADDR case TU_FIFO_COPY_CST_FULL_WORDS: // Intended for hardware buffers from which it can be read word by word only - if(n <= lin_count) - { + if (n <= lin_count) { // Linear only - _ff_push_const_addr(ff_buf, app_buf, n*f->item_size); - } - else - { + _ff_push_const_addr(ff_buf, app_buf, n * f->item_size); + } else { // Wrap around case // Write full words to linear part of buffer @@ -202,83 +190,80 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t // There could be odd 1-3 bytes before the wrap-around boundary uint8_t rem = lin_bytes & 0x03; - if (rem > 0) - { - volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; + if (rem > 0) { + const volatile uint32_t *rx_fifo = (volatile const uint32_t *)app_buf; - uint8_t remrem = (uint8_t) tu_min16(wrap_bytes, 4-rem); + uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem); wrap_bytes -= remrem; - uint32_t tmp32 = *rx_fifo; - uint8_t * src_u8 = ((uint8_t *) &tmp32); + uint32_t tmp32 = *rx_fifo; + uint8_t *src_u8 = ((uint8_t *)&tmp32); // Write 1-3 bytes before wrapped boundary - while(rem--) *ff_buf++ = *src_u8++; + while (rem--) { + *ff_buf++ = *src_u8++; + } // Read more bytes to beginning to complete a word ff_buf = f->buffer; - while(remrem--) *ff_buf++ = *src_u8++; - } - else - { + while (remrem--) { + *ff_buf++ = *src_u8++; + } + } else { ff_buf = f->buffer; // wrap around to beginning } // Write data wrapped part - if (wrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); + if (wrap_bytes > 0) { + _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); + } } break; #endif - default: break; + + default: + break; // unknown mode } } // get one item from fifo WITHOUT updating read pointer -static inline void _ff_pull(tu_fifo_t* f, void * app_buf, uint16_t rel) -{ +static inline void _ff_pull(tu_fifo_t *f, void *app_buf, uint16_t rel) { memcpy(app_buf, f->buffer + (rel * f->item_size), f->item_size); } // get n items from fifo WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const lin_count = f->depth - rd_ptr; - uint16_t const wrap_count = n - lin_count; // only used if wrapped +static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_copy_mode_t copy_mode) { + const uint16_t lin_count = f->depth - rd_ptr; + const uint16_t wrap_count = n - lin_count; // only used if wrapped - uint16_t lin_bytes = lin_count * f->item_size; + uint16_t lin_bytes = lin_count * f->item_size; uint16_t wrap_bytes = wrap_count * f->item_size; // current buffer of fifo - uint8_t* ff_buf = f->buffer + (rd_ptr * f->item_size); + uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size); - switch (copy_mode) - { + switch (copy_mode) { case TU_FIFO_COPY_INC: - if ( n <= lin_count ) - { + if (n <= lin_count) { // Linear only - memcpy(app_buf, ff_buf, n*f->item_size); - } - else - { + memcpy(app_buf, ff_buf, n * f->item_size); + } else { // Wrap around // Read data from linear part of buffer memcpy(app_buf, ff_buf, lin_bytes); // Read data wrapped part - memcpy((uint8_t*) app_buf + lin_bytes, f->buffer, wrap_bytes); + memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); } - break; + break; + #ifdef TUP_MEM_CONST_ADDR case TU_FIFO_COPY_CST_FULL_WORDS: - if ( n <= lin_count ) - { + if (n <= lin_count) { // Linear only - _ff_pull_const_addr(app_buf, ff_buf, n*f->item_size); - } - else - { + _ff_pull_const_addr(app_buf, ff_buf, n * f->item_size); + } else { // Wrap around case // Read full words from linear part of buffer @@ -288,36 +273,41 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rd_ptr, // There could be odd 1-3 bytes before the wrap-around boundary uint8_t rem = lin_bytes & 0x03; - if (rem > 0) - { - volatile uint32_t * reg_tx = (volatile uint32_t *) app_buf; + if (rem > 0) { + volatile uint32_t *reg_tx = (volatile uint32_t *)app_buf; - uint8_t remrem = (uint8_t) tu_min16(wrap_bytes, 4-rem); + uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem); wrap_bytes -= remrem; - uint32_t tmp32=0; - uint8_t * dst_u8 = (uint8_t *)&tmp32; + uint32_t tmp32 = 0; + uint8_t *dst_u8 = (uint8_t *)&tmp32; // Read 1-3 bytes before wrapped boundary - while(rem--) *dst_u8++ = *ff_buf++; + while (rem--) { + *dst_u8++ = *ff_buf++; + } // Read more bytes from beginning to complete a word ff_buf = f->buffer; - while(remrem--) *dst_u8++ = *ff_buf++; + while (remrem--) { + *dst_u8++ = *ff_buf++; + } *reg_tx = tmp32; - } - else - { + } else { ff_buf = f->buffer; // wrap around to beginning } // Read data wrapped part - if (wrap_bytes > 0) _ff_pull_const_addr(app_buf, ff_buf, wrap_bytes); + if (wrap_bytes > 0) { + _ff_pull_const_addr(app_buf, ff_buf, wrap_bytes); + } } - break; + break; #endif - default: break; + + default: + break; // unknown mode } } @@ -326,24 +316,18 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rd_ptr, //--------------------------------------------------------------------+ // return only the index difference and as such can be used to determine an overflow i.e overflowable count -TU_ATTR_ALWAYS_INLINE static inline -uint16_t _ff_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) { // In case we have non-power of two depth we need a further modification - if (wr_idx >= rd_idx) - { - return (uint16_t) (wr_idx - rd_idx); - } else - { - return (uint16_t) (2*depth - (rd_idx - wr_idx)); + if (wr_idx >= rd_idx) { + return (uint16_t)(wr_idx - rd_idx); + } else { + return (uint16_t)(2 * depth - (rd_idx - wr_idx)); } } // return remaining slot in fifo -TU_ATTR_ALWAYS_INLINE static inline -uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) -{ - uint16_t const count = _ff_count(depth, wr_idx, rd_idx); +TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) { + const uint16_t count = _ff_count(depth, wr_idx, rd_idx); return (depth > count) ? (depth - count) : 0; } @@ -353,16 +337,14 @@ uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) // Advance an absolute index // "absolute" index is only in the range of [0..2*depth) -static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) -{ +static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index - uint16_t new_idx = (uint16_t) (idx + offset); - if ( (idx > new_idx) || (new_idx >= 2*depth) ) - { - uint16_t const non_used_index_space = (uint16_t) (UINT16_MAX - (2*depth-1)); - new_idx = (uint16_t) (new_idx + non_used_index_space); + uint16_t new_idx = (uint16_t)(idx + offset); + if ((idx > new_idx) || (new_idx >= 2 * depth)) { + const uint16_t non_used_index_space = (uint16_t)(UINT16_MAX - (2 * depth - 1)); + new_idx = (uint16_t)(new_idx + non_used_index_space); } return new_idx; @@ -370,14 +352,12 @@ static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) #if 0 // not used but // Backward an absolute index -static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) -{ +static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index uint16_t new_idx = (uint16_t) (idx - offset); - if ( (idx < new_idx) || (new_idx >= 2*depth) ) - { + if ( (idx < new_idx) || (new_idx >= 2*depth) ) { uint16_t const non_used_index_space = (uint16_t) (UINT16_MAX - (2*depth-1)); new_idx = (uint16_t) (new_idx - non_used_index_space); } @@ -387,26 +367,22 @@ static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) #endif // index to pointer, simply an modulo with minus. -TU_ATTR_ALWAYS_INLINE static inline -uint16_t idx2ptr(uint16_t depth, uint16_t idx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t idx) { // Only run at most 3 times since index is limit in the range of [0..2*depth) - while ( idx >= depth ) idx -= depth; + while (idx >= depth) { + idx -= depth; + } return idx; } // Works on local copies of w // When an overwritable fifo is overflowed, rd_idx will be re-index so that it forms // an full fifo i.e _ff_count() = depth -TU_ATTR_ALWAYS_INLINE static inline -uint16_t _ff_correct_read_index(tu_fifo_t* f, uint16_t wr_idx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { uint16_t rd_idx; - if ( wr_idx >= f->depth ) - { + if (wr_idx >= f->depth) { rd_idx = wr_idx - f->depth; - }else - { + } else { rd_idx = wr_idx + f->depth; } @@ -417,16 +393,16 @@ uint16_t _ff_correct_read_index(tu_fifo_t* f, uint16_t wr_idx) // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wr_idx, uint16_t rd_idx) -{ +static bool _tu_fifo_peek(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_t rd_idx) { uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx); // nothing to peek - if ( cnt == 0 ) return false; + if (cnt == 0) { + return false; + } // Check overflow and correct if required - if ( cnt > f->depth ) - { + if (cnt > f->depth) { rd_idx = _ff_correct_read_index(f, wr_idx); } @@ -440,22 +416,25 @@ static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wr_idx, uint16 // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, tu_fifo_copy_mode_t copy_mode) -{ +static uint16_t _tu_fifo_peek_n( + tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx); // nothing to peek - if ( cnt == 0 ) return 0; + if (cnt == 0) { + return 0; + } // Check overflow and correct if required - if ( cnt > f->depth ) - { + if (cnt > f->depth) { rd_idx = _ff_correct_read_index(f, wr_idx); - cnt = f->depth; + cnt = f->depth; } // Check if we can read something at and after offset - if too less is available we read what remains - if ( cnt < n ) n = cnt; + if (cnt < n) { + n = cnt; + } uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); @@ -465,40 +444,36 @@ static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint1 return n; } -static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ - if ( n == 0 ) return 0; +static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_copy_mode_t copy_mode) { + if (n == 0) { + return 0; + } _ff_lock(f->mutex_wr); uint16_t wr_idx = f->wr_idx; uint16_t rd_idx = f->rd_idx; - uint8_t const* buf8 = (uint8_t const*) data; + const uint8_t *buf8 = (const uint8_t *)data; - TU_LOG(TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u: ", - rd_idx, wr_idx, _ff_count(f->depth, wr_idx, rd_idx), _ff_remaining(f->depth, wr_idx, rd_idx), n); + TU_LOG( + TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u: ", rd_idx, wr_idx, + _ff_count(f->depth, wr_idx, rd_idx), _ff_remaining(f->depth, wr_idx, rd_idx), n); - if ( !f->overwritable ) - { + if (!f->overwritable) { // limit up to full - uint16_t const remain = _ff_remaining(f->depth, wr_idx, rd_idx); - n = tu_min16(n, remain); - } - else - { + const uint16_t remain = _ff_remaining(f->depth, wr_idx, rd_idx); + n = tu_min16(n, remain); + } else { // In over-writable mode, fifo_write() is allowed even when fifo is full. In such case, // oldest data in fifo i.e at read pointer data will be overwritten // Note: we can modify read buffer contents but we must not modify the read index itself within a write function! // Since it would end up in a race condition with read functions! - if ( n >= f->depth ) - { + if (n >= f->depth) { // Only copy last part - if ( copy_mode == TU_FIFO_COPY_INC ) - { + if (copy_mode == TU_FIFO_COPY_INC) { buf8 += (n - f->depth) * f->item_size; - }else - { + } else { // TODO should read from hw fifo to discard data, however reading an odd number could // accidentally discard data. } @@ -507,12 +482,9 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // We start writing at the read pointer's position since we fill the whole buffer wr_idx = rd_idx; - } - else - { - uint16_t const overflowable_count = _ff_count(f->depth, wr_idx, rd_idx); - if (overflowable_count + n >= 2*f->depth) - { + } else { + const uint16_t overflowable_count = _ff_count(f->depth, wr_idx, rd_idx); + if (overflowable_count + n >= 2 * f->depth) { // Double overflowed // Index is bigger than the allowed range [0,2*depth) // re-position write index to have a full fifo after pushed @@ -522,8 +494,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // However memmove() is expensive due to actual copying + wrapping consideration. // Also race condition could happen anyway if read() is invoke while moving result in corrupted memory // currently deliberately not implemented --> result in incorrect data read back - }else - { + } else { // normal + single overflowed: // Index is in the range of [0,2*depth) and thus detect and recoverable. Recovering is handled in read() // Therefore we just increase write index @@ -532,16 +503,11 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu } } - if (n) - { + if (n) { uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - // Write data _ff_push_n(f, buf8, n, wr_ptr, copy_mode); - - // Advance index f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); @@ -552,8 +518,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu return n; } -static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ +static uint16_t _tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { _ff_lock(f->mutex_rd); // Peek the data @@ -586,31 +551,12 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo @returns Number of items in FIFO */ /******************************************************************************/ -uint16_t tu_fifo_count(tu_fifo_t* f) -{ +uint16_t tu_fifo_count(const tu_fifo_t *f) { return tu_min16(_ff_count(f->depth, f->wr_idx, f->rd_idx), f->depth); } /******************************************************************************/ /*! - @brief Check if FIFO is empty. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -bool tu_fifo_empty(tu_fifo_t* f) -{ - return f->wr_idx == f->rd_idx; -} - -/******************************************************************************/ -/*! @brief Check if FIFO is full. As this function only reads the read and write pointers once, this function is @@ -622,8 +568,7 @@ bool tu_fifo_empty(tu_fifo_t* f) @returns Number of items in FIFO */ /******************************************************************************/ -bool tu_fifo_full(tu_fifo_t* f) -{ +bool tu_fifo_full(const tu_fifo_t *f) { return _ff_count(f->depth, f->wr_idx, f->rd_idx) >= f->depth; } @@ -640,8 +585,7 @@ bool tu_fifo_full(tu_fifo_t* f) @returns Number of items in FIFO */ /******************************************************************************/ -uint16_t tu_fifo_remaining(tu_fifo_t* f) -{ +uint16_t tu_fifo_remaining(const tu_fifo_t *f) { return _ff_remaining(f->depth, f->wr_idx, f->rd_idx); } @@ -666,14 +610,12 @@ uint16_t tu_fifo_remaining(tu_fifo_t* f) @returns True if overflow happened */ /******************************************************************************/ -bool tu_fifo_overflowed(tu_fifo_t* f) -{ +bool tu_fifo_overflowed(const tu_fifo_t *f) { return _ff_count(f->depth, f->wr_idx, f->rd_idx) > f->depth; } // Only use in case tu_fifo_overflow() returned true! -void tu_fifo_correct_read_pointer(tu_fifo_t* f) -{ +void tu_fifo_correct_read_pointer(tu_fifo_t *f) { _ff_lock(f->mutex_rd); _ff_correct_read_index(f, f->wr_idx); _ff_unlock(f->mutex_rd); @@ -695,8 +637,7 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_read(tu_fifo_t* f, void * buffer) -{ +bool tu_fifo_read(tu_fifo_t *f, void *buffer) { _ff_lock(f->mutex_rd); // Peek the data @@ -726,8 +667,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) @returns number of items read from the FIFO */ /******************************************************************************/ -uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) -{ +uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); } @@ -749,8 +689,7 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) @returns number of items read from the FIFO */ /******************************************************************************/ -uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint16_t n) -{ +uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n) { return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS); } #endif @@ -768,8 +707,7 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) -{ +bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer) { _ff_lock(f->mutex_rd); bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); _ff_unlock(f->mutex_rd); @@ -791,8 +729,7 @@ bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) -{ +uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); uint16_t ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); _ff_unlock(f->mutex_rd); @@ -815,27 +752,19 @@ uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) FIFO will always return TRUE) */ /******************************************************************************/ -bool tu_fifo_write(tu_fifo_t* f, const void * data) -{ +bool tu_fifo_write(tu_fifo_t *f, const void *data) { _ff_lock(f->mutex_wr); - bool ret; - uint16_t const wr_idx = f->wr_idx; + bool ret; + const uint16_t wr_idx = f->wr_idx; - if ( tu_fifo_full(f) && !f->overwritable ) - { + if (tu_fifo_full(f) && !f->overwritable) { ret = false; - }else - { + } else { uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - - // Write data _ff_push(f, data, wr_ptr); - - // Advance pointer f->wr_idx = advance_index(f->depth, wr_idx, 1); - - ret = true; + ret = true; } _ff_unlock(f->mutex_wr); @@ -857,8 +786,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) @return Number of written elements */ /******************************************************************************/ -uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) -{ +uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC); } @@ -878,8 +806,7 @@ uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) @return Number of written elements */ /******************************************************************************/ -uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, uint16_t n) -{ +uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n) { return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS); } #endif @@ -892,8 +819,7 @@ uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, Pointer to the FIFO buffer to manipulate */ /******************************************************************************/ -bool tu_fifo_clear(tu_fifo_t *f) -{ +bool tu_fifo_clear(tu_fifo_t *f) { _ff_lock(f->mutex_wr); _ff_lock(f->mutex_rd); @@ -947,8 +873,7 @@ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { Number of items the write pointer moves forward */ /******************************************************************************/ -void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) -{ +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) { f->wr_idx = advance_index(f->depth, f->wr_idx, n); } @@ -968,8 +893,7 @@ void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) Number of items the read pointer moves forward */ /******************************************************************************/ -void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) -{ +void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) { f->rd_idx = advance_index(f->depth, f->rd_idx, n); } @@ -988,8 +912,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Pointer to struct which holds the desired infos */ /******************************************************************************/ -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { // Operate on temporary values in case they change in between uint16_t wr_idx = f->wr_idx; uint16_t rd_idx = f->rd_idx; @@ -997,8 +920,7 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx); // Check overflow and correct if required - may happen in case a DMA wrote too fast - if (cnt > f->depth) - { + if (cnt > f->depth) { _ff_lock(f->mutex_rd); rd_idx = _ff_correct_read_index(f, wr_idx); _ff_unlock(f->mutex_rd); @@ -1007,8 +929,7 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) } // Check if fifo is empty - if (cnt == 0) - { + if (cnt == 0) { info->len_lin = 0; info->len_wrap = 0; info->ptr_lin = NULL; @@ -1024,17 +945,14 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) info->ptr_lin = &f->buffer[rd_ptr]; // Check if there is a wrap around necessary - if (wr_ptr > rd_ptr) - { + if (wr_ptr > rd_ptr) { // Non wrapping case - info->len_lin = cnt; + info->len_lin = cnt; info->len_wrap = 0; info->ptr_wrap = NULL; - } - else - { - info->len_lin = f->depth - rd_ptr; // Also the case if FIFO was full + } else { + info->len_lin = f->depth - rd_ptr; // Also the case if FIFO was full info->len_wrap = cnt - info->len_lin; info->ptr_wrap = f->buffer; @@ -1056,14 +974,12 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) Pointer to struct which holds the desired infos */ /******************************************************************************/ -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { uint16_t wr_idx = f->wr_idx; uint16_t rd_idx = f->rd_idx; uint16_t remain = _ff_remaining(f->depth, wr_idx, rd_idx); - if (remain == 0) - { + if (remain == 0) { info->len_lin = 0; info->len_wrap = 0; info->ptr_lin = NULL; @@ -1078,15 +994,12 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) // Copy pointer to buffer to start writing to info->ptr_lin = &f->buffer[wr_ptr]; - if (wr_ptr < rd_ptr) - { + if (wr_ptr < rd_ptr) { // Non wrapping case - info->len_lin = rd_ptr-wr_ptr; + info->len_lin = rd_ptr - wr_ptr; info->len_wrap = 0; info->ptr_wrap = NULL; - } - else - { + } else { info->len_lin = f->depth - wr_ptr; info->len_wrap = remain - info->len_lin; // Remaining length - n already was limited to remain or FIFO depth info->ptr_wrap = f->buffer; // Always start of buffer diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 879acda4f..9d8b864e9 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -25,8 +25,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_FIFO_H_ -#define _TUSB_FIFO_H_ +#ifndef TUSB_FIFO_H_ +#define TUSB_FIFO_H_ #ifdef __cplusplus extern "C" { @@ -104,16 +104,16 @@ extern "C" { * | R | 1 | 2 | W | 4 | 5 | */ typedef struct { - uint8_t* buffer ; // buffer pointer - uint16_t depth ; // max items + uint8_t *buffer; // buffer pointer + uint16_t depth; // max items struct TU_ATTR_PACKED { - uint16_t item_size : 15; // size of each item - bool overwritable : 1 ; // ovwerwritable when full + uint16_t item_size : 15; // size of each item + bool overwritable : 1; // ovwerwritable when full }; - volatile uint16_t wr_idx ; // write index - volatile uint16_t rd_idx ; // read index + volatile uint16_t wr_idx; // write index + volatile uint16_t rd_idx; // read index #if OSAL_MUTEX_REQUIRED osal_mutex_t mutex_wr; @@ -129,12 +129,13 @@ typedef struct { void * ptr_wrap ; ///< wrapped part start pointer } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable){\ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ -} +#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ + { \ + .buffer = _buffer, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = _overwritable, \ + } #define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ uint8_t _name##_buf[_depth*sizeof(_type)]; \ @@ -154,33 +155,35 @@ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_m #define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) #endif -bool tu_fifo_write (tu_fifo_t* f, void const * data); -uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * data, uint16_t n); -#ifdef TUP_MEM_CONST_ADDR -uint16_t tu_fifo_write_n_const_addr_full_words (tu_fifo_t* f, const void * data, uint16_t n); -#endif +bool tu_fifo_write(tu_fifo_t *f, void const *data); +uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n); + +bool tu_fifo_read(tu_fifo_t *f, void *buffer); +uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n); -bool tu_fifo_read (tu_fifo_t* f, void * buffer); -uint16_t tu_fifo_read_n (tu_fifo_t* f, void * buffer, uint16_t n); #ifdef TUP_MEM_CONST_ADDR -uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); +uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n); +uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n); #endif -bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); +uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); -uint16_t tu_fifo_count (tu_fifo_t* f); -uint16_t tu_fifo_remaining (tu_fifo_t* f); -bool tu_fifo_empty (tu_fifo_t* f); -bool tu_fifo_full (tu_fifo_t* f); -bool tu_fifo_overflowed (tu_fifo_t* f); -void tu_fifo_correct_read_pointer (tu_fifo_t* f); +uint16_t tu_fifo_count(const tu_fifo_t *f); +uint16_t tu_fifo_remaining(const tu_fifo_t *f); +bool tu_fifo_full(const tu_fifo_t *f); +bool tu_fifo_overflowed(const tu_fifo_t *f); -TU_ATTR_ALWAYS_INLINE static inline -uint16_t tu_fifo_depth(tu_fifo_t* f) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_fifo_empty(const tu_fifo_t *f) { + return f->wr_idx == f->rd_idx; +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_depth(const tu_fifo_t *f) { return f->depth; } +void tu_fifo_correct_read_pointer(tu_fifo_t *f); + // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFETY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); @@ -196,4 +199,4 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); } #endif -#endif /* _TUSB_FIFO_H_ */ +#endif diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 1c11df114..002cd3a0e 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -37,14 +37,14 @@ #ifdef __ARM_ARCH // ARM Architecture set __ARM_FEATURE_UNALIGNED to 1 for mcu supports unaligned access #if defined(__ARM_FEATURE_UNALIGNED) && __ARM_FEATURE_UNALIGNED == 1 - #define TUP_ARCH_STRICT_ALIGN 0 + #define TUP_ARCH_STRICT_ALIGN 0 #else - #define TUP_ARCH_STRICT_ALIGN 1 + #define TUP_ARCH_STRICT_ALIGN 1 #endif #else // TODO default to strict align for others // Should investigate other architecture such as risv, xtensa, mips for optimal setting - #define TUP_ARCH_STRICT_ALIGN 1 + #define TUP_ARCH_STRICT_ALIGN 1 #endif /* USB Controller Attributes for Device, Host or MCU (both) @@ -57,36 +57,41 @@ //--------------------------------------------------------------------+ // NXP //--------------------------------------------------------------------+ -#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) +#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) #define TUP_USBIP_IP3511 - #define TUP_DCD_ENDPOINT_MAX 5 + #define TUP_DCD_ENDPOINT_MAX 5 #elif TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 #define TUP_USBIP_OHCI - #define TUP_OHCI_RHPORTS 2 + #define TUP_USBIP_OHCI_NXP + #define TUP_OHCI_RHPORTS 2 #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX) - #define TUP_USBIP_IP3511 - #define TUP_DCD_ENDPOINT_MAX 5 + #define TUP_USBIP_IP3511 + #define TUP_DCD_ENDPOINT_MAX 5 #elif TU_CHECK_MCU(OPT_MCU_LPC54) // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_LPC55) // TODO USB0 has 5, USB1 has 6 #define TUP_USBIP_IP3511 - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_USBIP_OHCI + #define TUP_USBIP_OHCI_NXP + #define TUP_OHCI_RHPORTS 1 // 1 downstream port + + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX) // USB0 has 6 with HS PHY, USB1 has 4 only FS #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI - #define TUP_DCD_ENDPOINT_MAX 6 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_MCXN9) // USB0 is chipidea FS @@ -97,15 +102,15 @@ #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_MCXA15) // USB0 is chipidea FS #define TUP_USBIP_CHIPIDEA_FS #define TUP_USBIP_CHIPIDEA_FS_MCX - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 #elif TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX) #include "fsl_device_registers.h" @@ -113,54 +118,61 @@ #define TUP_USBIP_CHIPIDEA_HS #define TUP_USBIP_EHCI - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 #if __CORTEX_M == 7 - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 - #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 #endif #elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K) #define TUP_USBIP_CHIPIDEA_FS #define TUP_USBIP_CHIPIDEA_FS_KINETIS - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 #elif TU_CHECK_MCU(OPT_MCU_MM32F327X) - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_EDPT_CLOSE_API //--------------------------------------------------------------------+ // Nordic //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_NRF5X) // 8 CBI + 1 ISO - #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_EDPT_CLOSE_API + +#elif TU_CHECK_MCU(OPT_MCU_NRF54) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_NRF + #define TUP_DCD_ENDPOINT_MAX 16 + #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 //--------------------------------------------------------------------+ // Microchip //--------------------------------------------------------------------+ -#elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAMD51, OPT_MCU_SAME5X) || \ - TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML21, OPT_MCU_SAML22) - #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAML2X, OPT_MCU_SAMD21) || TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_SAMG) - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_SAMX7X) - #define TUP_DCD_ENDPOINT_MAX 10 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 10 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY -#elif TU_CHECK_MCU(OPT_MCU_PIC32MX, OPT_MCU_PIC32MM, OPT_MCU_PIC32MK) || \ - TU_CHECK_MCU(OPT_MCU_PIC24, OPT_MCU_DSPIC33) - #define TUP_DCD_ENDPOINT_MAX 16 +#elif TU_CHECK_MCU(OPT_MCU_PIC32MX, OPT_MCU_PIC32MM, OPT_MCU_PIC32MK) || TU_CHECK_MCU(OPT_MCU_PIC24, OPT_MCU_DSPIC33) + #define TUP_DCD_ENDPOINT_MAX 16 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY + #define TUP_DCD_EDPT_CLOSE_API //--------------------------------------------------------------------+ // ST @@ -168,23 +180,23 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32F1) // - F102, F103 use fsdev // - F105, F107 use dwc2 - #if defined (STM32F105x8) || defined (STM32F105xB) || defined (STM32F105xC) || \ - defined (STM32F107xB) || defined (STM32F107xC) + #if defined(STM32F105x8) || defined(STM32F105xB) || defined(STM32F105xC) || defined(STM32F107xB) || \ + defined(STM32F107xC) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 #define CFG_TUH_DWC2_DMA_ENABLE_DEFAULT 0 - #define TUP_DCD_ENDPOINT_MAX 4 - #elif defined(STM32F102x6) || defined(STM32F102xB) || \ - defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) + #define TUP_DCD_ENDPOINT_MAX 4 + #elif defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6) || defined(STM32F103xB) || \ + defined(STM32F103xE) || defined(STM32F103xG) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #else #error "Unsupported STM32F1 mcu" #endif @@ -194,55 +206,55 @@ #define TUP_USBIP_DWC2_STM32 // FS has 4 ep, HS has 5 ep - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_STM32F3) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32F4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_STM32F7) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 // FS has 6, HS has 9 - #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_ENDPOINT_MAX 9 // MCU with on-chip HS Phy #if defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F733xx) - #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS + #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS #endif // Enable dcache if DMA is enabled - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE - #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 #elif TU_CHECK_MCU(OPT_MCU_STM32H7) #include "stm32h7xx.h" #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_ENDPOINT_MAX 9 #if __CORTEX_M == 7 // Enable dcache if DMA is enabled - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE - #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 #endif #elif TU_CHECK_MCU(OPT_MCU_STM32H5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32G4) // Device controller @@ -251,41 +263,40 @@ // TypeC controller #define TUP_USBIP_TYPEC_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #define TUP_TYPEC_RHPORTS_NUM 1 #elif TU_CHECK_MCU(OPT_MCU_STM32G0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32C0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32L0, OPT_MCU_STM32L1) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32L4) // - L4x2, L4x3 use fsdev // - L4x4, L4x6, L4x7, L4x9 use dwc2 - #if defined (STM32L475xx) || defined (STM32L476xx) || \ - defined (STM32L485xx) || defined (STM32L486xx) || defined (STM32L496xx) || \ - defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \ - defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || \ - defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + #if defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || \ + defined(STM32L4S7xx) || defined(STM32L4S9xx) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif defined(STM32L412xx) || defined(STM32L422xx) || defined(STM32L432xx) || defined(STM32L433xx) || \ - defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) + defined(STM32L442xx) || defined(STM32L443xx) || defined(STM32L452xx) || defined(STM32L462xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #else #error "Unsupported STM32L4 mcu" #endif @@ -293,19 +304,19 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32WB) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32WBA) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_DCD_ENDPOINT_MAX 9 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 #elif TU_CHECK_MCU(OPT_MCU_STM32U5) - #if defined (STM32U535xx) || defined (STM32U545xx) + #if defined(STM32U535xx) || defined(STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #else #define TUP_USBIP_DWC2 @@ -313,33 +324,38 @@ // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \ - defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) - #define TUP_DCD_ENDPOINT_MAX 9 - #define TUP_RHPORT_HIGHSPEED 1 + defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 #else - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #endif #endif #elif TU_CHECK_MCU(OPT_MCU_STM32L5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32U0) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 + +#elif TU_CHECK_MCU(OPT_MCU_STM32U3) + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 // FS has 6, HS has 9 - #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_DCD_ENDPOINT_MAX 9 // MCU with on-chip HS Phy - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_RHPORT_HIGHSPEED 1 // Enable dcache if DMA is enabled #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE @@ -350,39 +366,39 @@ // Sony //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_CXD56) - #define TUP_DCD_ENDPOINT_MAX 7 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 7 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ // TI //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_MSP430x5xx) - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_MSP432E4, OPT_MCU_TM4C123, OPT_MCU_TM4C129) #define TUP_USBIP_MUSB #define TUP_USBIP_MUSB_TI - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 //--------------------------------------------------------------------+ // ValentyUSB (Litex) //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_VALENTYUSB_EPTRI) - #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_MAX 16 //--------------------------------------------------------------------+ // Nuvoton //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_NUC121, OPT_MCU_NUC126) - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_NUC120) - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_DCD_ENDPOINT_MAX 6 #elif TU_CHECK_MCU(OPT_MCU_NUC505) - #define TUP_DCD_ENDPOINT_MAX 12 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 12 + #define TUP_RHPORT_HIGHSPEED 1 //--------------------------------------------------------------------+ // Espressif @@ -390,114 +406,124 @@ #elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_ESP32 - #define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN - #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN + + // clang-format off + #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format on #if CFG_TUSB_MCU == OPT_MCU_ESP32S3 #define TUP_MCU_MULTIPLE_CORE 1 #endif // Disable slave if DMA is enabled - #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE + #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE #elif TU_CHECK_MCU(OPT_MCU_ESP32P4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_ESP32 - #define TUP_RHPORT_HIGHSPEED 1 // port0 FS, port1 HS - #define TUP_DCD_ENDPOINT_MAX 16 // FS 7 ep, HS 16 ep + #define TUP_RHPORT_HIGHSPEED 1 // port0 FS, port1 HS + #define TUP_DCD_ENDPOINT_MAX 16 // FS 7 ep, HS 16 ep - #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format off + #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format on - #define TUP_MCU_MULTIPLE_CORE 1 + #define TUP_MCU_MULTIPLE_CORE 1 // Disable slave if DMA is enabled - #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE + #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE // Enable dcache if DMA is enabled - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE - #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 64 + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 64 -#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C5, OPT_MCU_ESP32C6, OPT_MCU_ESP32C61, OPT_MCU_ESP32H2) +#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C5, OPT_MCU_ESP32C6, \ + OPT_MCU_ESP32C61, OPT_MCU_ESP32H2) #if (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) - #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" + #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" #endif - #define TUP_DCD_ENDPOINT_MAX 0 - #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #define TUP_DCD_ENDPOINT_MAX 0 + + // clang-format off + #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + // clang-format on + //--------------------------------------------------------------------+ // Dialog //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_DA1469X) - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_EDPT_CLOSE_API //--------------------------------------------------------------------+ // Raspberry Pi //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_RP2040) - #define TUP_DCD_EDPT_ISO_ALLOC - #define TUP_DCD_ENDPOINT_MAX 16 - #define TUP_MCU_MULTIPLE_CORE 1 + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_MCU_MULTIPLE_CORE 1 - #define TU_ATTR_FAST_FUNC __not_in_flash("tinyusb") + #define TU_ATTR_FAST_FUNC __not_in_flash("tinyusb") //--------------------------------------------------------------------+ // Silabs //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_EFM32GG) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 7 + #define TUP_DCD_ENDPOINT_MAX 7 //--------------------------------------------------------------------+ // Renesas //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N, OPT_MCU_RAXXX) #define TUP_USBIP_RUSB2 - #define TUP_DCD_ENDPOINT_MAX 10 + #define TUP_DCD_ENDPOINT_MAX 10 //--------------------------------------------------------------------+ // GigaDevice //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_GD32VF103) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 //--------------------------------------------------------------------+ // Broadcom //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 //--------------------------------------------------------------------+ // Infineon //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_XMC4000) #define TUP_USBIP_DWC2 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 //--------------------------------------------------------------------+ // BridgeTek //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_FT90X) - #define TUP_DCD_ENDPOINT_MAX 8 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY #elif TU_CHECK_MCU(OPT_MCU_FT93X) - #define TUP_DCD_ENDPOINT_MAX 16 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ // Allwinner //--------------------------------------------------------------------+ #elif TU_CHECK_MCU(OPT_MCU_F1C100S) - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 //--------------------------------------------------------------------+ // WCH @@ -507,31 +533,35 @@ #define TUP_USBIP_WCH_USBFS #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 0 + #define CFG_TUD_WCH_USBIP_USBFS 0 #endif #if !defined(CFG_TUD_WCH_USBIP_USBHS) - #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) + #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) #endif - #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS - #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + + #if CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_EDPT_CLOSE_API + #endif #elif TU_CHECK_MCU(OPT_MCU_CH32V103) #define TUP_USBIP_WCH_USBFS #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 1 + #define CFG_TUD_WCH_USBIP_USBFS 1 #endif - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) // v20x support both port0 FSDEV (USBD) and port1 USBFS #define TUP_USBIP_WCH_USBFS #ifndef CFG_TUH_WCH_USBIP_USBFS - #define CFG_TUH_WCH_USBIP_USBFS 1 + #define CFG_TUH_WCH_USBIP_USBFS 1 #endif #define TUP_USBIP_FSDEV @@ -539,14 +569,14 @@ // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 0 + #define CFG_TUD_WCH_USBIP_USBFS 0 #endif #if !defined(CFG_TUD_WCH_USBIP_FSDEV) - #define CFG_TUD_WCH_USBIP_FSDEV (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) + #define CFG_TUD_WCH_USBIP_FSDEV (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) #endif - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_CH32V307) // v307 support both FS and HS, default to HS @@ -554,15 +584,19 @@ #define TUP_USBIP_WCH_USBFS #if !defined(CFG_TUD_WCH_USBIP_USBFS) - #define CFG_TUD_WCH_USBIP_USBFS 0 + #define CFG_TUD_WCH_USBIP_USBFS 0 #endif #if !defined(CFG_TUD_WCH_USBIP_USBHS) - #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) + #define CFG_TUD_WCH_USBIP_USBHS (CFG_TUD_WCH_USBIP_USBFS ? 0 : 1) #endif - #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS - #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) + + #if CFG_TUD_WCH_USBIP_USBHS + #define TUP_DCD_EDPT_CLOSE_API + #endif //--------------------------------------------------------------------+ // Analog Devices @@ -570,8 +604,8 @@ #elif TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) #define TUP_USBIP_MUSB #define TUP_USBIP_MUSB_ADI - #define TUP_DCD_ENDPOINT_MAX 12 - #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_DCD_ENDPOINT_MAX 12 + #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY //--------------------------------------------------------------------+ @@ -580,46 +614,44 @@ #elif TU_CHECK_MCU(OPT_MCU_AT32F403A_407) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F413) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F415) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 4 + #define TUP_DCD_ENDPOINT_MAX 4 #elif TU_CHECK_MCU(OPT_MCU_AT32F435_437) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F423) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_AT32F402_405) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 // AT32F405xx has on-chip HS PHY - #if defined(AT32F405CBT7) || defined(AT32F405CBU7) || \ - defined(AT32F405CCT7) || defined(AT32F405CCU7) || \ - defined(AT32F405KBU7_4) || defined(AT32F405KCU7_4) || \ - defined(AT32F405RBT7_7) || defined(AT32F405RBT7) || \ - defined(AT32F405RCT7_7) || defined(AT32F405RCT7) - #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS + #if defined(AT32F405CBT7) || defined(AT32F405CBU7) || defined(AT32F405CCT7) || defined(AT32F405CCU7) || \ + defined(AT32F405KBU7_4) || defined(AT32F405KCU7_4) || defined(AT32F405RBT7_7) || defined(AT32F405RBT7) || \ + defined(AT32F405RCT7_7) || defined(AT32F405RCT7) + #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS #endif #elif TU_CHECK_MCU(OPT_MCU_AT32F425) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #endif @@ -629,7 +661,7 @@ #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL - #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) + #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4 * (CFG_TUH_DEVICE_MAX - 1)) #endif #endif @@ -639,17 +671,17 @@ //--------------------------------------------------------------------+ #ifndef TUP_MCU_MULTIPLE_CORE -#define TUP_MCU_MULTIPLE_CORE 0 + #define TUP_MCU_MULTIPLE_CORE 0 #endif #if !defined(TUP_DCD_ENDPOINT_MAX) && defined(CFG_TUD_ENABLED) && CFG_TUD_ENABLED #warning "TUP_DCD_ENDPOINT_MAX is not defined for this MCU, default to 8" - #define TUP_DCD_ENDPOINT_MAX 8 + #define TUP_DCD_ENDPOINT_MAX 8 #endif // Default to fullspeed if not defined #ifndef TUP_RHPORT_HIGHSPEED - #define TUP_RHPORT_HIGHSPEED 0 + #define TUP_RHPORT_HIGHSPEED 0 #endif // fast function, normally mean placing function in SRAM @@ -657,8 +689,12 @@ #define TU_ATTR_FAST_FUNC #endif -// USBIP that support ISO alloc & activate API -#if defined(TUP_USBIP_DWC2) || defined(TUP_USBIP_FSDEV) || defined(TUP_USBIP_MUSB) +#if defined(TUP_USBIP_IP3511) || defined(TUP_USBIP_RUSB2) + #define TUP_DCD_EDPT_CLOSE_API +#endif + +// USBIP implement dcd_edpt_close() and does not support ISO alloc & activate API +#ifndef TUP_DCD_EDPT_CLOSE_API #define TUP_DCD_EDPT_ISO_ALLOC #endif diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 31aca8a31..be1264a71 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -40,6 +40,12 @@ extern tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM]; // Endpoint //--------------------------------------------------------------------+ +enum { + TU_EDPT_STATE_BUSY = 0x01, + TU_EDPT_STATE_STALLED = 0x02, + TU_EDPT_STATE_CLAIMED = 0x04, +}; + typedef struct TU_ATTR_PACKED { volatile uint8_t busy : 1; volatile uint8_t stalled : 1; @@ -48,8 +54,8 @@ typedef struct TU_ATTR_PACKED { typedef struct { struct TU_ATTR_PACKED { - uint8_t is_host : 1; // 1: host, 0: device - uint8_t is_mps512 : 1; // 1: 512, 0: 64 since stream is used for Bulk only + bool is_host : 1; // 1: host, 0: device + bool is_mps512 : 1; // 1: 512, 0: 64 since stream is used for Bulk only }; uint8_t ep_addr; uint16_t ep_bufsize; @@ -93,24 +99,27 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); // Open an stream for an endpoint -TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { - tu_fifo_clear(&s->ff); +TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { s->ep_addr = desc_ep->bEndpointAddress; - s->is_mps512 = (tu_edpt_packet_size(desc_ep) == 512) ? 1 : 0; + s->is_mps512 = tu_edpt_packet_size(desc_ep) == 512; } -TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_close(tu_edpt_stream_t* s) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_is_opened(const tu_edpt_stream_t *s) { + return s->ep_addr != 0; +} + +TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_close(tu_edpt_stream_t* s) { s->ep_addr = 0; } -// Clear fifo -TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { return tu_fifo_clear(&s->ff); } +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_empty(tu_edpt_stream_t *s) { + return tu_fifo_empty(&s->ff); +} + //--------------------------------------------------------------------+ // Stream Write //--------------------------------------------------------------------+ @@ -118,7 +127,7 @@ bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { // Write to stream uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize); -// Start an usb transfer if endpoint is not busy +// Start an usb transfer if endpoint is not busy. Return number of queued bytes uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s); // Start an zero-length packet if needed @@ -141,27 +150,25 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s); // Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { - if (tu_fifo_depth(&s->ff)) { + if (0u != tu_fifo_depth(&s->ff)) { tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); } } // Complete read transfer with provided buffer TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t* s, const void * buf, uint32_t xferred_bytes) { - if (tu_fifo_depth(&s->ff)) { +void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t *s, const void *buf, uint32_t xferred_bytes) { + if (0u != tu_fifo_depth(&s->ff)) { tu_fifo_write_n(&s->ff, buf, (uint16_t) xferred_bytes); } } // Get the number of bytes available for reading -TU_ATTR_ALWAYS_INLINE static inline -uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_edpt_stream_read_available(const tu_edpt_stream_t *s) { return (uint32_t) tu_fifo_count(&s->ff); } -TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_peek(tu_edpt_stream_t *s, uint8_t *ch) { return tu_fifo_peek(&s->ff, ch); } diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index b3ef1e9c9..73c816e3e 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -77,7 +77,7 @@ *------------------------------------------------------------------*/ typedef enum { - TUSB_ROLE_INVALID = 0, + TUSB_ROLE_INVALID = 0u, TUSB_ROLE_DEVICE = 0x1, TUSB_ROLE_HOST = 0x2, } tusb_role_t; @@ -103,6 +103,7 @@ typedef enum { TUSB_DIR_OUT = 0, TUSB_DIR_IN = 1, + TUSB_EPNUM_MASK = 0x0F, TUSB_DIR_IN_MASK = 0x80 } tusb_dir_t; @@ -178,7 +179,7 @@ typedef enum { } tusb_request_feature_selector_t; typedef enum { - TUSB_REQ_TYPE_STANDARD = 0, + TUSB_REQ_TYPE_STANDARD = 0u, TUSB_REQ_TYPE_CLASS, TUSB_REQ_TYPE_VENDOR, TUSB_REQ_TYPE_INVALID @@ -252,8 +253,8 @@ typedef enum { } device_capability_type_t; enum { - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = 1u << 5, - TUSB_DESC_CONFIG_ATT_SELF_POWERED = 1u << 6, + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = 1 << 5, + TUSB_DESC_CONFIG_ATT_SELF_POWERED = 1 << 6, }; #define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) @@ -311,7 +312,7 @@ enum { }; enum { - TUSB_INDEX_INVALID_8 = 0xFFu + TUSB_INDEX_INVALID_8 = 0xFF }; //--------------------------------------------------------------------+ @@ -350,7 +351,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; -TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18u, "size is not correct"); // USB Binary Device Object Store (BOS) Descriptor typedef struct TU_ATTR_PACKED { @@ -360,7 +361,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS } tusb_desc_bos_t; -TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_desc_bos_t) == 5u, "size is not correct"); /// USB Configuration Descriptor typedef struct TU_ATTR_PACKED { @@ -375,7 +376,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). } tusb_desc_configuration_t; -TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_desc_configuration_t) == 9u, "size is not correct"); /// USB Interface Descriptor typedef struct TU_ATTR_PACKED { @@ -391,7 +392,7 @@ typedef struct TU_ATTR_PACKED { uint8_t iInterface ; ///< Index of string descriptor describing this interface } tusb_desc_interface_t; -TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_t) == 9u, "size is not correct"); /// USB Endpoint Descriptor typedef struct TU_ATTR_PACKED { @@ -411,7 +412,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bInterval ; // Polling interval, in frames or microframes depending on the operating speed } tusb_desc_endpoint_t; -TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_desc_endpoint_t) == 7u, "size is not correct"); /// USB Other Speed Configuration Descriptor typedef struct TU_ATTR_PACKED { @@ -441,7 +442,7 @@ typedef struct TU_ATTR_PACKED { uint8_t bReserved ; ///< Reserved for future use, must be zero } tusb_desc_device_qualifier_t; -TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_desc_device_qualifier_t) == 10u, "size is not correct"); /// USB Interface Association Descriptor (IAD ECN) typedef struct TU_ATTR_PACKED { @@ -458,7 +459,7 @@ typedef struct TU_ATTR_PACKED { uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. } tusb_desc_interface_assoc_t; -TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8u, "size is not correct"); // USB String Descriptor typedef struct TU_ATTR_PACKED { @@ -528,7 +529,7 @@ typedef struct TU_ATTR_PACKED { uint16_t wLength; } tusb_control_request_t; -TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); +TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8u, "size is not correct"); TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END @@ -544,11 +545,11 @@ TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) { // Get Endpoint number from address TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) { - return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); + return (uint8_t) (addr & TUSB_EPNUM_MASK); } TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) { - return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); + return (uint8_t) (num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0u)); } TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_edpt_packet_size(tusb_desc_endpoint_t const* desc_ep) { diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index db91a73d9..587554e7f 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -67,10 +67,8 @@ //--------------------------------------------------------------------+ // TU_VERIFY Helper //--------------------------------------------------------------------+ - #if CFG_TUSB_DEBUG - #include <stdio.h> - #define TU_MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) + #define TU_MESS_FAILED() TU_LOG1("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) #else #define TU_MESS_FAILED() do {} while (0) #endif @@ -80,7 +78,7 @@ defined(__ARM7M__) || defined (__ARM7EM__) || defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) #define TU_BREAKPOINT() do { \ volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ - if ( (*ARM_CM_DHCSR) & 1UL ) __asm("BKPT #0\n"); /* Only halt mcu if debugger is attached */ \ + if (0u != ((*ARM_CM_DHCSR) & 1UL)) { __asm("BKPT #0\n"); } /* Only halt mcu if debugger is attached */ \ } while(0) #elif defined(__riscv) && !TUSB_MCU_VENDOR_ESPRESSIF @@ -100,7 +98,7 @@ *------------------------------------------------------------------*/ #define TU_VERIFY_DEFINE(_cond, _ret) \ do { \ - if ( !(_cond) ) { return _ret; } \ + if (!(_cond)) { return _ret; } \ } while(0) #define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) diff --git a/src/device/dcd.h b/src/device/dcd.h index 400f62bff..8a074ab47 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -79,7 +79,7 @@ typedef struct TU_ATTR_ALIGNED(4) { // FUNC_CALL struct { - void (*func) (void*); + void (*func) (void* param); void* param; }func_call; }; @@ -158,11 +158,11 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc void dcd_edpt_close_all (uint8_t rhport); // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr); // Submit an transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack // This API is optional, may be useful for register-based for transferring data. -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr); // Stall endpoint, any queuing transfer should be removed from endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); @@ -171,7 +171,12 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); // This API never calls with control endpoints, since it is auto cleared when receiving setup packet void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); -#ifdef TUP_DCD_EDPT_ISO_ALLOC +#ifdef TUP_DCD_EDPT_CLOSE_API +// Close an endpoint. +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr); + +#else + // Allocate packet buffer used by ISO endpoints // Some MCU need manual packet buffer allocation, we allocate the largest size to avoid clustering bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size); @@ -179,10 +184,6 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet // Configure and enable an ISO endpoint according to descriptor bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); -#else -// Close an endpoint. -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr); - #endif //--------------------------------------------------------------------+ @@ -214,7 +215,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport dcd_event_t event; event.rhport = rhport; event.event_id = DCD_EVENT_SETUP_RECEIVED; - memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t)); + (void) memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t)); dcd_event_handler(&event, in_isr); } diff --git a/src/device/usbd.c b/src/device/usbd.c index b1aef0b38..d4dfae4b4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -321,6 +321,20 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .sof = NULL }, #endif + + #if CFG_TUD_MTP + { + .name = DRIVER_NAME("MTP"), + .init = mtpd_init, + .deinit = mtpd_deinit, + .reset = mtpd_reset, + .open = mtpd_open, + .control_xfer_cb = mtpd_control_xfer_cb, + .xfer_cb = mtpd_xfer_cb, + .xfer_isr = NULL, + .sof = NULL + }, + #endif }; enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; @@ -338,9 +352,13 @@ TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8 if (drvid < _app_driver_count) { // Application drivers driver = &_app_driver[drvid]; - } else if (drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0) { - driver = &_usbd_driver[drvid - _app_driver_count]; + } else{ + drvid -= _app_driver_count; + if (drvid < BUILTIN_DRIVER_COUNT) { + driver = &_usbd_driver[drvid]; + } } + return driver; } @@ -401,8 +419,8 @@ TU_ATTR_WEAK usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_c return NULL; } -TU_ATTR_WEAK bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { - (void) rhport; (void) ep_addr; (void) ff; (void) total_bytes; +TU_ATTR_WEAK bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) rhport; (void) ep_addr; (void) ff; (void) total_bytes; (void) is_isr; return false; } @@ -558,7 +576,7 @@ bool tud_deinit(uint8_t rhport) { // Deinit device controller driver dcd_int_disable(rhport); dcd_disconnect(rhport); - dcd_deinit(rhport); + TU_VERIFY(dcd_deinit(rhport)); // Deinit class drivers for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { @@ -580,7 +598,6 @@ bool tud_deinit(uint8_t rhport) { #endif _usbd_rhport = RHPORT_INVALID; - return true; } @@ -592,8 +609,8 @@ static void configuration_reset(uint8_t rhport) { } tu_varclr(&_usbd_dev); - memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping + (void) memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping + (void) memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping } static void usbd_reset(uint8_t rhport) { @@ -624,12 +641,16 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { (void) in_isr; // not implemented yet // Skip if stack is not initialized - if (!tud_inited()) return; + if (!tud_inited()) { + return; + } // Loop until there is no more events in the queue while (1) { dcd_event_t event; - if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) return; + if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) { + return; + } #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG_USBD("\r\n"); // extra line for setup @@ -653,7 +674,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { TU_ASSERT(_usbd_queued_setup > 0,); _usbd_queued_setup--; TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); - if (_usbd_queued_setup) { + if (_usbd_queued_setup != 0) { TU_LOG_USBD(" Skipped since there is other SETUP in queue\r\n"); break; } @@ -689,8 +710,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; if (0 == epnum) { - usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, - event.xfer_complete.len); + usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); } else { usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]); TU_ASSERT(driver,); @@ -724,7 +744,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { case USBD_EVENT_FUNC_CALL: TU_LOG_USBD("\r\n"); - if (event.func_call.func) { + if (event.func_call.func != NULL) { event.func_call.func(event.func_call.param); } break; @@ -778,7 +798,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } #endif - switch ( p_request->bmRequestType_bit.recipient ) { + switch (p_request->bmRequestType_bit.recipient) { //-V2520 //------------- Device Requests e.g in enumeration -------------// case TUSB_REQ_RCPT_DEVICE: if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) { @@ -792,13 +812,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return invoke_class_control(rhport, driver, p_request); } - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { + if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) { // Non-standard request is not supported TU_BREAKPOINT(); return false; } - switch ( p_request->bRequest ) { + switch (p_request->bRequest) { //-V2520 case TUSB_REQ_SET_ADDRESS: // Depending on mcu, status phase could be sent either before or after changing device address, // or even require stack to not response with status at all @@ -820,18 +840,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Only process if new configure is different if (_usbd_dev.cfg_num != cfg_num) { - if ( _usbd_dev.cfg_num ) { + if (_usbd_dev.cfg_num != 0) { // already configured: need to clear all endpoints and driver first TU_LOG_USBD(" Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num); - // disable SOF dcd_sof_enable(rhport, false); - - // close all non-control endpoints, cancel all pending transfers if any dcd_edpt_close_all(rhport); // close all drivers and current configured state except bus speed - uint8_t const speed = _usbd_dev.speed; + const uint8_t speed = _usbd_dev.speed; configuration_reset(rhport); _usbd_dev.speed = speed; // restore speed @@ -839,18 +856,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.cfg_num = cfg_num; - // Handle the new configuration and execute the corresponding callback - if ( cfg_num ) { - // switch to new configuration if not zero + // Handle the new configuration + if (cfg_num == 0) { + tud_umount_cb(); + } else { if (!process_set_config(rhport, cfg_num)) { - TU_MESS_FAILED(); - TU_BREAKPOINT(); _usbd_dev.cfg_num = 0; - return false; + TU_ASSERT(false); } tud_mount_cb(); - } else { - tud_umount_cb(); } } @@ -859,17 +873,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_GET_DESCRIPTOR: - TU_VERIFY( process_get_descriptor(rhport, p_request) ); + TU_VERIFY(process_get_descriptor(rhport, p_request)); break; case TUSB_REQ_SET_FEATURE: - switch(p_request->wValue) { + switch(p_request->wValue) { //-V2520 case TUSB_REQ_FEATURE_REMOTE_WAKEUP: TU_LOG_USBD(" Enable Remote Wakeup\r\n"); // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; tud_control_status(rhport, p_request); - break; + break; #if CFG_TUD_TEST_MODE case TUSB_REQ_FEATURE_TEST_MODE: { @@ -883,7 +897,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const tud_control_status(rhport, p_request); break; } - #endif /* CFG_TUD_TEST_MODE */ + #endif // Stall unsupported feature selector default: return false; @@ -893,13 +907,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_CLEAR_FEATURE: // Only support remote wakeup for device feature TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue); - TU_LOG_USBD(" Disable Remote Wakeup\r\n"); // Host may disable remote wake up after resuming _usbd_dev.remote_wakeup_en = false; tud_control_status(rhport, p_request); - break; + break; case TUSB_REQ_GET_STATUS: { // Device status bit mask @@ -925,24 +938,24 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // all requests to Interface (STD or Class) is forwarded to class driver. // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE - if ( !invoke_class_control(rhport, driver, p_request) ) { + if (!invoke_class_control(rhport, driver, p_request)) { // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class // driver doesn't use alternate settings or implement this TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type); - switch(p_request->bRequest) { - case TUSB_REQ_GET_INTERFACE: - case TUSB_REQ_SET_INTERFACE: - // Clear complete callback if driver set since it can also stall the request. - usbd_control_set_complete_callback(NULL); + // Clear complete callback if driver set since it can also stall the request. + usbd_control_set_complete_callback(NULL); - if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) { - uint8_t alternate = 0; - tud_control_xfer(rhport, p_request, &alternate, 1); - }else { - tud_control_status(rhport, p_request); - } - break; + switch (p_request->bRequest) { //-V2520 + case TUSB_REQ_GET_INTERFACE: { + uint8_t alternate = 0; + tud_control_xfer(rhport, p_request, &alternate, 1); + break; + } + + case TUSB_REQ_SET_INTERFACE: + tud_control_status(rhport, p_request); + break; default: return false; } @@ -959,15 +972,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) ); usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]); - if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { + if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) { // Forward class request to its driver TU_VERIFY(driver); return invoke_class_control(rhport, driver, p_request); } else { // Handle STD request to endpoint - switch ( p_request->bRequest ) { + switch (p_request->bRequest) { //-V2520 case TUSB_REQ_GET_STATUS: { - uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000; + uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001u : 0x0000u; tud_control_xfer(rhport, p_request, &status, 2); } break; @@ -982,7 +995,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } } - if (driver) { + if (driver != NULL) { // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request // We will also forward std request targeted endpoint to class drivers as well @@ -992,7 +1005,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const usbd_control_set_complete_callback(NULL); // skip ZLP status if driver already did that - if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request); + if (!_usbd_dev.ep_status[0][TUSB_DIR_IN].busy) { + tud_control_status(rhport, p_request); + } } } break; @@ -1003,8 +1018,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const return false; } } + break; } - break; // Unknown recipient default: @@ -1067,10 +1082,11 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or // BTH (even CDC) with class in device descriptor (single interface) - if ( assoc_itf_count == 1) - { + if (assoc_itf_count == 1) { #if CFG_TUD_CDC - if ( driver->open == cdcd_open ) assoc_itf_count = 2; + if ( driver->open == cdcd_open ) { + assoc_itf_count = 2; + } #endif #if CFG_TUD_MIDI @@ -1087,6 +1103,28 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT if ( driver->open == btd_open ) assoc_itf_count = 2; #endif + + #if CFG_TUD_AUDIO + if (driver->open == audiod_open) { + // UAC1 device doesn't have IAD, needs to read AS interface count from CS AC descriptor + if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { + uint8_t const* p = tu_desc_next(p_desc); + uint8_t const* const itf_end = p_desc + remaining_len; + while (p < itf_end) { + if (TUSB_DESC_CS_INTERFACE == tu_desc_type(p) && + AUDIO10_CS_AC_INTERFACE_HEADER == ((audio10_desc_cs_ac_interface_1_t const *) p)->bDescriptorSubType) { + audio10_desc_cs_ac_interface_1_t const * p_header = (audio10_desc_cs_ac_interface_1_t const *) p; + // AC + AS interfaces + assoc_itf_count = p_header->bInCollection + 1; + break; + } + p = tu_desc_next(p); + } + } + } + #endif } // bind (associated) interfaces to found driver @@ -1122,8 +1160,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue); uint8_t const desc_index = tu_u16_low( p_request->wValue ); - switch(desc_type) - { + switch(desc_type) { //-V2520 case TUSB_DESC_DEVICE: { TU_LOG_USBD(" Device\r\n"); @@ -1151,7 +1188,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); - TU_VERIFY(desc_bos); + TU_VERIFY(desc_bos != 0); // Use offsetof to avoid pointer to the odd/misaligned address uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); @@ -1167,12 +1204,12 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const if ( desc_type == TUSB_DESC_CONFIGURATION ) { TU_LOG_USBD(" Configuration[%u]\r\n", desc_index); desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); - TU_ASSERT(desc_config); + TU_ASSERT(desc_config != 0); }else { // Host only request this after getting Device Qualifier descriptor TU_LOG_USBD(" Other Speed Configuration\r\n"); desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); - TU_VERIFY(desc_config); + TU_VERIFY(desc_config != 0); } // Use offsetof to avoid pointer to the odd/misaligned address @@ -1182,8 +1219,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } // break; // unreachable - case TUSB_DESC_STRING: - { + case TUSB_DESC_STRING: { TU_LOG_USBD(" String[%u]\r\n", desc_index); // String Descriptor always uses the desc set from user @@ -1396,7 +1432,7 @@ bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) { return tu_edpt_release(ep_state, _usbd_mutex); } -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -1419,7 +1455,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t t // could return and USBD task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = 1; - if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes)) { + if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes, is_isr)) { return true; } else { // DCD error, mark endpoint as ready to allow next transfer @@ -1435,7 +1471,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) { rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -1450,7 +1486,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_ // and usbd task can preempt and clear the busy _usbd_dev.ep_status[epnum][dir].busy = 1; - if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes)) { + if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes, is_isr)) { TU_LOG_USBD("OK\r\n"); return true; } else { diff --git a/src/device/usbd.h b/src/device/usbd.h index e5a848809..c446638c3 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBD_H_ -#define _TUSB_USBD_H_ +#ifndef TUSB_USBD_H_ +#define TUSB_USBD_H_ #include "common/tusb_common.h" @@ -95,7 +95,9 @@ bool tud_suspended(void); // Check if device is ready to transfer TU_ATTR_ALWAYS_INLINE static inline bool tud_ready(void) { - return tud_mounted() && !tud_suspended(); + const bool is_mounted = tud_mounted(); + const bool is_suspended = tud_suspended(); + return is_mounted && !is_suspended; } // Remote wake up host, only if suspended and enabled by host @@ -270,6 +272,25 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ //--------------------------------------------------------------------+ +// MTP Descriptor Templates +//--------------------------------------------------------------------+ + +// Length of template descriptor: 30 bytes +#define TUD_MTP_DESC_LEN (9 + 7 + 7 + 7) + +// Interface number, string index, EP event, EP event size, EP event polling, EP Out & EP In address, EP size +#define TUD_MTP_DESCRIPTOR(_itfnum, _stridx, _ep_evt, _ep_evt_size, _ep_evt_polling_interval, _epout, _epin, _epsize) \ + /* Interface */\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 3, TUSB_CLASS_IMAGE, MTP_SUBCLASS_STILL_IMAGE, MTP_PROTOCOL_PIMA_15470, _stridx,\ + /* Endpoint Interrupt */\ + 7, TUSB_DESC_ENDPOINT, _ep_evt, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_evt_size), _ep_evt_polling_interval,\ + /* Endpoint Out */\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\ + /* Endpoint In */\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + + +//--------------------------------------------------------------------+ // HID Descriptor Templates //--------------------------------------------------------------------+ @@ -280,7 +301,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval #define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol != HID_ITF_PROTOCOL_NONE) ? (uint8_t)HID_SUBCLASS_BOOT : 0u), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint In */\ @@ -293,7 +314,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval #define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \ /* Interface */\ - 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol != HID_ITF_PROTOCOL_NONE) ? (uint8_t)HID_SUBCLASS_BOOT : 0u), _boot_protocol, _stridx,\ /* HID descriptor */\ 9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\ /* Endpoint Out */\ @@ -311,7 +332,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ /* Audio Control (AC) Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, _stridx,\ /* AC Header */\ - 9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ + 9, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\ /* MIDI Streaming (MS) Interface */\ 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_FUNC_PROTOCOL_CODE_UNDEF, 0,\ /* MS Header */\ @@ -364,242 +385,352 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ TUD_MIDI_JACKID_OUT_EMB(1) //--------------------------------------------------------------------+ -// Audio v2.0 Descriptor Templates +// Audio Descriptor Templates //--------------------------------------------------------------------+ + +/* Audio v1.0 Descriptor Templates */ + +/* Standard AC Interface Descriptor UAC1 (4.3.1) */ +#define TUD_AUDIO10_DESC_STD_AC_LEN 9 +#define TUD_AUDIO10_DESC_STD_AC(_itfnum, _nEPs, _stridx) \ + TUD_AUDIO10_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V1, _stridx + +/* Class-Specific AC Interface Header Descriptor UAC1 (4.3.2) */ +#define TUD_AUDIO10_DESC_CS_AC_LEN(_nintfs) (8 + (_nintfs)) +// Class-Specific AC Interface Header descriptor, take list of streaming interface numbers as variable arguments +#define TUD_AUDIO10_DESC_CS_AC(_bcdADC, _totallen, ...) \ + TUD_AUDIO10_DESC_CS_AC_LEN(TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), U16_TO_U8S_LE(_totallen + TUD_AUDIO10_DESC_CS_AC_LEN(TU_ARGS_NUM(__VA_ARGS__))), TU_ARGS_NUM(__VA_ARGS__), __VA_ARGS__ + +/* Input Terminal Descriptor UAC1 (4.3.2.1) */ +#define TUD_AUDIO10_DESC_INPUT_TERM_LEN 12 +#define TUD_AUDIO10_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _nchannels, _channelcfg, _idxchannelnames, _stridx) \ + TUD_AUDIO10_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _nchannels, U16_TO_U8S_LE(_channelcfg), _idxchannelnames, _stridx + +/* Output Terminal Descriptor UAC1 (4.3.2.2) */ +#define TUD_AUDIO10_DESC_OUTPUT_TERM_LEN 9 +#define TUD_AUDIO10_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _stridx) \ + TUD_AUDIO10_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _stridx + +/* Mixer Unit Descriptor UAC1 (4.3.2.3) - One Input Pin */ +#define TUD_AUDIO10_DESC_MIXER_UNIT_ONE_PIN_LEN(_ctrlsize) (11 + (_ctrlsize)) +#define TUD_AUDIO10_DESC_MIXER_UNIT_ONE_PIN(_unitid, _srcid, _nrchannels, _channelcfg, _idxchannelnames, _ctrlsize, _stridx, ...) \ + TUD_AUDIO10_DESC_MIXER_UNIT_ONE_PIN_LEN(_ctrlsize), TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_MIXER_UNIT, _unitid, 1, _srcid, _nrchannels, U16_TO_U8S_LE(_channelcfg), _idxchannelnames, __VA_ARGS__, _stridx + +/* Selector Unit Descriptor UAC1 (4.3.2.4) - One Input Pin */ +#define TUD_AUDIO10_DESC_SELECTOR_UNIT_ONE_PIN_LEN 7 +#define TUD_AUDIO10_DESC_SELECTOR_UNIT_ONE_PIN(_unitid, _srcid, _stridx) \ + TUD_AUDIO10_DESC_SELECTOR_UNIT_ONE_PIN_LEN, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_SELECTOR_UNIT, _unitid, 1, _srcid, _stridx + +/* Feature Unit Descriptor UAC1 (4.3.2.5) - Variable Channels */ +#define TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(_nchannels) (7 + ((_nchannels) + 1) * 2) +// Feature Unit descriptor, take list of control bitmaps for master channel + each channel as variable arguments +#define TUD_AUDIO10_DESC_FEATURE_UNIT(_unitid, _srcid, _stridx, ...) \ + TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(TU_ARGS_NUM(__VA_ARGS__) - 1), TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, 2, TU_ARGS_APPLY_EXPAND(U16_TO_U8S_LE, __VA_ARGS__), _stridx + +/* Standard AS Interface Descriptor UAC1 (4.5.1) */ +#define TUD_AUDIO10_DESC_STD_AS_LEN 9 +#define TUD_AUDIO10_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ + TUD_AUDIO10_DESC_STD_AS_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V1, _stridx + +/* Class-Specific AS Interface Descriptor UAC1 (4.5.2) */ +#define TUD_AUDIO10_DESC_CS_AS_INT_LEN 7 +#define TUD_AUDIO10_DESC_CS_AS_INT(_termid, _delay, _formattype) \ + TUD_AUDIO10_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AS_INTERFACE_AS_GENERAL, _termid, _delay, U16_TO_U8S_LE(_formattype) + +/* Type I Format Type Descriptor UAC1 (2.2.5) */ +#define TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(_nfreqs) (8 + (_nfreqs)*3) +// Type I Format descriptor, take list of sample rates in Hz as variable arguments +#define TUD_AUDIO10_DESC_TYPE_I_FORMAT(_nrchannels, _subframesize, _bitresolution, ...) \ + TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(TU_ARGS_NUM(__VA_ARGS__)), TUSB_DESC_CS_INTERFACE, AUDIO10_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO10_FORMAT_TYPE_I, _nrchannels, _subframesize, _bitresolution, TU_ARGS_NUM(__VA_ARGS__), TU_ARGS_APPLY_EXPAND(U24_TO_U8S_LE, __VA_ARGS__) + +/* Standard AS Isochronous Audio Data Endpoint Descriptor UAC1 (4.6.1.1) */ +#define TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN 9 +#define TUD_AUDIO10_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval, _sync_ep) \ + TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval, 0x00, _sync_ep + +/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor UAC1 (4.6.1.2) */ +#define TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN 7 +#define TUD_AUDIO10_DESC_CS_AS_ISO_EP(_attr, _lockdelayunits, _lockdelay) \ + TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO10_CS_EP_SUBTYPE_GENERAL, _attr, _lockdelayunits, U16_TO_U8S_LE(_lockdelay) + +/* Standard AS Isochronous Synch Endpoint Descriptor UAC1 (4.6.2.1) */ +#define TUD_AUDIO10_DESC_STD_AS_ISO_SYNC_EP_LEN 9 +#define TUD_AUDIO10_DESC_STD_AS_ISO_SYNC_EP(_ep, _bRefresh) \ + TUD_AUDIO10_DESC_STD_AS_ISO_SYNC_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_ISOCHRONOUS, U16_TO_U8S_LE(3), 1, _bRefresh, 0x00 + +/* Standard AC Interrupt Endpoint Descriptor UAC1 (4.4.2) */ +#define TUD_AUDIO10_DESC_STD_AC_INT_EP_LEN 9 +#define TUD_AUDIO10_DESC_STD_AC_INT_EP(_ep, _interval) \ + TUD_AUDIO10_DESC_STD_AC_INT_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(2), _interval, 0x00, 0x00 + +// AUDIO simple descriptor templates for UAC1 + +// AUDIO simple descriptor (UAC1) for 1 microphone input +// - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal + +#define TUD_AUDIO10_MIC_ONE_CH_DESC_LEN(_nfreqs) (\ + + TUD_AUDIO10_DESC_STD_AC_LEN\ + + TUD_AUDIO10_DESC_CS_AC_LEN(1)\ + + TUD_AUDIO10_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO10_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(1)\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + + TUD_AUDIO10_DESC_STD_AS_LEN\ + + TUD_AUDIO10_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO10_DESC_TYPE_I_FORMAT_LEN(_nfreqs)\ + + TUD_AUDIO10_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO10_DESC_CS_AS_ISO_EP_LEN) + +#define TUD_AUDIO10_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize, ...) \ + /* Standard AC Interface Descriptor(4.3.1) */\ + TUD_AUDIO10_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + /* Class-Specific AC Interface Header Descriptor(4.3.2) */\ + TUD_AUDIO10_DESC_CS_AC(/*_bcdADC*/ 0x0100, /*_totallen*/ (TUD_AUDIO10_DESC_INPUT_TERM_LEN+TUD_AUDIO10_DESC_OUTPUT_TERM_LEN+TUD_AUDIO10_DESC_FEATURE_UNIT_LEN(1)), /*_itf*/ ((_itfnum)+1)),\ + /* Input Terminal Descriptor(4.3.2.1) */\ + TUD_AUDIO10_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_nchannels*/ 0x01, /*_channelcfg*/ AUDIO10_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_stridx*/ 0x00),\ + /* Output Terminal Descriptor(4.3.2.2) */\ + TUD_AUDIO10_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_stridx*/ 0x00),\ + /* Feature Unit Descriptor(4.3.2.5) */\ + TUD_AUDIO10_DESC_FEATURE_UNIT(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_stridx*/ 0x00, /*_ctrlmaster*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME), /*_ctrlch1*/ (AUDIO10_FU_CONTROL_BM_MUTE | AUDIO10_FU_CONTROL_BM_VOLUME)),\ + /* Standard AS Interface Descriptor(4.5.1) */\ + /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + /* Standard AS Interface Descriptor(4.5.1) */\ + /* Interface 1, Alternate 1 - alternate interface for data streaming */\ + TUD_AUDIO10_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + /* Class-Specific AS Interface Descriptor(4.5.2) */\ + TUD_AUDIO10_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_delay*/ 0x01, /*_formattype*/ AUDIO10_DATA_FORMAT_TYPE_I_PCM),\ + /* Type I Format Type Descriptor(2.2.5) */\ + TUD_AUDIO10_DESC_TYPE_I_FORMAT(/*_nrchannels*/ 0x01, /*_subframesize*/ _nBytesPerSample, /*_bitresolution*/ _nBitsUsedPerSample, /*_freq*/ __VA_ARGS__),\ + /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.6.1.1) */\ + TUD_AUDIO10_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01, /* _sync_ep */ 0x00),\ + /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.6.1.2) */\ + TUD_AUDIO10_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO10_CS_AS_ISO_DATA_EP_ATT_SAMPLING_FRQ, /*_lockdelayunits*/ AUDIO10_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001) + +/* Audio v2.0 Descriptor Templates */ + /* Standard Interface Association Descriptor (IAD) */ -#define TUD_AUDIO_DESC_IAD_LEN 8 -#define TUD_AUDIO_DESC_IAD(_firstitf, _nitfs, _stridx) \ - TUD_AUDIO_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitf, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx +#define TUD_AUDIO20_DESC_IAD_LEN 8 +#define TUD_AUDIO20_DESC_IAD(_firstitf, _nitfs, _stridx) \ + TUD_AUDIO20_DESC_IAD_LEN, TUSB_DESC_INTERFACE_ASSOCIATION, _firstitf, _nitfs, TUSB_CLASS_AUDIO, AUDIO_FUNCTION_SUBCLASS_UNDEFINED, AUDIO_FUNC_PROTOCOL_CODE_V2, _stridx /* Standard AC Interface Descriptor(4.7.1) */ -#define TUD_AUDIO_DESC_STD_AC_LEN 9 -#define TUD_AUDIO_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ - TUD_AUDIO_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx +#define TUD_AUDIO20_DESC_STD_AC_LEN 9 +#define TUD_AUDIO20_DESC_STD_AC(_itfnum, _nEPs, _stridx) /* _nEPs is 0 or 1 */\ + TUD_AUDIO20_DESC_STD_AC_LEN, TUSB_DESC_INTERFACE, _itfnum, /* fixed to zero */ 0x00, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AC Interface Header Descriptor(4.7.2) */ -#define TUD_AUDIO_DESC_CS_AC_LEN 9 -#define TUD_AUDIO_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO_DESC_CS_AC_LEN, we already do this here*/ \ - TUD_AUDIO_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO_DESC_CS_AC_LEN), _ctrl +#define TUD_AUDIO20_DESC_CS_AC_LEN 9 +#define TUD_AUDIO20_DESC_CS_AC(_bcdADC, _category, _totallen, _ctrl) /* _bcdADC : Audio Device Class Specification Release Number in Binary-Coded Decimal, _category : see audio20_function_t, _totallen : Total number of bytes returned for the class-specific AudioControl interface i.e. Clock Source, Unit and Terminal descriptors - Do not include TUD_AUDIO20_DESC_CS_AC_LEN, we already do this here*/ \ + TUD_AUDIO20_DESC_CS_AC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AC_INTERFACE_HEADER, U16_TO_U8S_LE(_bcdADC), _category, U16_TO_U8S_LE(_totallen + TUD_AUDIO20_DESC_CS_AC_LEN), _ctrl /* Clock Source Descriptor(4.7.2.1) */ -#define TUD_AUDIO_DESC_CLK_SRC_LEN 8 -#define TUD_AUDIO_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ - TUD_AUDIO_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx +#define TUD_AUDIO20_DESC_CLK_SRC_LEN 8 +#define TUD_AUDIO20_DESC_CLK_SRC(_clkid, _attr, _ctrl, _assocTerm, _stridx) \ + TUD_AUDIO20_DESC_CLK_SRC_LEN, TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AC_INTERFACE_CLOCK_SOURCE, _clkid, _attr, _ctrl, _assocTerm, _stridx /* Input Terminal Descriptor(4.7.2.4) */ -#define TUD_AUDIO_DESC_INPUT_TERM_LEN 17 -#define TUD_AUDIO_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ - TUD_AUDIO_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx +#define TUD_AUDIO20_DESC_INPUT_TERM_LEN 17 +#define TUD_AUDIO20_DESC_INPUT_TERM(_termid, _termtype, _assocTerm, _clkid, _nchannelslogical, _channelcfg, _idxchannelnames, _ctrl, _stridx) \ + TUD_AUDIO20_DESC_INPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AC_INTERFACE_INPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _clkid, _nchannelslogical, U32_TO_U8S_LE(_channelcfg), _idxchannelnames, U16_TO_U8S_LE(_ctrl), _stridx /* Output Terminal Descriptor(4.7.2.5) */ -#define TUD_AUDIO_DESC_OUTPUT_TERM_LEN 12 -#define TUD_AUDIO_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ - TUD_AUDIO_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx +#define TUD_AUDIO20_DESC_OUTPUT_TERM_LEN 12 +#define TUD_AUDIO20_DESC_OUTPUT_TERM(_termid, _termtype, _assocTerm, _srcid, _clkid, _ctrl, _stridx) \ + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN, TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AC_INTERFACE_OUTPUT_TERMINAL, _termid, U16_TO_U8S_LE(_termtype), _assocTerm, _srcid, _clkid, U16_TO_U8S_LE(_ctrl), _stridx /* Feature Unit Descriptor(4.7.2.8) */ -// 1 - Channel -#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN 6+(1+1)*4 -#define TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), _stridx - -// 2 - Channels -#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN (6+(2+1)*4) -#define TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_TWO_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), _stridx -// 4 - Channels -#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN (6+(4+1)*4) -#define TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(_unitid, _srcid, _ctrlch0master, _ctrlch1, _ctrlch2, _ctrlch3, _ctrlch4, _stridx) \ - TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, U32_TO_U8S_LE(_ctrlch0master), U32_TO_U8S_LE(_ctrlch1), U32_TO_U8S_LE(_ctrlch2), U32_TO_U8S_LE(_ctrlch3), U32_TO_U8S_LE(_ctrlch4), _stridx - -// For more channels, add definitions here +#define TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(_nchannels) (6 + ((_nchannels) + 1) * 4) +#define TUD_AUDIO20_DESC_FEATURE_UNIT(_unitid, _srcid, _stridx, ...) \ + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(TU_ARGS_NUM(__VA_ARGS__) - 1), TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AC_INTERFACE_FEATURE_UNIT, _unitid, _srcid, TU_ARGS_APPLY_EXPAND(U32_TO_U8S_LE, __VA_ARGS__), _stridx /* Standard AC Interrupt Endpoint Descriptor(4.8.2.1) */ -#define TUD_AUDIO_DESC_STD_AC_INT_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AC_INT_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AC_INT_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(6), _interval +#define TUD_AUDIO20_DESC_STD_AC_INT_EP_LEN 7 +#define TUD_AUDIO20_DESC_STD_AC_INT_EP(_ep, _interval) \ + TUD_AUDIO20_DESC_STD_AC_INT_EP_LEN, TUSB_DESC_ENDPOINT, _ep, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(6), _interval /* Standard AS Interface Descriptor(4.9.1) */ -#define TUD_AUDIO_DESC_STD_AS_INT_LEN 9 -#define TUD_AUDIO_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ - TUD_AUDIO_DESC_STD_AS_INT_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx +#define TUD_AUDIO20_DESC_STD_AS_LEN 9 +#define TUD_AUDIO20_DESC_STD_AS_INT(_itfnum, _altset, _nEPs, _stridx) \ + TUD_AUDIO20_DESC_STD_AS_LEN, TUSB_DESC_INTERFACE, _itfnum, _altset, _nEPs, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_STREAMING, AUDIO_INT_PROTOCOL_CODE_V2, _stridx /* Class-Specific AS Interface Descriptor(4.9.2) */ -#define TUD_AUDIO_DESC_CS_AS_INT_LEN 16 -#define TUD_AUDIO_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ - TUD_AUDIO_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx +#define TUD_AUDIO20_DESC_CS_AS_INT_LEN 16 +#define TUD_AUDIO20_DESC_CS_AS_INT(_termid, _ctrl, _formattype, _formats, _nchannelsphysical, _channelcfg, _stridx) \ + TUD_AUDIO20_DESC_CS_AS_INT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AS_INTERFACE_AS_GENERAL, _termid, _ctrl, _formattype, U32_TO_U8S_LE(_formats), _nchannelsphysical, U32_TO_U8S_LE(_channelcfg), _stridx /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */ -#define TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN 6 -#define TUD_AUDIO_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO_FORMAT_TYPE_I, _subslotsize, _bitresolution +#define TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN 6 +#define TUD_AUDIO20_DESC_TYPE_I_FORMAT(_subslotsize, _bitresolution) /* _subslotsize is number of bytes per sample (i.e. subslot) and can be 1,2,3, or 4 */\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN, TUSB_DESC_CS_INTERFACE, AUDIO20_CS_AS_INTERFACE_FORMAT_TYPE, AUDIO20_FORMAT_TYPE_I, _subslotsize, _bitresolution /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */ -#define TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval +#define TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN 7 +#define TUD_AUDIO20_DESC_STD_AS_ISO_EP(_ep, _attr, _maxEPsize, _interval) \ + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN, TUSB_DESC_ENDPOINT, _ep, _attr, U16_TO_U8S_LE(_maxEPsize), _interval /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ -#define TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN 8 -#define TUD_AUDIO_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ - TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) +#define TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN 8 +#define TUD_AUDIO20_DESC_CS_AS_ISO_EP(_attr, _ctrl, _lockdelayunit, _lockdelay) \ + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN, TUSB_DESC_CS_ENDPOINT, AUDIO20_CS_EP_SUBTYPE_GENERAL, _attr, _ctrl, _lockdelayunit, U16_TO_U8S_LE(_lockdelay) /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _epsize, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(_epsize), _interval +#define TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP_LEN 7 +#define TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP(_ep, _epsize, _interval) \ + TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(_epsize), _interval // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -#define TUD_AUDIO_MIC_ONE_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) +#define TUD_AUDIO20_MIC_ONE_CH_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\ + + TUD_AUDIO20_DESC_STD_AC_LEN\ + + TUD_AUDIO20_DESC_CS_AC_LEN\ + + TUD_AUDIO20_DESC_CLK_SRC_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1)\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces +#define TUD_AUDIO20_MIC_ONE_CH_DESC_N_AS_INT 1 // Number of AS interfaces -#define TUD_AUDIO_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +#define TUD_AUDIO20_MIC_ONE_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1), /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO20_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO20_CTRL_R << AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_stridx*/ 0x00, /*_ctrlch0master*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) // AUDIO simple descriptor (UAC2) for 4 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source -#define TUD_AUDIO_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN) +#define TUD_AUDIO20_MIC_FOUR_CH_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\ + + TUD_AUDIO20_DESC_STD_AC_LEN\ + + TUD_AUDIO20_DESC_CS_AC_LEN\ + + TUD_AUDIO20_DESC_CLK_SRC_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(4)\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN) -#define TUD_AUDIO_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces +#define TUD_AUDIO20_MIC_FOUR_CH_DESC_N_AS_INT 1 // Number of AS interfaces -#define TUD_AUDIO_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ +#define TUD_AUDIO20_MIC_FOUR_CH_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_MICROPHONE, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(4), /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO20_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO20_CTRL_R << AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_IN_GENERIC_MIC, /*_assocTerm*/ 0x03, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x04, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS, /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_FOUR_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_stridx*/ 0x00, /*_ctrlch0master*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch2*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch3*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch4*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum)+1), /*_altset*/ 0x01, /*_nEPs*/ 0x01, /*_stridx*/ 0x00),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ 0x03, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x04, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epin, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000) // AUDIO simple descriptor (UAC2) for mono speaker // - 1 Input Terminal, 2 Feature Unit (Mute and Volume Control), 3 Output Terminal, 4 Clock Source -#define TUD_AUDIO_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO_DESC_IAD_LEN\ - + TUD_AUDIO_DESC_STD_AC_LEN\ - + TUD_AUDIO_DESC_CS_AC_LEN\ - + TUD_AUDIO_DESC_CLK_SRC_LEN\ - + TUD_AUDIO_DESC_INPUT_TERM_LEN\ - + TUD_AUDIO_DESC_OUTPUT_TERM_LEN\ - + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_STD_AS_INT_LEN\ - + TUD_AUDIO_DESC_CS_AS_INT_LEN\ - + TUD_AUDIO_DESC_TYPE_I_FORMAT_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ - + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) +#define TUD_AUDIO20_SPEAKER_MONO_FB_DESC_LEN (TUD_AUDIO20_DESC_IAD_LEN\ + + TUD_AUDIO20_DESC_STD_AC_LEN\ + + TUD_AUDIO20_DESC_CS_AC_LEN\ + + TUD_AUDIO20_DESC_CLK_SRC_LEN\ + + TUD_AUDIO20_DESC_INPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_OUTPUT_TERM_LEN\ + + TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1)\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_STD_AS_LEN\ + + TUD_AUDIO20_DESC_CS_AS_INT_LEN\ + + TUD_AUDIO20_DESC_TYPE_I_FORMAT_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_CS_AS_ISO_EP_LEN\ + + TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP_LEN) -#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, _epfbsize) \ +#define TUD_AUDIO20_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, _epfbsize) \ /* Standard Interface Association Descriptor (IAD) */\ - TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ - TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ + TUD_AUDIO20_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx),\ /* Class-Specific AC Interface Header Descriptor(4.7.2) */\ - TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO_DESC_CLK_SRC_LEN+TUD_AUDIO_DESC_INPUT_TERM_LEN+TUD_AUDIO_DESC_OUTPUT_TERM_LEN+TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ + TUD_AUDIO20_DESC_CS_AC(/*_bcdADC*/ 0x0200, /*_category*/ AUDIO20_FUNC_DESKTOP_SPEAKER, /*_totallen*/ TUD_AUDIO20_DESC_CLK_SRC_LEN+TUD_AUDIO20_DESC_INPUT_TERM_LEN+TUD_AUDIO20_DESC_OUTPUT_TERM_LEN+TUD_AUDIO20_DESC_FEATURE_UNIT_LEN(1), /*_ctrl*/ AUDIO20_CS_AS_INTERFACE_CTRL_LATENCY_POS),\ /* Clock Source Descriptor(4.7.2.1) */\ - TUD_AUDIO_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO_CTRL_R << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CLK_SRC(/*_clkid*/ 0x04, /*_attr*/ AUDIO20_CLOCK_SOURCE_ATT_INT_FIX_CLK, /*_ctrl*/ (AUDIO20_CTRL_R << AUDIO20_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ 0x01, /*_stridx*/ 0x00),\ /* Input Terminal Descriptor(4.7.2.4) */\ - TUD_AUDIO_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO_CTRL_R << AUDIO_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_INPUT_TERM(/*_termid*/ 0x01, /*_termtype*/ AUDIO_TERM_TYPE_USB_STREAMING, /*_assocTerm*/ 0x00, /*_clkid*/ 0x04, /*_nchannelslogical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_idxchannelnames*/ 0x00, /*_ctrl*/ 0 * (AUDIO20_CTRL_R << AUDIO20_IN_TERM_CTRL_CONNECTOR_POS), /*_stridx*/ 0x00),\ /* Output Terminal Descriptor(4.7.2.5) */\ - TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_FEATURE_UNIT(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_stridx*/ 0x00, /*_ctrlch0master*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO20_CTRL_RW << AUDIO20_FEATURE_UNIT_CTRL_VOLUME_POS),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 1 - alternate interface for data streaming */\ - TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x01, /*_nEPs*/ 0x02, /*_stridx*/ 0x00),\ /* Class-Specific AS Interface Descriptor(4.9.2) */\ - TUD_AUDIO_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO_CTRL_NONE, /*_formattype*/ AUDIO_FORMAT_TYPE_I, /*_formats*/ AUDIO_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ + TUD_AUDIO20_DESC_CS_AS_INT(/*_termid*/ 0x01, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_formattype*/ AUDIO20_FORMAT_TYPE_I, /*_formats*/ AUDIO20_DATA_FORMAT_TYPE_I_PCM, /*_nchannelsphysical*/ 0x01, /*_channelcfg*/ AUDIO20_CHANNEL_CONFIG_NON_PREDEFINED, /*_stridx*/ 0x00),\ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ - TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ + TUD_AUDIO20_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ + TUD_AUDIO20_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ - TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ + TUD_AUDIO20_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO20_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO20_CTRL_NONE, /*_lockdelayunit*/ AUDIO20_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_epsize*/ _epfbsize, /*_interval*/ 1) + TUD_AUDIO20_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_epsize*/ _epfbsize, /*_interval*/ 1) // Calculate wMaxPacketSize of Endpoints -#define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ - ((((_maxFrequency + (TUD_OPT_HIGH_SPEED ? 7999 : 999)) / (TUD_OPT_HIGH_SPEED ? 8000 : 1000)) + 1) * _nBytesPerSample * _nChannels) +#define TUD_AUDIO_EP_SIZE(_is_highspeed, _maxFrequency, _nBytesPerSample, _nChannels) \ + (((((_maxFrequency) + ((_is_highspeed) ? 7999 : 999)) / ((_is_highspeed) ? 8000 : 1000)) + 1) * (_nBytesPerSample) * (_nChannels)) //--------------------------------------------------------------------+ @@ -678,44 +809,44 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size // Note: Alternate count must be numeric or macro, string index is increased by one for each Alt interface #define TUD_DFU_DESCRIPTOR(_itfnum, _alt_count, _stridx, _attr, _timeout, _xfer_size) \ - TU_XSTRCAT(_TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ + TU_XSTRCAT(TUD_DFU_ALT_,_alt_count)(_itfnum, 0, _stridx), \ /* Function */ \ 9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) -#define _TUD_DFU_ALT(_itfnum, _alt, _stridx) \ +#define TUD_DFU_ALT(_itfnum, _alt, _stridx) \ /* Interface */ \ 9, TUSB_DESC_INTERFACE, _itfnum, _alt, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_DFU, _stridx -#define _TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx) +#define TUD_DFU_ALT_1(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx) -#define _TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_2(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_1(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_3(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_2(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_4(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_3(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_5(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_4(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_6(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_5(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_7(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_6(_itfnum, _alt_count+1, _stridx+1) -#define _TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ - _TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ - _TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) +#define TUD_DFU_ALT_8(_itfnum, _alt_count, _stridx) \ + TUD_DFU_ALT(_itfnum, _alt_count, _stridx), \ + TUD_DFU_ALT_7(_itfnum, _alt_count+1, _stridx+1) //--------------------------------------------------------------------+ // CDC-ECM Descriptor Templates @@ -885,6 +1016,6 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ } #endif -#endif /* _TUSB_USBD_H_ */ +#endif /* TUSB_USBD_H_ */ /** @} */ diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index c9700fd9d..47d58a1f9 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -60,7 +60,7 @@ typedef struct { static usbd_control_xfer_t _ctrl_xfer; CFG_TUD_MEM_SECTION static struct { - TUD_EPBUF_DEF(buf, CFG_TUD_ENDPOINT0_SIZE); + TUD_EPBUF_DEF(buf, CFG_TUD_ENDPOINT0_BUFSIZE); } _ctrl_epbuf; //--------------------------------------------------------------------+ @@ -71,7 +71,7 @@ CFG_TUD_MEM_SECTION static struct { static inline bool status_stage_xact(uint8_t rhport, const tusb_control_request_t* request) { // Opposite to endpoint in Data Phase const uint8_t ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN; - return usbd_edpt_xfer(rhport, ep_addr, NULL, 0); + return usbd_edpt_xfer(rhport, ep_addr, NULL, 0, false); } // Status phase @@ -88,17 +88,17 @@ bool tud_control_status(uint8_t rhport, const tusb_control_request_t* request) { // Each transaction has up to Endpoint0's max packet size. // This function can also transfer an zero-length packet static bool data_stage_xact(uint8_t rhport) { - const uint16_t xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_SIZE); + const uint16_t xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_BUFSIZE); uint8_t ep_addr = EDPT_CTRL_OUT; if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) { ep_addr = EDPT_CTRL_IN; - if (xact_len) { - TU_VERIFY(0 == tu_memcpy_s(_ctrl_epbuf.buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len)); + if (0u != xact_len) { + TU_VERIFY(0 == tu_memcpy_s(_ctrl_epbuf.buf, CFG_TUD_ENDPOINT0_BUFSIZE, _ctrl_xfer.buffer, xact_len)); } } - return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _ctrl_epbuf.buf : NULL, xact_len); + return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _ctrl_epbuf.buf : NULL, xact_len, false); } // Transmit data to/from the control endpoint. @@ -159,7 +159,7 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, // invoke optional dcd hook if available dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); - if (_ctrl_xfer.complete_cb) { + if (NULL != _ctrl_xfer.complete_cb) { // TODO refactor with usbd_driver_print_control_complete_name _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); } @@ -179,13 +179,13 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, // Data Stage is complete when all request's length are transferred or // a short packet is sent including zero-length packet. if ((_ctrl_xfer.request.wLength == _ctrl_xfer.total_xferred) || - (xferred_bytes < CFG_TUD_ENDPOINT0_SIZE)) { + (xferred_bytes < CFG_TUD_ENDPOINT0_BUFSIZE)) { // DATA stage is complete bool is_ok = true; // invoke complete callback if set // callback can still stall control in status phase e.g out data does not make sense - if (_ctrl_xfer.complete_cb) { + if (NULL != _ctrl_xfer.complete_cb) { #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a688cf497..72323ac80 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -84,10 +84,10 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer -bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr); // Submit a usb ISO transfer by use of a FIFO (ring buffer) - all bytes in FIFO get transmitted -bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes); +bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr); // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. @@ -117,20 +117,17 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endp // Check if endpoint is ready (not busy and not stalled) TU_ATTR_ALWAYS_INLINE static inline bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { - return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); + const bool is_busy = usbd_edpt_busy(rhport, ep_addr); + const bool is_stalled = usbd_edpt_stalled(rhport, ep_addr); + return !is_busy && !is_stalled; } // Enable SOF interrupt void usbd_sof_enable(uint8_t rhport, sof_consumer_t consumer, bool en); -/*------------------------------------------------------------------*/ -/* Helper - *------------------------------------------------------------------*/ - bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr); - #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif diff --git a/src/host/hcd.h b/src/host/hcd.h index d3551bf5b..36a7f5da5 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_HCD_H_ -#define _TUSB_HCD_H_ +#ifndef TUSB_HCD_H_ +#define TUSB_HCD_H_ #include "common/tusb_common.h" #include "osal/osal.h" @@ -84,7 +84,7 @@ typedef struct { // FUNC_CALL struct { - void (*func) (void*); + void (*func) (void* param); void* param; }func_call; }; diff --git a/src/host/usbh.c b/src/host/usbh.c index 6bafde368..734024771 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -292,13 +292,17 @@ static uint8_t _app_driver_count = 0; #define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) -static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) { +// virtually joins built-in and application drivers together. +// Application is positioned first to allow overwriting built-in ones. +TU_ATTR_ALWAYS_INLINE static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) { usbh_class_driver_t const *driver = NULL; - - if ( drv_id < _app_driver_count ) { + if (drv_id < _app_driver_count) { driver = &_app_driver[drv_id]; - } else if ( drv_id < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0) { - driver = &usbh_class_drivers[drv_id - _app_driver_count]; + } else { + drv_id -= _app_driver_count; + if (drv_id < BUILTIN_DRIVER_COUNT) { + driver = &usbh_class_drivers[drv_id]; + } } return driver; @@ -318,7 +322,7 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) } TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { - return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); + return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); //-V560 } TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) { @@ -372,7 +376,8 @@ bool tuh_connected(uint8_t daddr) { return _usbh_data.enumerating_daddr == 0; } else { const usbh_device_t* dev = get_device(daddr); - return dev && dev->connected; + TU_VERIFY(dev != NULL); + return dev->connected; } } @@ -439,8 +444,8 @@ bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) { static void clear_device(usbh_device_t* dev) { tu_memclr(dev, sizeof(usbh_device_t)); - memset(dev->itf2drv, TUSB_INDEX_INVALID_8, sizeof(dev->itf2drv)); // invalid mapping - memset(dev->ep2drv , TUSB_INDEX_INVALID_8, sizeof(dev->ep2drv )); // invalid mapping + (void) memset(dev->itf2drv, TUSB_INDEX_INVALID_8, sizeof(dev->itf2drv)); // invalid mapping + (void) memset(dev->ep2drv , TUSB_INDEX_INVALID_8, sizeof(dev->ep2drv )); // invalid mapping } bool tuh_inited(void) { @@ -510,7 +515,7 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Class drivers for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbh_class_driver_t const* driver = get_driver(drv_id); - if (driver) { + if (driver != NULL) { TU_LOG_USBH("%s init\r\n", driver->name); driver->init(); } @@ -657,7 +662,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { // with enabled driver e.g HID endpoint #if CFG_TUH_API_EDPT_XFER tuh_xfer_cb_t const complete_cb = dev->ep_callback[epnum][ep_dir].complete_cb; - if ( complete_cb ) { + if (complete_cb != NULL) { // re-construct xfer info tuh_xfer_t xfer = { .daddr = event.dev_addr, @@ -675,7 +680,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; usbh_class_driver_t const* driver = get_driver(drv_id); - if (driver) { + if (driver != NULL) { TU_LOG_USBH(" %s xfer callback\r\n", driver->name); driver->xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); @@ -690,10 +695,13 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { } case USBH_EVENT_FUNC_CALL: - if (event.func_call.func) event.func_call.func(event.func_call.param); + if (event.func_call.func != NULL) { + event.func_call.func(event.func_call.param); + } break; default: + // unknown event break; } @@ -743,7 +751,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { tu_str_std_request[xfer->setup->bRequest] : "Class Request"); TU_LOG_BUF_USBH(xfer->setup, 8); - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { TU_ASSERT(usbh_setup_send(daddr, (uint8_t const *) &_usbh_epbuf.request)); }else { // blocking if complete callback is not provided @@ -795,7 +803,7 @@ static void _control_xfer_complete(uint8_t daddr, xfer_result_t result) { _control_set_xfer_stage(CONTROL_STAGE_IDLE); - if (xfer_temp.complete_cb) { + if (xfer_temp.complete_cb != NULL) { xfer_temp.complete_cb(&xfer_temp); } } @@ -834,7 +842,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t case XFER_RESULT_SUCCESS: switch(ctrl_info->stage) { case CONTROL_STAGE_SETUP: - if (request->wLength) { + if (request->wLength > 0) { // DATA stage: initial data toggle is always 1 _control_set_xfer_stage(CONTROL_STAGE_DATA); const uint8_t ep_data = tu_edpt_addr(0, request->bmRequestType_bit.direction); @@ -844,7 +852,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t TU_ATTR_FALLTHROUGH; case CONTROL_STAGE_DATA: { - if (request->wLength) { + if (request->wLength > 0) { TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr); TU_LOG_MEM_USBH(ctrl_info->buffer, xferred_bytes, 2); } @@ -1084,7 +1092,7 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info) { usbh_device_t const* dev = get_device(daddr); - if (dev) { + if (dev != NULL) { *bus_info = dev->bus_info; } else { *bus_info = _usbh_data.dev0_bus; @@ -1109,7 +1117,9 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) } break; - default: break; + default: + // nothing to do + break; } queue_event(event, in_isr); @@ -1314,7 +1324,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub do { for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { usbh_device_t* dev = &_usbh_devices[dev_id]; - uint8_t const daddr = dev_id + 1; + uint8_t const daddr = dev_id + 1u; // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub if (dev->bus_info.rhport == rhport && dev->connected && @@ -1336,7 +1346,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub // Close class driver for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbh_class_driver_t const* driver = get_driver(drv_id); - if (driver) { + if (driver != NULL) { driver->close(daddr); } } @@ -1354,7 +1364,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { - if (removing_hubs[h_id]) { + if (0 != removing_hubs[h_id]) { removing_hubs[h_id] = 0; // update hub_addr and hub_port for next loop @@ -1423,16 +1433,13 @@ static bool enum_new_device(hcd_event_t* event) { // wait until device connection is stable TODO non blocking tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); - // clear roothub debouncing delay - if (dev0_bus->hub_addr == 0) { - _usbh_data.attach_debouncing_bm &= (uint8_t) ~TU_BIT(dev0_bus->rhport); - } - if (dev0_bus->hub_addr == 0) { // connected directly to roothub // USB bus not active and frame number is not available yet. // need to depend on tusb_time_millis_api() TODO non blocking + _usbh_data.attach_debouncing_bm &= (uint8_t) ~TU_BIT(dev0_bus->rhport); // clear roothub debouncing delay + if (!hcd_port_connect_status(dev0_bus->rhport)) { TU_LOG_USBH("Device unplugged while debouncing\r\n"); enum_full_complete(); @@ -1503,7 +1510,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { usbh_device_t* dev = get_device(daddr); tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; if (daddr > 0) { - TU_ASSERT(dev,); + TU_ASSERT(dev != NULL,); } uint16_t langid = 0x0409; // default is English @@ -1513,7 +1520,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { hub_port_status_response_t port_status; hub_port_get_status_local(dev0_bus->hub_addr, dev0_bus->hub_port, &port_status); - if (!port_status.status.connection) { + if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub while debouncing\r\n"); enum_full_complete(); return; @@ -1535,7 +1542,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { hub_port_status_response_t port_status; hub_port_get_status_local(dev0_bus->hub_addr, dev0_bus->hub_port, &port_status); - if (port_status.change.reset) { + if (1 == port_status.change.reset) { // Acknowledge Port Reset Change TU_ASSERT(hub_port_clear_reset_change(dev0_bus->hub_addr, dev0_bus->hub_port, process_enumeration, ENUM_HUB_CLEAR_RESET_COMPLETE),); } else { @@ -1550,7 +1557,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { hub_port_status_response_t port_status; hub_port_get_status_local(dev0_bus->hub_addr, dev0_bus->hub_port, &port_status); - if (!port_status.status.connection) { + if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub (not addressed yet)\r\n"); enum_full_complete(); return; @@ -1619,17 +1626,18 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_GET_STRING_LANGUAGE_ID_LEN: { // save the received device descriptor tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl; - dev->bcdUSB = desc_device->bcdUSB; - dev->bDeviceClass = desc_device->bDeviceClass; - dev->bDeviceSubClass = desc_device->bDeviceSubClass; - dev->bDeviceProtocol = desc_device->bDeviceProtocol; - dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0; - dev->idVendor = desc_device->idVendor; - dev->idProduct = desc_device->idProduct; - dev->bcdDevice = desc_device->bcdDevice; - dev->iManufacturer = desc_device->iManufacturer; - dev->iProduct = desc_device->iProduct; - dev->iSerialNumber = desc_device->iSerialNumber; + + dev->bcdUSB = desc_device->bcdUSB; + dev->bDeviceClass = desc_device->bDeviceClass; + dev->bDeviceSubClass = desc_device->bDeviceSubClass; + dev->bDeviceProtocol = desc_device->bDeviceProtocol; + dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0; + dev->idVendor = desc_device->idVendor; + dev->idProduct = desc_device->idProduct; + dev->bcdDevice = desc_device->bcdDevice; + dev->iManufacturer = desc_device->iManufacturer; + dev->iProduct = desc_device->iProduct; + dev->iSerialNumber = desc_device->iSerialNumber; dev->bNumConfigurations = desc_device->bNumConfigurations; tuh_enum_descriptor_device_cb(daddr, desc_device); // callback @@ -1654,9 +1662,8 @@ static void process_enumeration(tuh_xfer_t* xfer) { tuh_descriptor_get_string(daddr, dev->iManufacturer, langid, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_MANUFACTURER); break; - }else { - TU_ATTR_FALLTHROUGH; } + TU_ATTR_FALLTHROUGH; } case ENUM_GET_STRING_MANUFACTURER: { @@ -1666,22 +1673,21 @@ static void process_enumeration(tuh_xfer_t* xfer) { tuh_descriptor_get_string(daddr, dev->iManufacturer, langid, _usbh_epbuf.ctrl, str_len, process_enumeration, ENUM_GET_STRING_PRODUCT_LEN); break; - } else { - TU_ATTR_FALLTHROUGH; } + TU_ATTR_FALLTHROUGH; } - case ENUM_GET_STRING_PRODUCT_LEN: + case ENUM_GET_STRING_PRODUCT_LEN: { if (dev->iProduct != 0) { if (state == ENUM_GET_STRING_PRODUCT_LEN) { langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through } - tuh_descriptor_get_string(daddr, dev->iProduct, langid, _usbh_epbuf.ctrl, 2, - process_enumeration, ENUM_GET_STRING_PRODUCT); + tuh_descriptor_get_string( + daddr, dev->iProduct, langid, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_PRODUCT); break; - } else { - TU_ATTR_FALLTHROUGH; } + TU_ATTR_FALLTHROUGH; + } case ENUM_GET_STRING_PRODUCT: { if (dev->iProduct != 0) { @@ -1690,22 +1696,21 @@ static void process_enumeration(tuh_xfer_t* xfer) { tuh_descriptor_get_string(daddr, dev->iProduct, langid, _usbh_epbuf.ctrl, str_len, process_enumeration, ENUM_GET_STRING_SERIAL_LEN); break; - } else { - TU_ATTR_FALLTHROUGH; } + TU_ATTR_FALLTHROUGH; } - case ENUM_GET_STRING_SERIAL_LEN: + case ENUM_GET_STRING_SERIAL_LEN: { if (dev->iSerialNumber != 0) { if (state == ENUM_GET_STRING_SERIAL_LEN) { langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through } - tuh_descriptor_get_string(daddr, dev->iSerialNumber, langid, _usbh_epbuf.ctrl, 2, - process_enumeration, ENUM_GET_STRING_SERIAL); + tuh_descriptor_get_string( + daddr, dev->iSerialNumber, langid, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_SERIAL); break; - } else { - TU_ATTR_FALLTHROUGH; } + TU_ATTR_FALLTHROUGH; + } case ENUM_GET_STRING_SERIAL: { if (dev->iSerialNumber != 0) { @@ -1714,9 +1719,8 @@ static void process_enumeration(tuh_xfer_t* xfer) { tuh_descriptor_get_string(daddr, dev->iSerialNumber, langid, _usbh_epbuf.ctrl, str_len, process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC); break; - } else { - TU_ATTR_FALLTHROUGH; } + TU_ATTR_FALLTHROUGH; } case ENUM_GET_9BYTE_CONFIG_DESC: { @@ -1748,7 +1752,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_SET_CONFIG: { uint8_t config_idx = (uint8_t) tu_le16toh(xfer->setup->wIndex); if (tuh_enum_descriptor_configuration_cb(daddr, config_idx, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl)) { - TU_ASSERT(tuh_configuration_set(daddr, config_idx+1, process_enumeration, ENUM_CONFIG_DRIVER),); + TU_ASSERT(tuh_configuration_set(daddr, config_idx+1u, process_enumeration, ENUM_CONFIG_DRIVER),); } else { config_idx++; TU_ASSERT(config_idx < dev->bNumConfigurations,); @@ -1794,7 +1798,7 @@ static uint8_t enum_get_new_address(bool is_hub) { } for (uint8_t idx = start; idx < end; idx++) { - if (!_usbh_devices[idx].connected) { + if (0 == _usbh_devices[idx].connected) { return (idx + 1); } } @@ -1904,7 +1908,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { // with usbh_driver_set_config_complete() uint8_t const drv_id = dev->itf2drv[itf_num]; usbh_class_driver_t const * driver = get_driver(drv_id); - if (driver) { + if (driver != NULL) { TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; diff --git a/src/host/usbh.h b/src/host/usbh.h index 8d48bf90d..4b6747848 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBH_H_ -#define _TUSB_USBH_H_ +#ifndef TUSB_USBH_H_ +#define TUSB_USBH_H_ #ifdef __cplusplus extern "C" { @@ -179,7 +179,7 @@ TU_ATTR_ALWAYS_INLINE static inline void tuh_task(void) { // Check if there is pending events need processing by tuh_task() bool tuh_task_event_ready(void); -#ifndef _TUSB_HCD_H_ +#ifndef TUSB_HCD_H_ extern void hcd_int_handler(uint8_t rhport, bool in_isr); #endif diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 9d91e52e8..d722bb7e8 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBH_PVT_H_ -#define _TUSB_USBH_PVT_H_ +#ifndef TUSB_USBH_PVT_H_ +#define TUSB_USBH_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" diff --git a/src/osal/osal.h b/src/osal/osal.h index a33280425..44521620f 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OSAL_H_ -#define _TUSB_OSAL_H_ +#ifndef TUSB_OSAL_H_ +#define TUSB_OSAL_H_ #ifdef __cplusplus extern "C" { @@ -33,7 +33,7 @@ #include "common/tusb_common.h" -typedef void (*osal_task_func_t)( void * ); +typedef void (*osal_task_func_t)(void* param); // Timeout #define OSAL_TIMEOUT_NOTIMEOUT (0) // Return immediately @@ -71,10 +71,9 @@ typedef void (*osal_task_func_t)( void * ); #error OS is not supported yet #endif -//--------------------------------------------------------------------+ -// OSAL Porting API -// Should be implemented as static inline function in osal_port.h header -/* +/*-------------------------------------------------------------------- + OSAL Porting API + Should be implemented as static inline function in osal_port.h header void osal_spin_init(osal_spinlock_t *ctx); void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr); @@ -83,7 +82,7 @@ typedef void (*osal_task_func_t)( void * ); bool osal_semaphore_delete(osal_semaphore_t semd_hdl); bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec); - void osal_semaphore_reset(osal_semaphore_t sem_hdl); // TODO removed + void osal_semaphore_reset(osal_semaphore_t sem_hdl); osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef); bool osal_mutex_delete(osal_mutex_t mutex_hdl) @@ -95,11 +94,11 @@ typedef void (*osal_task_func_t)( void * ); bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec); bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); bool osal_queue_empty(osal_queue_t qhdl); -*/ -//--------------------------------------------------------------------+ +--------------------------------------------------------------------------*/ + #ifdef __cplusplus } #endif -#endif /* _TUSB_OSAL_H_ */ +#endif diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index bde5ec010..9aeda4d01 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -70,15 +70,15 @@ typedef struct { } osal_queue_def_t; #if defined(configQUEUE_REGISTRY_SIZE) && (configQUEUE_REGISTRY_SIZE>0) - #define _OSAL_Q_NAME(_name) .name = #_name + #define OSAL_Q_NAME(_name) .name = #_name #else - #define _OSAL_Q_NAME(_name) + #define OSAL_Q_NAME(_name) #endif // _int_set is not used with an RTOS #define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ static _type _name##_##buf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, _OSAL_Q_NAME(_name) } + osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, OSAL_Q_NAME(_name) } //--------------------------------------------------------------------+ // TASK API @@ -137,7 +137,7 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { if (in_isr) { - if (!TUP_MCU_MULTIPLE_CORE) { + if (TUP_MCU_MULTIPLE_CORE == 0) { (void) ctx; return; // single core MCU does not need to lock in ISR } @@ -149,7 +149,7 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bo TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { if (in_isr) { - if (!TUP_MCU_MULTIPLE_CORE) { + if (TUP_MCU_MULTIPLE_CORE == 0) { (void) ctx; return; // single core MCU does not need to lock in ISR } @@ -166,7 +166,7 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) { #if configSUPPORT_STATIC_ALLOCATION - return xSemaphoreCreateBinaryStatic(semdef); + return xSemaphoreCreateBinaryStatic((StaticSemaphore_t*) semdef); #else (void) semdef; return xSemaphoreCreateBinary(); @@ -174,7 +174,7 @@ TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_ } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) { - vSemaphoreDelete(semd_hdl); + vSemaphoreDelete((SemaphoreHandle_t) semd_hdl); return true; } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 3e397ef35..174136e38 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -34,26 +34,41 @@ extern "C" { //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ +// Note: This implementation is designed for bare-metal single-core systems without RTOS. +// - Supports nested locking within the same execution context +// - NOT suitable for true SMP (Symmetric Multi-Processing) systems +// - NOT thread-safe for multi-threaded environments +// - Primarily manages interrupt enable/disable state for critical sections typedef struct { - void (* interrupt_set)(bool); + void (* interrupt_set)(bool enabled); + uint32_t nested_count; } osal_spinlock_t; // For SMP, spinlock must be locked by hardware, cannot just use interrupt #define OSAL_SPINLOCK_DEF(_name, _int_set) \ - osal_spinlock_t _name = { .interrupt_set = _int_set } + osal_spinlock_t _name = { .interrupt_set = _int_set, .nested_count = 0 } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { (void) ctx; } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - if (!in_isr) { + // Disable interrupts first to make nested_count increment atomic + if (!in_isr && ctx->nested_count == 0) { ctx->interrupt_set(false); } + ctx->nested_count++; } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - if (!in_isr) { + if (ctx->nested_count == 0) { + return; // spin is not locked to begin with + } + + ctx->nested_count--; + + // Only re-enable interrupts when fully unlocked + if (!in_isr && ctx->nested_count == 0) { ctx->interrupt_set(true); } } @@ -141,7 +156,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd #include "common/tusb_fifo.h" typedef struct { - void (* interrupt_set)(bool); + void (* interrupt_set)(bool enabled); tu_fifo_t ff; } osal_queue_def_t; @@ -156,7 +171,7 @@ typedef osal_queue_def_t* osal_queue_t; } TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { - tu_fifo_clear(&qdef->ff); + (void) tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index ace5907d7..f5385071a 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -81,8 +81,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { (void) in_isr; - sem_release(sem_hdl); - return true; + return sem_release(sem_hdl); } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { @@ -139,7 +138,7 @@ typedef osal_queue_def_t* osal_queue_t; TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { critical_section_init(&qdef->critsec); - tu_fifo_clear(&qdef->ff); + (void) tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; } diff --git a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c index 34a8be3b6..89477b9ac 100644 --- a/src/portable/bridgetek/ft9xx/dcd_ft9xx.c +++ b/src/portable/bridgetek/ft9xx/dcd_ft9xx.c @@ -556,7 +556,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) (void)dev_addr; // Respond with status. There is no checking that the address is in range. - dcd_edpt_xfer(rhport, tu_edpt_addr(USBD_EP_0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(USBD_EP_0, TUSB_DIR_IN), NULL, 0, false); // Set the update bit for the address register. dev_addr |= 0x80; @@ -806,9 +806,24 @@ void dcd_edpt_close_all(uint8_t rhport) _ft9xx_reset_edpts(); } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; uint8_t ep_number = tu_edpt_number(ep_addr); uint8_t ep_dir = tu_edpt_dir(ep_addr); @@ -891,8 +906,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; (void)ep_addr; (void)ff; @@ -1200,5 +1216,4 @@ void ft9xx_usbd_pm_ISR(void) } } } - #endif diff --git a/src/portable/chipidea/ci_fs/dcd_ci_fs.c b/src/portable/chipidea/ci_fs/dcd_ci_fs.c index 11ddb683f..312a98299 100644 --- a/src/portable/chipidea/ci_fs/dcd_ci_fs.c +++ b/src/portable/chipidea/ci_fs/dcd_ci_fs.c @@ -131,7 +131,7 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + _dcd.setup_packet, sizeof(_dcd.setup_packet), false); } static void process_stall(uint8_t rhport) @@ -303,7 +303,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -344,24 +344,21 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - - const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - const unsigned xfer = ep_desc->bmAttributes.xfer; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - const unsigned odd = ep->odd; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; +static bool edpt_open(uint8_t rhport, uint8_t ep_addr, uint16_t max_packet_size, tusb_xfer_type_t xfer) { + (void)rhport; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); - ep->max_packet_size = tu_edpt_packet_size(ep_desc); + ep->max_packet_size = max_packet_size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; - val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; CI_REG->EP[epn].CTL |= val; @@ -375,8 +372,27 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } -void dcd_edpt_close_all(uint8_t rhport) -{ +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + return edpt_open(rhport, ep_desc->bEndpointAddress, tu_edpt_packet_size(ep_desc), ep_desc->bmAttributes.xfer); +} + +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + return edpt_open(rhport, ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS); +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + const unsigned epn = tu_edpt_number(ep_desc->bEndpointAddress); + const unsigned dir = tu_edpt_dir(ep_desc->bEndpointAddress); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + + dcd_int_disable(rhport); + ep->max_packet_size = tu_edpt_packet_size(ep_desc); + dcd_int_enable(rhport); + + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) { dcd_int_disable(rhport); for (unsigned i = 1; i < 16; ++i) { @@ -399,28 +415,9 @@ void dcd_edpt_close_all(uint8_t rhport) } } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; - - dcd_int_disable(rhport); - - CI_REG->EP[epn].CTL &= ~msk; - ep->max_packet_size = 0; - ep->length = 0; - ep->remaining = 0; - bd[0].head = 0; - bd[1].head = 0; - - dcd_int_enable(rhport); -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; @@ -564,5 +561,4 @@ void dcd_int_handler(uint8_t rhport) process_tokdne(rhport); } } - #endif diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index 244f5a2d4..c6d405e98 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -65,15 +65,18 @@ bool dcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) { // ENDPTCTRL enum { + ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field +}; + +enum { ENDPTCTRL_STALL = TU_BIT(0), ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), // used for test only ENDPTCTRL_TOGGLE_RESET = TU_BIT(6), - ENDPTCTRL_ENABLE = TU_BIT(7) + ENDPTCTRL_ENABLE = TU_BIT(7), }; -enum { - ENDPTCTRL_TYPE_POS = 2, // Endpoint type is 2-bit field -}; +#define ENDPTCTRL_TYPE(_type) ((_type) << ENDPTCTRL_TYPE_POS) + #define ENDPTCTRL_RESET_MASK (ENDPTCTRL_TYPE(TUSB_XFER_BULK) | (ENDPTCTRL_TYPE(TUSB_XFER_BULK) << 16u)) // USBSTS, USBINTR enum { @@ -170,9 +173,7 @@ static dcd_data_t _dcd_data; // Prototypes and Helper Functions //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE -static inline uint8_t ci_ep_count(ci_hs_regs_t const* dcd_reg) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t ci_ep_count(const ci_hs_regs_t *dcd_reg) { return dcd_reg->DCCPARAMS & DCCPARAMS_DEN_MASK; } @@ -191,9 +192,8 @@ static void bus_reset(uint8_t rhport) // type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior // for the data PID tracking on the active endpoint. uint8_t const ep_count = ci_ep_count(dcd_reg); - for( uint8_t i=1; i < ep_count; i++) - { - dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); + for (uint8_t i = 1; i < ep_count; i++) { + dcd_reg->ENDPTCTRL[i] = ENDPTCTRL_RESET_MASK; } //------------- Clear All Registers -------------// @@ -277,7 +277,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); dcd_reg->DEVICEADDR = (dev_addr << 25) | TU_BIT(24); @@ -315,26 +315,25 @@ void dcd_sof_enable(uint8_t rhport, bool en) // HELPER //--------------------------------------------------------------------+ -static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) -{ - dcd_dcache_clean_invalidate((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes); +static void qtd_init(dcd_qtd_t *p_qtd, void *data_ptr, uint16_t total_bytes) { + dcd_dcache_clean_invalidate((uint32_t *)tu_align((uint32_t)data_ptr, 4), total_bytes); tu_memclr(p_qtd, sizeof(dcd_qtd_t)); - p_qtd->next = QTD_NEXT_INVALID; - p_qtd->active = 1; - p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; - p_qtd->int_on_complete = true; + p_qtd->next = QTD_NEXT_INVALID; + p_qtd->active = 1; + p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes; + p_qtd->int_on_complete = true; - if (data_ptr != NULL) - { - p_qtd->buffer[0] = (uint32_t) data_ptr; + if (data_ptr != NULL) { + p_qtd->buffer[0] = (uint32_t)data_ptr; - uint32_t const bufend = p_qtd->buffer[0] + total_bytes; - for(uint8_t i=1; i<5; i++) - { - uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096; - if ( bufend <= next_page ) break; + const uint32_t bufend = p_qtd->buffer[0] + total_bytes; + for (uint8_t i = 1; i < 5; i++) { + const uint32_t next_page = tu_align4k(p_qtd->buffer[i - 1]) + 4096; + if (bufend <= next_page) { + break; + } p_qtd->buffer[i] = next_page; @@ -346,6 +345,35 @@ static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes) //--------------------------------------------------------------------+ // DCD Endpoint Port //--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_write(volatile uint32_t *epctrl, uint8_t dir, uint32_t value) { + if (dir == TUSB_DIR_OUT) { + *epctrl = (*epctrl & 0xFFFF0000u) | value; + } else { + *epctrl = (*epctrl & 0x0000FFFFu) | (value << 16); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_mask(volatile uint32_t *epctrl, uint8_t dir, uint32_t and_mask, + uint32_t or_mask) { + uint32_t value = *epctrl; + if (and_mask != 0) { + value &= (dir == TUSB_DIR_OUT) ? and_mask : (and_mask << 16u); + } + if (or_mask != 0) { + value |= (dir == TUSB_DIR_OUT) ? or_mask : (or_mask << 16u); + } + + *epctrl = value; +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_set(volatile uint32_t *epctrl, uint8_t dir, uint32_t mask) { + ep_ctrl_mask(epctrl, dir, 0, mask); +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_ctrl_clear(volatile uint32_t *epctrl, uint8_t dir, uint32_t mask) { + ep_ctrl_mask(epctrl, dir, ~mask, 0); +} + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); @@ -366,80 +394,91 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) // data toggle also need to be reset ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_TOGGLE_RESET << ( dir ? 16 : 0 ); - dcd_reg->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << ( dir ? 16 : 0)); + dcd_reg->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << (dir ? 16 : 0)); } -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) -{ - uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - - ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); - - // Must not exceed max endpoint number - TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - - //------------- Prepare Queue Head -------------// - dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir]; +static void qhd_init(dcd_qhd_t *p_qhd, uint16_t max_packet_size, uint8_t iso_mult) { tu_memclr(p_qhd, sizeof(dcd_qhd_t)); - p_qhd->zero_length_termination = 1; - p_qhd->max_packet_size = tu_edpt_packet_size(p_endpoint_desc); - if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) - { - p_qhd->iso_mult = 1; - } - + p_qhd->max_packet_size = max_packet_size; + p_qhd->iso_mult = iso_mult; p_qhd->qtd_overlay.next = QTD_NEXT_INVALID; - dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); +} - // Enable EP Control - uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET; +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *endpoint_desc) { + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + const uint8_t epnum = tu_edpt_number(endpoint_desc->bEndpointAddress); + const uint8_t dir = tu_edpt_dir(endpoint_desc->bEndpointAddress); + const uint8_t xfer_type = endpoint_desc->bmAttributes.xfer; + TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - if ( dir == TUSB_DIR_OUT ) - { - dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl; - }else - { - dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16); - } + dcd_qhd_t *p_qhd = &_dcd_data.qhd[epnum][dir]; + qhd_init(p_qhd, tu_edpt_packet_size(endpoint_desc), 0u); + + // EP Control + const uint32_t epctrl = ENDPTCTRL_TYPE(xfer_type) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET; + ep_ctrl_write(&dcd_reg->ENDPTCTRL[epnum], dir, epctrl); return true; } -void dcd_edpt_close_all (uint8_t rhport) -{ - ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; - // Disable all non-control endpoints - uint8_t const ep_count = ci_ep_count(dcd_reg); - for (uint8_t epnum = 1; epnum < ep_count; epnum++) - { - _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1; - _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1; + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); + TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum+16); - dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS)); - } + // EP Control: set type but not enabled yet + const uint32_t epctrl = ENDPTCTRL_TYPE(TUSB_XFER_ISOCHRONOUS) | ENDPTCTRL_TOGGLE_RESET; + ep_ctrl_write(&dcd_reg->ENDPTCTRL[epnum], dir, epctrl); + + return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + const uint8_t epnum = tu_edpt_number(desc_ep->bEndpointAddress); + const uint8_t dir = tu_edpt_dir(desc_ep->bEndpointAddress); + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + TU_ASSERT(epnum < ci_ep_count(dcd_reg)); - ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport); + dcd_qhd_t *p_qhd = &_dcd_data.qhd[epnum][dir]; + volatile uint32_t *endptctrl = &dcd_reg->ENDPTCTRL[epnum]; - _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1; + // _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1; + // dcd_dcache_clean_invalidate(&_dcd_data, sizeof(dcd_data_t)); // Flush EP - uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0)); - dcd_reg->ENDPTFLUSH = flush_mask; - while(dcd_reg->ENDPTFLUSH & flush_mask); + const uint32_t flush_mask = TU_BIT(epnum + (dir ? 16 : 0)); + dcd_reg->ENDPTFLUSH = flush_mask; + while (dcd_reg->ENDPTFLUSH & flush_mask) {} + + // disable to change max packet size + ep_ctrl_clear(endptctrl, dir, ENDPTCTRL_ENABLE); - // Clear EP enable - dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0)); + qhd_init(p_qhd, tu_edpt_packet_size(desc_ep), 1u); + + ep_ctrl_set(endptctrl, dir, ENDPTCTRL_ENABLE); + + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) { + ci_hs_regs_t *dcd_reg = CI_HS_REG(rhport); + + // Disable all non-control endpoints + uint8_t const ep_count = ci_ep_count(dcd_reg); + for (uint8_t epnum = 1; epnum < ep_count; epnum++) { + _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1; + _dcd_data.qhd[epnum][TUSB_DIR_IN].qtd_overlay.halted = 1; + + dcd_reg->ENDPTFLUSH = TU_BIT(epnum) | TU_BIT(epnum + 16); + dcd_reg->ENDPTCTRL[epnum] = ENDPTCTRL_RESET_MASK; + } } static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir) @@ -465,8 +504,9 @@ static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir) dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0)); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -486,8 +526,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t #if !CFG_TUD_MEM_DCACHE_ENABLE // fifo has to be aligned to 4k boundary // It's incompatible with dcache enabled transfer, since neither address nor size is aligned to cache line -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -678,5 +719,4 @@ void dcd_int_handler(uint8_t rhport) dcd_event_sof(rhport, frame, true); } } - #endif diff --git a/src/portable/dialog/da146xx/dcd_da146xx.c b/src/portable/dialog/da146xx/dcd_da146xx.c index 56ecb7575..a283c8362 100644 --- a/src/portable/dialog/da146xx/dcd_da146xx.c +++ b/src/portable/dialog/da146xx/dcd_da146xx.c @@ -837,7 +837,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) // Set default address for one ZLP USB->USB_EPC0_REG = USB_USB_EPC0_REG_USB_DEF_Msk; USB->USB_FAR_REG = (dev_addr & USB_USB_FAR_REG_USB_AD_Msk) | USB_USB_FAR_REG_USB_AD_EN_Msk; - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -1025,8 +1025,24 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) tu_memclr(xfer, sizeof(*xfer)); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} +#endif + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); @@ -1218,5 +1234,4 @@ void dcd_int_handler(uint8_t rhport) handle_alt_ev(); } } - #endif diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 953483583..c33c970e4 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -919,8 +919,8 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c if (interval < 4) { // sub millisecond interval p_qhd->interval_ms = 0; - p_qhd->int_smask = (interval == 1) ? TU_BIN8(11111111) : - (interval == 2) ? TU_BIN8(10101010): TU_BIN8(01000100); + p_qhd->int_smask = (interval == 1) ? 0xff : // 0b11111111 + (interval == 2) ? 0xaa /* 0b10101010 */ : 0x44 /* 0b01000100 */; } else { p_qhd->interval_ms = (uint8_t) tu_min16(1 << (interval - 4), 255); p_qhd->int_smask = TU_BIT(interval % 8); @@ -929,7 +929,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c TU_ASSERT(0 != interval, ); // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes p_qhd->int_smask = 0x01; - p_qhd->fl_int_cmask = TU_BIN8(11100); + p_qhd->fl_int_cmask = 0x1c; // 0b11100 p_qhd->interval_ms = interval; } break; diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 87659701b..719bdeafc 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_EHCI_H_ -#define _TUSB_EHCI_H_ +#ifndef TUSB_EHCI_H_ +#define TUSB_EHCI_H_ /* Abbreviation @@ -458,4 +458,4 @@ TU_VERIFY_STATIC(sizeof(ehci_cap_registers_t) == 16, "size is not correct"); } #endif -#endif /* _TUSB_EHCI_H_ */ +#endif /* TUSB_EHCI_H_ */ diff --git a/src/portable/ehci/ehci_api.h b/src/portable/ehci/ehci_api.h index 12e0a73d7..79fbe702a 100644 --- a/src/portable/ehci/ehci_api.h +++ b/src/portable/ehci/ehci_api.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_EHCI_API_H_ -#define _TUSB_EHCI_API_H_ +#ifndef TUSB_EHCI_API_H_ +#define TUSB_EHCI_API_H_ #ifdef __cplusplus extern "C" { diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c deleted file mode 100644 index 1b6aae026..000000000 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ /dev/null @@ -1,889 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. 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 "tusb_option.h" - -#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && CFG_TUD_ENABLED) - -// Espressif -#include "xtensa/xtensa_api.h" - -#include "esp_intr_alloc.h" -#include "esp_log.h" -#include "soc/dport_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/usb_periph.h" -#include "soc/usb_reg.h" -#include "soc/usb_struct.h" -#include "soc/periph_defs.h" // for interrupt source - -#include "device/dcd.h" - -#ifndef USB_OUT_EP_NUM -#define USB_OUT_EP_NUM ((int) (sizeof(USB0.out_ep_reg) / sizeof(USB0.out_ep_reg[0]))) -#endif - -#ifndef USB_IN_EP_NUM -#define USB_IN_EP_NUM ((int) (sizeof(USB0.in_ep_reg) / sizeof(USB0.in_ep_reg[0]))) -#endif - -// Max number of bi-directional endpoints including EP0 -// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 -// We should probably prohibit enabling Endpoint IN > 4 (not done yet) -#define EP_MAX USB_OUT_EP_NUM - -// FIFO size in bytes -#define EP_FIFO_SIZE 1024 - -// Max number of IN EP FIFOs -#define EP_FIFO_NUM 5 - -typedef struct { - uint8_t *buffer; - // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API - uint16_t total_len; - uint16_t queued_len; - uint16_t max_size; - bool short_packet; - uint8_t interval; -} xfer_ctl_t; - -static const char *TAG = "TUSB:DCD"; -static intr_handle_t usb_ih; - - -static uint32_t _setup_packet[2]; - -#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] -static xfer_ctl_t xfer_status[EP_MAX][2]; - -// Keep count of how many FIFOs are in use -static uint8_t _allocated_fifos = 1; //FIFO0 is always in use - -// Will either return an unused FIFO number, or 0 if all are used. -static uint8_t get_free_fifo(void) -{ - if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; - return 0; -} - -// Setup the control endpoint 0. -static void bus_reset(void) -{ - for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { - USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // clear device address - USB0.dcfg &= ~USB_DEVADDR_M; - - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK; - USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; - - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): - // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN - // - // - All EP OUT shared a unique OUT FIFO which uses - // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). - // * 2 locations for OUT endpoint control words. - // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) - // * 1 location for global NAK (not required/used here). - // * It is recommended to allocate 2 times the largest packet size, therefore - // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 - USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, - USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo - USB0.grxfsiz = 52; - - // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) - USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); - - // Ready to receive SETUP packet - USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; - - USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; -} - -static void enum_done_processing(void) -{ - ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); - // On current silicon on the Full Speed core, speed is fixed to Full Speed. - // However, keep for debugging and in case Low Speed is ever supported. - uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); - - // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL - if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) - USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - } else { - USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes - USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall - xfer_status[0][TUSB_DIR_OUT].max_size = 8; - xfer_status[0][TUSB_DIR_IN].max_size = 8; - } -} - - -/*------------------------------------------------------------------*/ -/* Controller API - *------------------------------------------------------------------*/ -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; - ESP_LOGV(TAG, "DCD init - Start"); - - // A. Disconnect - ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); - USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect - - // B. Programming DCFG - /* If USB host misbehaves during status portion of control xfer - (non zero-length packet), send STALL back and discard. Full speed. */ - USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL - (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) - - USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON - USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode - USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides - - // C. Setting SNAKs, then connect - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK - } - - // D. Interruption masking - USB0.gintmsk = 0; //mask all - USB0.gotgint = ~0U; //clear OTG ints - USB0.gintsts = ~0U; //clear pending ints - USB0.gintmsk = USB_OTGINTMSK_M | - USB_MODEMISMSK_M | - USB_RXFLVIMSK_M | - USB_ERLYSUSPMSK_M | - USB_USBSUSPMSK_M | - USB_USBRSTMSK_M | - USB_ENUMDONEMSK_M | - USB_RESETDETMSK_M | - USB_WKUPINT_M | - USB_DISCONNINTMSK_M; // host most only - - dcd_connect(rhport); - return true; -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; - ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); - USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); - // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -void dcd_remote_wakeup(uint8_t rhport) -{ - (void)rhport; - - // set remote wakeup - USB0.dctl |= USB_RMTWKUPSIG_M; - - // enable SOF to detect bus resume - USB0.gintsts = USB_SOF_M; - USB0.gintmsk |= USB_SOFMSK_M; - - // Per specs: remote wakeup signal bit must be clear within 1-15ms - vTaskDelay(pdMS_TO_TICKS(1)); - - USB0.dctl &= ~USB_RMTWKUPSIG_M; -} - -// connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl &= ~USB_SFTDISCON_M; -} - -// disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - USB0.dctl |= USB_SFTDISCON_M; -} - -void dcd_sof_enable(uint8_t rhport, bool en) -{ - (void) rhport; - (void) en; - - // TODO implement later -} - -/*------------------------------------------------------------------*/ -/* DCD Endpoint port - *------------------------------------------------------------------*/ - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) -{ - ESP_LOGV(TAG, "DCD endpoint opened"); - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); - - TU_ASSERT(epnum < EP_MAX); - - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = tu_edpt_packet_size(desc_edpt); - xfer->interval = desc_edpt->bInterval; - - if (dir == TUSB_DIR_OUT) { - out_ep[epnum].doepctl |= USB_USBACTEP1_M | - desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) | - xfer->max_size << USB_MPS1_S; - USB0.daintmsk |= (1 << (16 + epnum)); - } else { - // "USB Data FIFOs" section in reference manual - // Peripheral FIFO architecture - // - // --------------- 320 or 1024 ( 1280 or 4096 bytes ) - // | IN FIFO MAX | - // --------------- - // | ... | - // --------------- y + x + 16 + GRXFSIZ - // | IN FIFO 2 | - // --------------- x + 16 + GRXFSIZ - // | IN FIFO 1 | - // --------------- 16 + GRXFSIZ - // | IN FIFO 0 | - // --------------- GRXFSIZ - // | OUT FIFO | - // | ( Shared ) | - // --------------- 0 - // - // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints - // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) - // - Offset: GRXFSIZ + 16 + Size*(epnum-1) - // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". - - uint8_t fifo_num = get_free_fifo(); - TU_ASSERT(fifo_num != 0); - - in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); - in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | - fifo_num << USB_D_TXFNUM1_S | - desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | - (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | - xfer->max_size << 0; - - USB0.daintmsk |= (1 << (0 + epnum)); - - // Both TXFD and TXSA are in unit of 32-bit words. - // IN FIFO 0 was configured during enumeration, hence the "+ 16". - uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; - uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); - uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); - - // DIEPTXF starts at FIFO #1. - USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; - } - return true; -} - -void dcd_edpt_close_all(uint8_t rhport) -{ - (void) rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - // Disable non-control interrupt - USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; - - for(uint8_t n = 1; n < EP_MAX; n++) - { - // disable OUT endpoint - out_ep[n].doepctl = 0; - xfer_status[n][TUSB_DIR_OUT].max_size = 0; - - // disable IN endpoint - in_ep[n].diepctl = 0; - xfer_status[n][TUSB_DIR_IN].max_size = 0; - } - - _allocated_fifos = 1; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) -{ - (void)rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); - xfer->buffer = buffer; - // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API - xfer->total_len = total_bytes; - xfer->queued_len = 0; - xfer->short_packet = false; - - uint16_t num_packets = (total_bytes / xfer->max_size); - uint8_t short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - - ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", - epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), - num_packets, total_bytes); - - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them - // here. - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; - USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK - - // For ISO endpoint with interval=1 set correct DATA0/DATA1 bit for next frame - if ((USB0.in_ep_reg[epnum].diepctl & USB_D_EPTYPE0_M) == (1 << USB_D_EPTYPE1_S) && xfer->interval == 1) { - // Take odd/even bit from frame counter. - uint32_t const odd_frame_now = (USB0.dsts & (1u << USB_SOFFN_S)); - USB0.in_ep_reg[epnum].diepctl |= (odd_frame_now ? USB_DI_SETD0PID1 : USB_DI_SETD1PID1); - } - - // Enable fifo empty interrupt only if there are something to put in the fifo. - if(total_bytes != 0) { - USB0.dtknqr4_fifoemptymsk |= (1 << epnum); - } - } else { - // Each complete packet for OUT xfers triggers XFRC. - USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - - // For ISO endpoint with interval=1 set correct DATA0/DATA1 bit for next frame - if ((USB0.out_ep_reg[epnum].doepctl & USB_D_EPTYPE0_M) == (1 << USB_D_EPTYPE1_S) && xfer->interval == 1) { - // Take odd/even bit from frame counter. - uint32_t const odd_frame_now = (USB0.dsts & (1u << USB_SOFFN_S)); - USB0.out_ep_reg[epnum].doepctl |= (odd_frame_now ? USB_DO_SETD0PID1 : USB_DO_SETD1PID1); - } - } - return true; -} - -#if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) -{ - (void)rhport; -} -#endif - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); - } else { - // Stop transmitting packets and NAK IN xfers. - in_ep[epnum].diepctl |= USB_DI_SNAK1_M; - while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; - - // Disable the endpoint. Note that both SNAK and STALL are set here. - in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); - while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; - in_ep[epnum].diepint = USB_D_EPDISBLD0_M; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); - USB0.grstctl |= (fifo_num << USB_TXFNUM_S); - USB0.grstctl |= USB_TXFFLSH_M; - while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; - } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { - out_ep[epnum].doepctl |= USB_STALL0_M; - } else { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - USB0.dctl |= USB_SGOUTNAK_M; - while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; - - // Ditto here- disable the endpoint. Note that only STALL and not SNAK - // is set here. - out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); - while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; - out_ep[epnum].doepint = USB_EPDISBLD0_M; - - // Allow other OUT endpoints to keep receiving. - USB0.dctl |= USB_CGOUTNAK_M; - } - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); - usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - in_ep[epnum].diepctl &= ~USB_D_STALL1_M; - - uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; - } - } else { - out_ep[epnum].doepctl &= ~USB_STALL1_M; - - uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; - // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt - // and bulk endpoints. - if (eptype == 2 || eptype == 3) { - out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; - } - } -} - -/*------------------------------------------------------------------*/ - -static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) -{ - ESP_EARLY_LOGV(TAG, "USB - receive_packet"); - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // See above TODO - // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; - // xfer->queued_len = xfer->total_len - remaining; - - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t to_recv_size; - - if (remaining <= xfer->max_size) { - // Avoid buffer overflow. - to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; - } else { - // Room for full packet, choose recv_size based on what the microcontroller - // claims. - to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; - } - - // Common buffer read -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); - } - else -#endif - { - uint8_t to_recv_rem = to_recv_size % 4; - uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; - - // Do not assume xfer buffer is aligned. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to collect. - if (to_recv_size >= 4) { - for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { - uint32_t tmp = (*rx_fifo); - base[i] = tmp & 0x000000FF; - base[i + 1] = (tmp & 0x0000FF00) >> 8; - base[i + 2] = (tmp & 0x00FF0000) >> 16; - base[i + 3] = (tmp & 0xFF000000) >> 24; - } - } - - // Do not read invalid bytes from RX FIFO. - if (to_recv_rem != 0) { - uint32_t tmp = (*rx_fifo); - uint8_t *last_32b_bound = base + to_recv_size_aligned; - - last_32b_bound[0] = tmp & 0x000000FF; - if (to_recv_rem > 1) { - last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; - } - if (to_recv_rem > 2) { - last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; - } - } - } - - xfer->queued_len += xfer_size; - - // Per USB spec, a short OUT packet (including length 0) is always - // indicative of the end of a transfer (at least for ctl, bulk, int). - xfer->short_packet = (xfer_size < xfer->max_size); -} - -static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) -{ - ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); - volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; - - uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; - xfer->queued_len = xfer->total_len - remaining; - - uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; - -#if 0 // TODO support dcd_edpt_xfer_fifo API - if (xfer->ff) - { - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); - } - else -#endif - { - uint8_t to_xfer_rem = to_xfer_size % 4; - uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; - - // Buffer might not be aligned to 32b, so we need to force alignment - // by copying to a temp var. - uint8_t *base = (xfer->buffer + xfer->queued_len); - - // This for loop always runs at least once- skip if less than 4 bytes - // to send off. - if (to_xfer_size >= 4) { - for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { - uint32_t tmp = base[i] | (base[i + 1] << 8) | - (base[i + 2] << 16) | (base[i + 3] << 24); - (*tx_fifo) = tmp; - } - } - - // Do not read beyond end of buffer if not divisible by 4. - if (to_xfer_rem != 0) { - uint32_t tmp = 0; - uint8_t *last_32b_bound = base + to_xfer_size_aligned; - - tmp |= last_32b_bound[0]; - if (to_xfer_rem > 1) { - tmp |= (last_32b_bound[1] << 8); - } - if (to_xfer_rem > 2) { - tmp |= (last_32b_bound[2] << 16); - } - - (*tx_fifo) = tmp; - } - } -} - -static void read_rx_fifo(void) -{ - // Pop control word off FIFO (completed xfers will have 2 control words, - // we only pop one ctl word each interrupt). - uint32_t const ctl_word = USB0.grxstsp; - uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; - uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; - uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; - - switch (pktsts) { - case 0x01: // Global OUT NAK (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); - break; - - case 0x02: { // Out packet recvd - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); - xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - receive_packet(xfer, bcnt); - } - break; - - case 0x03: // Out packet done (Interrupt) - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); - break; - - case 0x04: // Step 2: Setup transaction completed (Interrupt) - // After this event, OEPINT interrupt will occur with SETUP bit set - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); - USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; - break; - - case 0x06: { // Step1: Setup data packet received - volatile uint32_t *rx_fifo = USB0.fifo[0]; - - // We can receive up to three setup packets in succession, but - // only the last one is valid. Therefore we just overwrite it - _setup_packet[0] = (*rx_fifo); - _setup_packet[1] = (*rx_fifo); - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); - } - break; - - default: // Invalid, do something here, like breakpoint? - TU_BREAKPOINT(); - break; - } -} - -static void handle_epout_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DOEPINTx is cleared. - // DOEPINT will be cleared when DAINT's out bits are cleared. - for (int n = 0; n < USB_OUT_EP_NUM; n++) { - xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); - - if (USB0.daint & (1 << (16 + n))) { - // SETUP packet Setup Phase done. - if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { - USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear - dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); - } - - // OUT XFER complete (single packet).q - if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { - - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); - USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; - - // Transfer complete if short packet or total len is transferred - if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { - xfer->short_packet = false; - dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Schedule another packet to be received. - USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); - USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; - } - } - } - } -} - -static void handle_epin_ints(void) -{ - // GINTSTS will be cleared with DAINT == 0 - // DAINT for a given EP clears when DIEPINTx is cleared. - // IEPINT will be cleared when DAINT's out bits are cleared. - for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { - xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; - - if (USB0.daint & (1 << (0 + n))) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); - // IN XFER complete (entire xfer). - if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); - USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; - dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - - // XFER FIFO empty - if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { - ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); - USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; - transmit_packet(xfer, &USB0.in_ep_reg[n], n); - - // Turn off TXFE if all bytes are written. - if (xfer->queued_len == xfer->total_len) - { - USB0.dtknqr4_fifoemptymsk &= ~(1 << n); - } - } - - // XFER Timeout - if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { - // Clear interrupt or endpoint will hang. - USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; - // Maybe retry? - } - } - } -} - - -static void _dcd_int_handler(void* arg) -{ - (void) arg; - uint8_t const rhport = 0; - - const uint32_t int_msk = USB0.gintmsk; - const uint32_t int_status = USB0.gintsts & int_msk; - - if (int_status & USB_USBRST_M) { - // start of reset - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); - USB0.gintsts = USB_USBRST_M; - // FIFOs will be reassigned when the endpoints are reopen - _allocated_fifos = 1; - bus_reset(); - } - - if (int_status & USB_RESETDET_M) { - ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); - USB0.gintsts = USB_RESETDET_M; - bus_reset(); - } - - if (int_status & USB_ENUMDONE_M) { - // ENUMDNE detects speed of the link. For full-speed, we - // always expect the same value. This interrupt is considered - // the end of reset. - USB0.gintsts = USB_ENUMDONE_M; - enum_done_processing(); - dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); - } - - if(int_status & USB_USBSUSP_M) - { - USB0.gintsts = USB_USBSUSP_M; - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - } - - if(int_status & USB_WKUPINT_M) - { - USB0.gintsts = USB_WKUPINT_M; - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - } - - if (int_status & USB_OTGINT_M) - { - // OTG INT bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); - - uint32_t const otg_int = USB0.gotgint; - - if (otg_int & USB_SESENDDET_M) - { - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); - } - - USB0.gotgint = otg_int; - } - - if (int_status & USB_SOF_M) { - USB0.gintsts = USB_SOF_M; - - // Disable SOF interrupt since currently only used for remote wakeup detection - USB0.gintmsk &= ~USB_SOFMSK_M; - - dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); - } - - - if (int_status & USB_RXFLVI_M) { - // RXFLVL bit is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); - - // Mask out RXFLVL while reading data from FIFO - USB0.gintmsk &= ~USB_RXFLVIMSK_M; - read_rx_fifo(); - USB0.gintmsk |= USB_RXFLVIMSK_M; - } - - // OUT endpoint interrupt handling. - if (int_status & USB_OEPINT_M) { - // OEPINT is read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); - handle_epout_ints(); - } - - // IN endpoint interrupt handling. - if (int_status & USB_IEPINT_M) { - // IEPINT bit read-only - ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); - handle_epin_ints(); - } - - // Without handling - USB0.gintsts |= USB_CURMOD_INT_M | - USB_MODEMIS_M | - USB_OTGINT_M | - USB_NPTXFEMP_M | - USB_GINNAKEFF_M | - USB_GOUTNAKEFF | - USB_ERLYSUSP_M | - USB_USBSUSP_M | - USB_ISOOUTDROP_M | - USB_EOPF_M | - USB_EPMIS_M | - USB_INCOMPISOIN_M | - USB_INCOMPIP_M | - USB_FETSUSP_M | - USB_PTXFEMP_M; -} - -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); -} - -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - esp_intr_free(usb_ih); -} - -#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3 diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index 4fce08dd9..1e4ec0015 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -772,8 +772,9 @@ void dcd_edpt_close_all(uint8_t rhport) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); @@ -794,8 +795,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack // - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); diff --git a/src/portable/mentor/musb/musb_max32.h b/src/portable/mentor/musb/musb_max32.h index 35849b5f8..599de2ca1 100644 --- a/src/portable/mentor/musb/musb_max32.h +++ b/src/portable/mentor/musb/musb_max32.h @@ -31,7 +31,17 @@ extern "C" { #endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "mxc_device.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "usbhs_regs.h" #define MUSB_CFG_SHARED_FIFO 1 // shared FIFO for TX and RX endpoints diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index b4a698199..fedede8ab 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -545,7 +545,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -687,8 +687,24 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) if (ie) intr_enable(rhport); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} +#endif + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); @@ -866,5 +882,4 @@ void dcd_int_handler(uint8_t rhport) intr_clear(rhport); } - #endif diff --git a/src/portable/microchip/pic32mz/dcd_pic32mz.c b/src/portable/microchip/pic32mz/dcd_pic32mz.c index cbd157d6b..94ecf1455 100644 --- a/src/portable/microchip/pic32mz/dcd_pic32mz.c +++ b/src/portable/microchip/pic32mz/dcd_pic32mz.c @@ -438,14 +438,23 @@ void dcd_edpt_close_all (uint8_t rhport) } } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; (void) ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); @@ -744,5 +753,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/microchip/samd/dcd_samd.c b/src/portable/microchip/samd/dcd_samd.c index 357aa1549..cdfb00e3c 100644 --- a/src/portable/microchip/samd/dcd_samd.c +++ b/src/portable/microchip/samd/dcd_samd.c @@ -26,10 +26,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21) +#if CFG_TUD_ENABLED && TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X, OPT_MCU_SAMD51, OPT_MCU_SAME5X) #include "sam.h" #include "device/dcd.h" @@ -106,10 +103,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } -#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X - -void dcd_int_enable(uint8_t rhport) -{ +#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) +void dcd_int_enable(uint8_t rhport) { (void) rhport; NVIC_EnableIRQ(USB_0_IRQn); NVIC_EnableIRQ(USB_1_IRQn); @@ -117,8 +112,7 @@ void dcd_int_enable(uint8_t rhport) NVIC_EnableIRQ(USB_3_IRQn); } -void dcd_int_disable(uint8_t rhport) -{ +void dcd_int_disable(uint8_t rhport) { (void) rhport; NVIC_DisableIRQ(USB_3_IRQn); NVIC_DisableIRQ(USB_2_IRQn); @@ -126,17 +120,13 @@ void dcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_0_IRQn); } -#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 - -void dcd_int_enable(uint8_t rhport) -{ +#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X) +void dcd_int_enable(uint8_t rhport) { (void) rhport; NVIC_EnableIRQ(USB_IRQn); } -void dcd_int_disable(uint8_t rhport) -{ +void dcd_int_disable(uint8_t rhport) { (void) rhport; NVIC_DisableIRQ(USB_IRQn); } @@ -152,7 +142,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; // Response with zlp status - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() @@ -255,11 +245,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) { +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; (void) ep_addr; + (void)largest_packet_size; + return false; +} - // TODO: implement if necessary? +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -268,8 +264,9 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -437,5 +434,4 @@ void dcd_int_handler (uint8_t rhport) // Handle complete transfer maybe_transfer_complete(); } - #endif diff --git a/src/portable/microchip/samd/hcd_samd.c b/src/portable/microchip/samd/hcd_samd.c index 1f4b2b233..0de7ddeb6 100644 --- a/src/portable/microchip/samd/hcd_samd.c +++ b/src/portable/microchip/samd/hcd_samd.c @@ -26,11 +26,8 @@ #include "tusb_option.h" -#if CFG_TUH_ENABLED && \ - !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) && \ - (CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21) +#if CFG_TUH_ENABLED && !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) && \ + TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X, OPT_MCU_SAMD51, OPT_MCU_SAME5X) #include "host/hcd.h" #include "sam.h" @@ -428,7 +425,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } -#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X +#if TU_CHECK_MCU(OPT_MCU_SAMD51, OPT_MCU_SAME5X) // Enable USB interrupt void hcd_int_enable(uint8_t rhport) @@ -450,8 +447,7 @@ void hcd_int_disable(uint8_t rhport) NVIC_DisableIRQ(USB_0_IRQn); } -#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 +#elif TU_CHECK_MCU(OPT_MCU_SAMD11, OPT_MCU_SAMD21, OPT_MCU_SAML2X) // Enable USB interrupt void hcd_int_enable(uint8_t rhport) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index a5c768839..149eee794 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -175,7 +175,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) (void) dev_addr; // Response with zlp status - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // DCD can only set address after status for this request is complete. // do it at dcd_edpt0_status_complete() @@ -270,9 +270,17 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -282,8 +290,9 @@ void dcd_edpt_close_all (uint8_t rhport) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -309,8 +318,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; return true; } @@ -494,5 +504,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index 8aec1568d..4d54f9057 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -132,7 +132,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() // Response with zlp status - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } // Wake up host @@ -559,15 +559,17 @@ void dcd_edpt_close_all (uint8_t rhport) // TODO implement dcd_edpt_close_all() } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); + (void) ep_addr; + (void) largest_packet_size; + return false; +} - // Disable endpoint interrupt - USB_REG->DEVIDR = 1 << (DEVIDR_PEP_0_Pos + epnum); - // Disable EP - USB_REG->DEVEPT &=~(1 << (DEVEPT_EPEN0_Pos + epnum)); +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; } static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) @@ -605,8 +607,9 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -666,8 +669,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -773,5 +777,4 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; USB_REG->DEVEPTIER[epnum] = HSTPIPIER_RSTDTS; } - #endif diff --git a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c index 1ce3da27e..6f88e0a24 100644 --- a/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c +++ b/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MM32F327X ) +#if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_MM32F327X) #include "reg_usb_otg_fs.h" #include "mm32_device.h" @@ -43,56 +43,53 @@ enum { TOK_PID_SETUP = 0xDu, }; -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { union { uint32_t head; struct { union { struct { - uint16_t : 2; - uint16_t tok_pid : 4; - uint16_t data : 1; - uint16_t own : 1; - uint16_t : 8; + uint16_t : 2; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + uint16_t : 8; }; struct { - uint16_t : 2; - uint16_t bdt_stall: 1; - uint16_t dts : 1; - uint16_t ninc : 1; - uint16_t keep : 1; - uint16_t : 10; + uint16_t : 2; + uint16_t bdt_stall : 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + uint16_t : 10; }; }; - uint16_t bc : 10; - uint16_t : 6; + uint16_t bc : 10; + uint16_t : 6; }; }; uint8_t *addr; -}buffer_descriptor_t; +} buffer_descriptor_t; -TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(buffer_descriptor_t) == 8, "size is not correct"); -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { union { uint32_t state; struct { - uint32_t max_packet_size :11; + uint32_t max_packet_size : 11; uint32_t : 5; uint32_t odd : 1; - uint32_t :15; + uint32_t : 15; }; }; uint16_t length; uint16_t remaining; -}endpoint_state_t; +} endpoint_state_t; -TU_VERIFY_STATIC( sizeof(endpoint_state_t) == 8, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(endpoint_state_t) == 8, "size is not correct"); -typedef struct -{ +typedef struct { union { /* [#EP][OUT,IN][EVEN,ODD] */ buffer_descriptor_t bdt[16][2][2]; @@ -104,7 +101,7 @@ typedef struct }; uint8_t setup_packet[8]; uint8_t addr; -}dcd_data_t; +} dcd_data_t; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -112,10 +109,9 @@ typedef struct // BDT(Buffer Descriptor Table) must be 256-byte aligned CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(512) static dcd_data_t _dcd; -TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); +TU_VERIFY_STATIC(sizeof(_dcd.bdt) == 512, "size is not correct"); -static void prepare_next_setup_packet(uint8_t rhport) -{ +static void prepare_next_setup_packet(uint8_t rhport) { const unsigned out_odd = _dcd.endpoint[0][0].odd; const unsigned in_odd = _dcd.endpoint[0][1].odd; if (_dcd.bdt[0][0][out_odd].own) { @@ -126,12 +122,10 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][0][out_odd ^ 1].data = 1; _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), _dcd.setup_packet, sizeof(_dcd.setup_packet), false); } -static void process_stall(uint8_t rhport) -{ +static void process_stall(uint8_t rhport) { if (USB_OTG_FS->EP_CTL[0] & USB_ENDPT_EPSTALL_MASK) { /* clear stall condition of the control pipe */ prepare_next_setup_packet(rhport); @@ -139,13 +133,12 @@ static void process_stall(uint8_t rhport) } } -static void process_tokdne(uint8_t rhport) -{ - const unsigned s = USB_OTG_FS->STAT; - USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ - buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; - endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; - unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; +static void process_tokdne(uint8_t rhport) { + const unsigned s = USB_OTG_FS->STAT; + USB_OTG_FS->INT_STAT = USB_ISTAT_TOKDNE_MASK; /* fetch the next token if received */ + buffer_descriptor_t *bd = (buffer_descriptor_t *)&_dcd.bda[s]; + endpoint_state_t *ep = &_dcd.endpoint_unified[s >> 3]; + unsigned odd = (s & USB_STAT_ODD_MASK) ? 1 : 0; /* fetch pid before discarded by the next steps */ const unsigned pid = bd->tok_pid; @@ -155,7 +148,7 @@ static void process_tokdne(uint8_t rhport) bd->ninc = 0; bd->keep = 0; /* update the odd variable to prepare for the next transfer */ - ep->odd = odd ^ 1; + ep->odd = odd ^ 1; if (pid == TOK_PID_SETUP) { dcd_event_setup_received(rhport, bd->addr, true); USB_OTG_FS->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; @@ -165,25 +158,24 @@ static void process_tokdne(uint8_t rhport) TU_LOG1("TKDNE %x\r\n", s); } - const unsigned bc = bd->bc; + const unsigned bc = bd->bc; const unsigned remaining = ep->remaining - bc; if (remaining && bc == ep->max_packet_size) { /* continue the transferring consecutive data */ - ep->remaining = remaining; + ep->remaining = remaining; const int next_remaining = remaining - ep->max_packet_size; if (next_remaining > 0) { /* prepare to the after next transfer */ bd->addr += ep->max_packet_size * 2; - bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size: next_remaining; + bd->bc = next_remaining > ep->max_packet_size ? ep->max_packet_size : next_remaining; __DSB(); - bd->own = 1; /* the own bit must set after addr */ + bd->own = 1; /* the own bit must set after addr */ } return; } const unsigned length = ep->length; - dcd_event_xfer_complete(rhport, - ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), - length - remaining, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, ((s & USB_STAT_TX_MASK) << 4) | (s >> USB_STAT_ENDP_SHIFT), length - remaining, + XFER_RESULT_SUCCESS, true); if (0 == (s & USB_STAT_ENDP_MASK) && 0 == length) { /* After completion a ZLP of control transfer, * it prepares for the next steup transfer. */ @@ -191,24 +183,23 @@ static void process_tokdne(uint8_t rhport) /* When the transfer was the SetAddress, * the device address should be updated here. */ USB_OTG_FS->ADDR = _dcd.addr; - _dcd.addr = 0; + _dcd.addr = 0; } prepare_next_setup_packet(rhport); } } -static void process_bus_reset(uint8_t rhport) -{ - USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; - USB_OTG_FS->ADDR = 0; - USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; +static void process_bus_reset(uint8_t rhport) { + USB_OTG_FS->CTL |= USB_CTL_ODDRST_MASK; + USB_OTG_FS->ADDR = 0; + USB_OTG_FS->INT_ENB = (USB_OTG_FS->INT_ENB & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; USB_OTG_FS->EP_CTL[0] = USB_ENDPT_EPHSHK_MASK | USB_ENDPT_EPRXEN_MASK | USB_ENDPT_EPTXEN_MASK; for (unsigned i = 1; i < 16; ++i) { USB_OTG_FS->EP_CTL[i] = 0; } buffer_descriptor_t *bd = _dcd.bdt[0][0]; - for (unsigned i = 0; i < sizeof(_dcd.bdt)/sizeof(*bd); ++i, ++bd) { + for (unsigned i = 0; i < sizeof(_dcd.bdt) / sizeof(*bd); ++i, ++bd) { bd->head = 0; } const endpoint_state_t ep0 = { @@ -226,31 +217,29 @@ static void process_bus_reset(uint8_t rhport) dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } -static void process_bus_inactive(uint8_t rhport) -{ - (void) rhport; +static void process_bus_inactive(uint8_t rhport) { + (void)rhport; const unsigned inten = USB_OTG_FS->INT_ENB; - USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_SLEEPEN_MASK) | USB_INTEN_RESUMEEN_MASK; dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); } -static void process_bus_active(uint8_t rhport) -{ - (void) rhport; +static void process_bus_active(uint8_t rhport) { + (void)rhport; const unsigned inten = USB_OTG_FS->INT_ENB; - USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; + USB_OTG_FS->INT_ENB = (inten & ~USB_INTEN_RESUMEEN_MASK) | USB_INTEN_SLEEPEN_MASK; dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } /*------------------------------------------------------------------*/ /* Device API *------------------------------------------------------------------*/ -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rhport; - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rhport; + (void)rh_init; tu_memclr(&_dcd, sizeof(_dcd)); - USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); + USB_OTG_FS->BDT_PAGE_01 = (uint8_t)((uintptr_t)_dcd.bdt >> 8); USB_OTG_FS->BDT_PAGE_02 = (uint8_t)((uintptr_t)_dcd.bdt >> 16); USB_OTG_FS->BDT_PAGE_03 = (uint8_t)((uintptr_t)_dcd.bdt >> 24); @@ -259,30 +248,27 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } #define USB_DEVICE_INTERRUPT_PRIORITY (3U) -void dcd_int_enable(uint8_t rhport) -{ +void dcd_int_enable(uint8_t rhport) { uint8_t irqNumber; irqNumber = USB_FS_IRQn; - (void) rhport; - USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | - USB_INTEN_SLEEPEN_MASK | USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; + (void)rhport; + USB_OTG_FS->INT_ENB = USB_INTEN_USBRSTEN_MASK | USB_INTEN_TOKDNEEN_MASK | USB_INTEN_SLEEPEN_MASK | + USB_INTEN_ERROREN_MASK | USB_INTEN_STALLEN_MASK; NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY); NVIC_EnableIRQ(USB_FS_IRQn); } -void dcd_int_disable(uint8_t rhport) -{ - (void) rhport; +void dcd_int_disable(uint8_t rhport) { + (void)rhport; NVIC_DisableIRQ(USB_FS_IRQn); USB_OTG_FS->INT_ENB = 0; } -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void) rhport; +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void)rhport; _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } #ifdef __GNUC__ // caused by extra declaration of SystemCoreClock in freeRTOSConfig.h @@ -296,31 +282,29 @@ extern u32 SystemCoreClock; #pragma GCC diagnostic pop #endif -void dcd_remote_wakeup(uint8_t rhport) -{ - (void) rhport; +void dcd_remote_wakeup(uint8_t rhport) { + (void)rhport; unsigned cnt = SystemCoreClock / 100; USB_OTG_FS->CTL |= USB_CTL_RESUME_MASK; - while (cnt--) __NOP(); + while (cnt--) { + __NOP(); + } USB_OTG_FS->CTL &= ~USB_CTL_RESUME_MASK; } -void dcd_connect(uint8_t rhport) -{ - (void) rhport; - USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; +void dcd_connect(uint8_t rhport) { + (void)rhport; + USB_OTG_FS->CTL |= USB_CTL_USBENSOFEN_MASK; } -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; - USB_OTG_FS->CTL = 0; +void dcd_disconnect(uint8_t rhport) { + (void)rhport; + USB_OTG_FS->CTL = 0; } -void dcd_sof_enable(uint8_t rhport, bool en) -{ - (void) rhport; - (void) en; +void dcd_sof_enable(uint8_t rhport, bool en) { + (void)rhport; + (void)en; // TODO implement later } @@ -328,24 +312,23 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + (void)rhport; - const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - const unsigned xfer = ep_desc->bmAttributes.xfer; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - const unsigned odd = ep->odd; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned xfer = ep_desc->bmAttributes.xfer; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); ep->max_packet_size = tu_edpt_packet_size(ep_desc); - unsigned val = USB_ENDPT_EPCTLDIS_MASK; - val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; USB_OTG_FS->EP_CTL[epn] |= val; @@ -359,21 +342,19 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } -void dcd_edpt_close_all (uint8_t rhport) -{ - (void) rhport; +void dcd_edpt_close_all(uint8_t rhport) { + (void)rhport; // TODO implement dcd_edpt_close_all() } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; - const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][0]; + const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; USB_OTG_FS->EP_CTL[epn] &= ~msk; ep->max_packet_size = 0; ep->length = 0; @@ -381,14 +362,29 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) bd->head = 0; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) -{ - (void) rhport; + #if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + #endif + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; + (void)rhport; NVIC_DisableIRQ(USB_FS_IRQn); - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + buffer_descriptor_t *bd = &_dcd.bdt[epn][dir][ep->odd]; if (bd->own) { TU_LOG1("DCD XFER fail %x %d %lx %lx\r\n", ep_addr, total_bytes, ep->state, bd->head); @@ -399,42 +395,40 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to const unsigned mps = ep->max_packet_size; if (total_bytes > mps) { - buffer_descriptor_t *next = ep->odd ? bd - 1: bd + 1; + buffer_descriptor_t *next = ep->odd ? bd - 1 : bd + 1; /* When total_bytes is greater than the max packet size, * it prepares to the next transfer to avoid NAK in advance. */ - next->bc = total_bytes >= 2 * mps ? mps: total_bytes - mps; + next->bc = total_bytes >= 2 * mps ? mps : total_bytes - mps; next->addr = buffer + mps; next->own = 1; } - bd->bc = total_bytes >= mps ? mps: total_bytes; - bd->addr = buffer; + bd->bc = total_bytes >= mps ? mps : total_bytes; + bd->addr = buffer; __DSB(); - bd->own = 1; /* the own bit must set after addr */ + bd->own = 1; /* the own bit must set after addr */ NVIC_EnableIRQ(USB_FS_IRQn); return true; } -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; const unsigned epn = ep_addr & 0xFu; if (0 == epn) { - USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; + USB_OTG_FS->EP_CTL[epn] |= USB_ENDPT_EPSTALL_MASK; } else { - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - bd[0].bdt_stall = 1; - bd[1].bdt_stall = 1; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + bd[0].bdt_stall = 1; + bd[1].bdt_stall = 1; } } -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - const unsigned epn = ep_addr & 0xFu; - const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; - const unsigned odd = _dcd.endpoint[epn][dir].odd; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + const unsigned epn = ep_addr & 0xFu; + const unsigned dir = (ep_addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; + const unsigned odd = _dcd.endpoint[epn][dir].odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; bd[odd ^ 1].own = 0; bd[odd ^ 1].data = 1; @@ -447,19 +441,18 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; +void dcd_int_handler(uint8_t rhport) { + (void)rhport; - uint32_t is = USB_OTG_FS->INT_STAT; - uint32_t msk = USB_OTG_FS->INT_ENB; + uint32_t is = USB_OTG_FS->INT_STAT; + uint32_t msk = USB_OTG_FS->INT_ENB; USB_OTG_FS->INT_STAT = is & ~msk; is &= msk; if (is & USB_ISTAT_ERROR_MASK) { /* TODO: */ - uint32_t es = USB_OTG_FS->ERR_STAT; + uint32_t es = USB_OTG_FS->ERR_STAT; USB_OTG_FS->ERR_STAT = es; - USB_OTG_FS->INT_STAT = is; /* discard any pending events */ + USB_OTG_FS->INT_STAT = is; /* discard any pending events */ return; } @@ -493,5 +486,4 @@ void dcd_int_handler(uint8_t rhport) return; } } - #endif diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 9e5f5117f..82b6db5fd 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -426,8 +426,24 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { __DSB(); } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} +#endif + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { (void) rhport; + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); @@ -1062,5 +1078,4 @@ void tusb_hal_nrf_power_event(uint32_t event) { break; } } - #endif diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index b0b6fe857..d9a0e3fa8 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -275,14 +275,28 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ @@ -313,8 +327,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index f4af97ca7..42fb58a0a 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -38,8 +38,18 @@ #if CFG_TUD_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) #include "device/dcd.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "NuMicro.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) // We disable SOF for now until needed later on #ifndef USE_SOF @@ -293,8 +303,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) /* construct USB Configuration Register value and then write it */ uint32_t cfg = tu_edpt_number(p_endpoint_desc->bEndpointAddress); cfg |= (TUSB_DIR_IN == dir) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT; - if (TUSB_XFER_ISOCHRONOUS == type) + if (TUSB_XFER_ISOCHRONOUS == type) { cfg |= USBD_CFG_TYPE_ISO; + } ep->CFG = cfg; /* make a note of the endpoint size */ @@ -303,14 +314,28 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ @@ -341,8 +366,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; /* mine the data for the information we need */ diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 1c98a0a49..7c80f06d9 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -38,8 +38,18 @@ #if CFG_TUD_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) #include "device/dcd.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + #include "NUC505Series.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + /* * The DMA functionality of the USBD peripheral does not appear to succeed with * transfer lengths that are longer (> 64 bytes) and are not a multiple of 4. @@ -357,14 +367,28 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; if (0x80 == ep_addr) /* control EP0 IN */ @@ -424,8 +448,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; TU_ASSERT(0x80 != ep_addr && 0x00 != ep_addr); // Must not be used for control stuff diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 3d5e195a9..ad27b8528 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -129,7 +129,7 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + _dcd.setup_packet, sizeof(_dcd.setup_packet), false); } static void process_stall(uint8_t rhport) @@ -314,7 +314,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -355,24 +355,21 @@ void dcd_sof_enable(uint8_t rhport, bool en) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; +static bool edpt_open(uint8_t rhport, uint8_t ep_addr, uint16_t max_packet_size, tusb_xfer_type_t xfer) { + (void)rhport; - const unsigned ep_addr = ep_desc->bEndpointAddress; - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - const unsigned xfer = ep_desc->bmAttributes.xfer; - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - const unsigned odd = ep->odd; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir = tu_edpt_dir(ep_addr); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + const unsigned odd = ep->odd; + buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; /* No support for control transfer */ TU_ASSERT(epn && (xfer != TUSB_XFER_CONTROL)); - ep->max_packet_size = tu_edpt_packet_size(ep_desc); - unsigned val = USB_ENDPT_EPCTLDIS_MASK; - val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK: 0; + ep->max_packet_size = max_packet_size; + unsigned val = USB_ENDPT_EPCTLDIS_MASK; + val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? USB_ENDPT_EPHSHK_MASK : 0; val |= dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; KHCI->ENDPOINT[epn].ENDPT |= val; @@ -386,6 +383,26 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) return true; } +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + return edpt_open(rhport, ep_desc->bEndpointAddress, tu_edpt_packet_size(ep_desc), ep_desc->bmAttributes.xfer); +} + +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + return edpt_open(rhport, ep_addr, largest_packet_size, TUSB_XFER_ISOCHRONOUS); +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + const unsigned epn = tu_edpt_number(ep_desc->bEndpointAddress); + const unsigned dir = tu_edpt_dir(ep_desc->bEndpointAddress); + endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; + + dcd_int_disable(rhport); + ep->max_packet_size = tu_edpt_packet_size(ep_desc); + dcd_int_enable(rhport); + + return true; +} + void dcd_edpt_close_all(uint8_t rhport) { (void) rhport; @@ -408,29 +425,10 @@ void dcd_edpt_close_all(uint8_t rhport) } } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - - const unsigned epn = tu_edpt_number(ep_addr); - const unsigned dir = tu_edpt_dir(ep_addr); - endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; - buffer_descriptor_t *bd = _dcd.bdt[epn][dir]; - const unsigned msk = dir ? USB_ENDPT_EPTXEN_MASK : USB_ENDPT_EPRXEN_MASK; - const unsigned ie = NVIC_GetEnableIRQ(USB0_IRQn); - NVIC_DisableIRQ(USB0_IRQn); - KHCI->ENDPOINT[epn].ENDPT &= ~msk; - ep->max_packet_size = 0; - ep->length = 0; - ep->remaining = 0; - bd[0].head = 0; - bd[1].head = 0; - if (ie) NVIC_EnableIRQ(USB0_IRQn); -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { (void) rhport; + (void) is_isr; const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; @@ -577,5 +575,4 @@ void dcd_int_handler(uint8_t rhport) process_tokdne(rhport); } } - #endif diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 855c59cd1..349229c8d 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -205,7 +205,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); sie_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable @@ -337,9 +337,17 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -399,8 +407,9 @@ static bool control_xact(uint8_t rhport, uint8_t dir, uint8_t * buffer, uint8_t return true; } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; // Control transfer is not DMA support, and must be done in slave mode if ( tu_edpt_number(ep_addr) == 0 ) { @@ -600,5 +609,4 @@ void dcd_int_handler(uint8_t rhport) TU_BREAKPOINT(); } } - #endif diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h index 654b80866..25c9f9985 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DCD_LPC17_40_H_ -#define _TUSB_DCD_LPC17_40_H_ +#ifndef TUSB_DCD_LPC17_40_H_ +#define TUSB_DCD_LPC17_40_H_ #include "common/tusb_common.h" diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 7c637ce0c..5f4a441dc 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -322,7 +322,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; // Response with status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); dcd_reg->DEVCMDSTAT &= ~DEVCMDSTAT_DEVICE_ADDR_MASK; dcd_reg->DEVCMDSTAT |= dev_addr; @@ -432,6 +432,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) _dcd.ep[ep_id][0].cmd_sts.disable = _dcd.ep[ep_id][1].cmd_sts.disable = 1; } +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} +#endif + static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes) { uint16_t nbytes; ep_cmd_sts_t* ep_cs = get_ep_cs(ep_id); @@ -464,7 +479,8 @@ static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, ep_cs[0].cmd_sts.active = 1; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const ep_id = ep_addr2id(ep_addr); if (!buffer || total_bytes == 0) { @@ -631,5 +647,4 @@ void dcd_int_handler(uint8_t rhport) // Endpoint transfer complete interrupt process_xfer_isr(rhport, int_status); } - #endif diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index f1689b5b4..5ca093506 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -41,13 +41,16 @@ #include "host/usbh.h" #include "ohci.h" -// TODO remove -#include "chip.h" +#if defined(TUP_USBIP_OHCI_NXP) + #include "ohci_nxp.h" +#else + #error Unsupported OHCI IP +#endif //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) + enum { OHCI_CONTROL_FUNCSTATE_RESET = 0, @@ -109,22 +112,22 @@ enum { enum { OHCI_CCODE_NO_ERROR = 0, OHCI_CCODE_CRC = 1, - OHCI_CCODE_BIT_STUFFING = 2, - OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, - OHCI_CCODE_STALL = 4, - OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, - OHCI_CCODE_PID_CHECK_FAILURE = 6, - OHCI_CCODE_UNEXPECTED_PID = 7, - OHCI_CCODE_DATA_OVERRUN = 8, - OHCI_CCODE_DATA_UNDERRUN = 9, - OHCI_CCODE_BUFFER_OVERRUN = 12, - OHCI_CCODE_BUFFER_UNDERRUN = 13, - OHCI_CCODE_NOT_ACCESSED = 14, + OHCI_CCODE_BIT_STUFFING = 2, + OHCI_CCODE_DATA_TOGGLE_MISMATCH = 3, + OHCI_CCODE_STALL = 4, + OHCI_CCODE_DEVICE_NOT_RESPONDING = 5, + OHCI_CCODE_PID_CHECK_FAILURE = 6, + OHCI_CCODE_UNEXPECTED_PID = 7, + OHCI_CCODE_DATA_OVERRUN = 8, + OHCI_CCODE_DATA_UNDERRUN = 9, + OHCI_CCODE_BUFFER_OVERRUN = 12, + OHCI_CCODE_BUFFER_UNDERRUN = 13, + OHCI_CCODE_NOT_ACCESSED = 14, }; enum { OHCI_INT_ON_COMPLETE_YES = 0, - OHCI_INT_ON_COMPLETE_NO = TU_BIN8(111) + OHCI_INT_ON_COMPLETE_NO = 0x7 // 0b111 }; enum { @@ -144,21 +147,36 @@ enum { }; //--------------------------------------------------------------------+ +// Support for explicit D-cache operations +//--------------------------------------------------------------------+ +TU_ATTR_WEAK bool hcd_dcache_clean(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } +TU_ATTR_WEAK bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) { (void) addr; (void) data_size; return true; } + +// Optional macro to access ED in uncached way +#ifndef hcd_dcache_uncached +#define hcd_dcache_uncached(x) (x) +#endif + +//--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(256) static ohci_data_t ohci_data; -static ohci_ed_t * const p_ed_head[] = -{ - [TUSB_XFER_CONTROL] = &ohci_data.control[0].ed, - [TUSB_XFER_BULK ] = &ohci_data.bulk_head_ed, - [TUSB_XFER_INTERRUPT] = &ohci_data.period_head_ed, +static ohci_ed_t * const p_ed_head[] = { + [TUSB_XFER_CONTROL] = hcd_dcache_uncached(&ohci_data.control[0].ed), + [TUSB_XFER_BULK ] = hcd_dcache_uncached(&ohci_data.bulk_head_ed), + [TUSB_XFER_INTERRUPT] = hcd_dcache_uncached(&ohci_data.period_head_ed), [TUSB_XFER_ISOCHRONOUS] = NULL // TODO Isochronous }; static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed); static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr); static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd); +static ohci_ed_t* ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); + +TU_ATTR_ALWAYS_INLINE static inline ohci_ed_t* ed_control(uint8_t daddr) { + return hcd_dcache_uncached(&ohci_data.control[daddr].ed); +} //--------------------------------------------------------------------+ // USBH-HCD API @@ -166,13 +184,11 @@ static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd); // If your system requires separation of virtual and physical memory, implement // tusb_app_virt_to_phys and tusb_app_virt_to_phys in your application. -TU_ATTR_ALWAYS_INLINE static inline void *_phys_addr(void *virtual_address) -{ +TU_ATTR_ALWAYS_INLINE static inline void *_phys_addr(void *virtual_address) { return tusb_app_virt_to_phys(virtual_address); } -TU_ATTR_ALWAYS_INLINE static inline void *_virt_addr(void *physical_address) -{ +TU_ATTR_ALWAYS_INLINE static inline void *_virt_addr(void *physical_address) { return tusb_app_phys_to_virt(physical_address); } @@ -181,34 +197,33 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rhport; (void) rh_init; + ohci_phy_init(rhport); + //------------- Data Structure init -------------// tu_memclr(&ohci_data, sizeof(ohci_data_t)); - for(uint8_t i=0; i<32; i++) - { // assign all interrupt pointers to period head ed + // assign all interrupt pointers to period head ed + for(uint8_t i=0; i<32; i++) { ohci_data.hcca.interrupt_table[i] = (uint32_t) _phys_addr(&ohci_data.period_head_ed); } - ohci_data.control[0].ed.skip = 1; - ohci_data.bulk_head_ed.skip = 1; - ohci_data.period_head_ed.skip = 1; + ohci_data.control[0].ed.w0.skip = 1; + ohci_data.bulk_head_ed.w0.skip = 1; + ohci_data.period_head_ed.w0.skip = 1; //If OHCI hardware is in SMM mode, gain ownership (Ref OHCI spec 5.1.1.3.3) - if (OHCI_REG->control_bit.interrupt_routing == 1) - { + if (OHCI_REG->control_bit.interrupt_routing == 1) { OHCI_REG->command_status_bit.ownership_change_request = 1; while (OHCI_REG->control_bit.interrupt_routing == 1) {} - } - - //If OHCI hardware has come from warm-boot, signal resume (Ref OHCI spec 5.1.1.3.4) - else if (OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_RESET && - OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_OPERATIONAL) - { + } else if (OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_RESET && + OHCI_REG->control_bit.hc_functional_state != OHCI_CONTROL_FUNCSTATE_OPERATIONAL) { + //If OHCI hardware has come from warm-boot, signal resume (Ref OHCI spec 5.1.1.3.4) //Wait 20 ms. (Ref Usb spec 7.1.7.7) OHCI_REG->control_bit.hc_functional_state = OHCI_CONTROL_FUNCSTATE_RESUME; - tusb_time_delay_ms_api(20); } + hcd_dcache_clean(&ohci_data, sizeof(ohci_data)); + // reset controller OHCI_REG->command_status_bit.controller_reset = 1; while( OHCI_REG->command_status_bit.controller_reset ) {} // should not take longer than 10 us @@ -245,7 +260,6 @@ uint32_t hcd_frame_number(uint8_t rhport) return (ohci_data.frame_number_hi << 16) | OHCI_REG->frame_number; } - //--------------------------------------------------------------------+ // PORT API //--------------------------------------------------------------------+ @@ -271,26 +285,18 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid) // endpoints are tied to an address, which only reclaim after a long delay when enumerating // thus there is no need to make sure ED is not in HC's cahed as it will not for sure -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // TODO OHCI (void) rhport; // addr0 serves as static head --> only set skip bit - if ( dev_addr == 0 ) - { - ohci_data.control[0].ed.skip = 1; - }else - { - // remove control - ed_list_remove_by_addr( p_ed_head[TUSB_XFER_CONTROL], dev_addr); - - // remove bulk - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); - - // remove interrupt - ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); - + if (dev_addr == 0) { + ohci_ed_t* ed = ed_control(0); + ed->w0.skip = 1; + } else { + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_CONTROL], dev_addr); // remove control + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_BULK], dev_addr); // remove bulk + ed_list_remove_by_addr(p_ed_head[TUSB_XFER_INTERRUPT], dev_addr); // remove interrupt // TODO remove ISO } } @@ -302,35 +308,36 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) //--------------------------------------------------------------------+ // List Helper //--------------------------------------------------------------------+ -static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) -{ - return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : - (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : - (p_ed->is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; +static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_word0_t w0) { + return (w0.ep_number == 0 ) ? TUSB_XFER_CONTROL : + (w0.is_iso ) ? TUSB_XFER_ISOCHRONOUS : + (w0.is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; } -static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) -{ +static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) { (void) interval; // address 0 is used as async head, which always on the list --> cannot be cleared - if (dev_addr != 0) - { - tu_memclr(p_ed, sizeof(ohci_ed_t)); + if (dev_addr != 0) { + p_ed->td_tail = 0; + p_ed->td_head.address = 0; + p_ed->next = 0; } tuh_bus_info_t bus_info; tuh_bus_info_get(dev_addr, &bus_info); - p_ed->dev_addr = dev_addr; - p_ed->ep_number = ep_addr & 0x0F; - p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); - p_ed->speed = bus_info.speed; - p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - p_ed->max_packet_size = ep_size; + ohci_ed_word0_t w0 = {.value = 0}; + w0.dev_addr = dev_addr; + w0.ep_number = ep_addr & 0x0F; + w0.pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); + w0.speed = bus_info.speed; + w0.is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; + w0.max_packet_size = ep_size; - p_ed->used = 1; - p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); + w0.used = 1; + w0.is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); + p_ed->w0 = w0; } static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) { @@ -353,126 +360,109 @@ static void gtd_init(ohci_gtd_t *p_td, uint8_t *data_ptr, uint16_t total_bytes) } } -static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) -{ - if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; +static ohci_ed_t* ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { + if (tu_edpt_number(ep_addr) == 0) { + return ed_control(dev_addr); + } ohci_ed_t* ed_pool = ohci_data.ed_pool; - - for(uint32_t i=0; i<ED_MAX; i++) - { - if ( (ed_pool[i].dev_addr == dev_addr) && - ep_addr == tu_edpt_addr(ed_pool[i].ep_number, ed_pool[i].pid == PID_IN) ) - { - return &ed_pool[i]; + for (size_t i = 0; i < ED_MAX; i++) { + ohci_ed_t* qhd = hcd_dcache_uncached(&ed_pool[i]); + if ((qhd->w0.dev_addr == dev_addr) && + ep_addr == tu_edpt_addr(qhd->w0.ep_number, qhd->w0.pid == PID_IN)) { + return qhd; } } return NULL; } -static ohci_ed_t * ed_find_free(void) -{ +static ohci_ed_t* ed_find_free(void) { ohci_ed_t* ed_pool = ohci_data.ed_pool; - - for(uint8_t i = 0; i < ED_MAX; i++) - { - if ( !ed_pool[i].used ) return &ed_pool[i]; + for (size_t i = 0; i < ED_MAX; i++) { + ohci_ed_t* qhd = hcd_dcache_uncached(&ed_pool[i]); + if (!qhd->w0.used) { + return qhd; + } } - return NULL; } -static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) -{ +static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed) { p_ed->next = p_pre->next; p_pre->next = (uint32_t) _phys_addr(p_ed); } -static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) -{ +static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) { ohci_ed_t* p_prev = p_head; - while( p_prev->next ) - { - ohci_ed_t* ed = (ohci_ed_t*) _virt_addr((void *)p_prev->next); + while (p_prev->next) { + ohci_ed_t* ed = (ohci_ed_t*)_virt_addr((void*)p_prev->next); - if (ed->dev_addr == dev_addr) - { + if (ed->w0.dev_addr == dev_addr) { // Prevent Host Controller from processing this ED while we remove it - ed->skip = 1; + ed->w0.skip = 1; // unlink ed, will also move up p_prev p_prev->next = ed->next; // point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED - ed->next = (uint32_t) _phys_addr(p_head); - ed->used = 0; - ed->skip = 0; - }else - { - p_prev = (ohci_ed_t*) _virt_addr((void *)p_prev->next); + ed->next = (uint32_t)_phys_addr(p_head); + ed->w0.used = 0; + ed->w0.skip = 0; + } else { + p_prev = (ohci_ed_t*)_virt_addr((void*)p_prev->next); } } } -static ohci_gtd_t * gtd_find_free(void) -{ - for(uint8_t i=0; i < GTD_MAX; i++) - { - if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; +static ohci_gtd_t* gtd_find_free(void) { + for (uint8_t i = 0; i < GTD_MAX; i++) { + if (!ohci_data.gtd_pool[i].used) { + return &ohci_data.gtd_pool[i]; + } } - return NULL; } -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) -{ - // tail is always NULL - if ( tu_align16(p_ed->td_head.address) == 0 ) - { // TD queue is empty --> head = TD - p_ed->td_head.address |= (uint32_t) _phys_addr(p_gtd); - } - else - { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) tu_align16((uint32_t)_virt_addr((void *)p_ed->td_head.address)))->next = (uint32_t) _phys_addr(p_gtd); - } -} - //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc) { + (void)rhport; // TODO iso support TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// - ohci_ed_t * p_ed; - - if ( ep_desc->bEndpointAddress == 0 ) - { - p_ed = &ohci_data.control[dev_addr].ed; - }else - { + ohci_ed_t* p_ed; + if (ep_desc->bEndpointAddress == 0) { + p_ed = ed_control(dev_addr); + } else { p_ed = ed_find_free(); } TU_ASSERT(p_ed); - ed_init( p_ed, dev_addr, tu_edpt_packet_size(ep_desc), ep_desc->bEndpointAddress, - ep_desc->bmAttributes.xfer, ep_desc->bInterval ); + ed_init(p_ed, dev_addr, tu_edpt_packet_size(ep_desc), ep_desc->bEndpointAddress, + ep_desc->bmAttributes.xfer, ep_desc->bInterval); // control of dev0 is used as static async head - if ( dev_addr == 0 ) - { - p_ed->skip = 0; // only need to clear skip bit + if (dev_addr == 0) { + p_ed->w0.skip = 0; // only need to clear skip bit return true; } - ed_list_insert( p_ed_head[ep_desc->bmAttributes.xfer], p_ed ); + if (tu_edpt_number(ep_desc->bEndpointAddress) != 0) { + // Get an empty TD and use it as the end-of-list marker. + // This marker TD will be used when a transfer is made on this EP + // (and a new, empty TD will be allocated for the next-next transfer). + ohci_gtd_t* gtd = gtd_find_free(); + TU_ASSERT(gtd); + p_ed->td_head.address = (uint32_t)_phys_addr(gtd); + p_ed->td_tail = (uint32_t)_phys_addr(gtd); + } + ed_list_insert(p_ed_head[ep_desc->bmAttributes.xfer], p_ed); return true; } @@ -481,18 +471,20 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { return false; // TODO not implemented yet } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { (void) rhport; - ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + ohci_ed_t* ed = ed_control(dev_addr); ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd; + hcd_dcache_clean(setup_packet, 8); + gtd_init(qtd, (uint8_t*)(uintptr_t) setup_packet, 8); qtd->index = dev_addr; qtd->pid = PID_SETUP; qtd->data_toggle = GTD_DT_DATA0; qtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + hcd_dcache_clean(qtd, sizeof(ohci_gtd_t)); //------------- Attach TDs list to Control Endpoint -------------// ed->td_head.address = (uint32_t) _phys_addr(qtd); @@ -502,43 +494,53 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - if ( epnum == 0 ) - { - ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; + // IN transfer: invalidate buffer, OUT transfer: clean buffer + if (dir) { + hcd_dcache_invalidate(buffer, buflen); + } else { + hcd_dcache_clean(buffer, buflen); + } + ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); + TU_ASSERT(ed); + if (epnum == 0) { + ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; gtd_init(gtd, buffer, buflen); - gtd->index = dev_addr; - gtd->pid = dir ? PID_IN : PID_OUT; - gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 + gtd->pid = dir ? PID_IN : PID_OUT; + gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); - ed->td_head.address = (uint32_t) _phys_addr(gtd); + ed->td_head.address = (uint32_t)_phys_addr(gtd); OHCI_REG->command_status_bit.control_list_filled = 1; - }else - { - ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); - ohci_gtd_t* gtd = gtd_find_free(); - - TU_ASSERT(gtd); + } else { + tusb_xfer_type_t xfer_type = ed_get_xfer_type(ed->w0); + ohci_gtd_t* gtd = (ohci_gtd_t*)_virt_addr((void*)ed->td_tail); gtd_init(gtd, buffer, buflen); gtd->index = ed-ohci_data.ed_pool; gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - td_insert_to_ed(ed, gtd); + // Insert a new, empty TD at the tail, to be used by the next transfer + ohci_gtd_t* new_gtd = gtd_find_free(); + TU_ASSERT(new_gtd); + + gtd->next = (uint32_t)_phys_addr(new_gtd); + hcd_dcache_clean(gtd, sizeof(ohci_gtd_t)); + + ed->td_tail = (uint32_t)_phys_addr(new_gtd); - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + if (TUSB_XFER_BULK == xfer_type) { + OHCI_REG->command_status_bit.bulk_list_filled = 1; + } } return true; @@ -556,13 +558,14 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; ohci_ed_t * const p_ed = ed_from_addr(dev_addr, ep_addr); - p_ed->is_stalled = 0; - p_ed->td_tail &= 0x0Ful; // set tail pointer back to NULL - - p_ed->td_head.toggle = 0; // reset data toggle - p_ed->td_head.halted = 0; + ohci_ed_word2_t td_head = p_ed->td_head; + td_head.toggle = 0; // reset data toggle + td_head.halted = 0; + p_ed->td_head = td_head; - if ( TUSB_XFER_BULK == ed_get_xfer_type(p_ed) ) OHCI_REG->command_status_bit.bulk_list_filled = 1; + if (TUSB_XFER_BULK == ed_get_xfer_type(p_ed->w0)) { + OHCI_REG->command_status_bit.bulk_list_filled = 1; + } return true; } @@ -571,14 +574,18 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { //--------------------------------------------------------------------+ // OHCI Interrupt Handler //--------------------------------------------------------------------+ -static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) -{ - ohci_td_item_t* td_reverse_head = NULL; +TU_ATTR_ALWAYS_INLINE static inline bool is_itd(ohci_td_item_t* item) { + (void) item; + return false; // ISO not supported yet +} - while(td_head != NULL) - { +static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) { + ohci_td_item_t* td_reverse_head = NULL; + while(td_head != NULL) { td_head = _virt_addr(td_head); - uint32_t next = td_head->next; + const uint32_t item_size = is_itd(td_head) ? sizeof(ohci_itd_t) : sizeof(ohci_gtd_t); + hcd_dcache_invalidate(td_head, item_size); + const uint32_t next = td_head->next; // make current's item become reverse's first item td_head->next = (uint32_t) td_reverse_head; @@ -590,24 +597,22 @@ static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head) return _virt_addr(td_reverse_head); } -static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) -{ +TU_ATTR_ALWAYS_INLINE static inline bool gtd_is_control(ohci_gtd_t const * const p_qtd) { return ((uint32_t) p_qtd) < ((uint32_t) ohci_data.gtd_pool); // check ohci_data_t for memory layout } -static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) -{ - if ( gtd_is_control(p_qtd) ) - { - return &ohci_data.control[p_qtd->index].ed; - }else - { - return &ohci_data.ed_pool[p_qtd->index]; +TU_ATTR_ALWAYS_INLINE static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const* const p_qtd) { + ohci_ed_t* ed; + if (gtd_is_control(p_qtd)) { + ed = &ohci_data.control[p_qtd->index].ed; + } else { + ed = &ohci_data.ed_pool[p_qtd->index]; } + return hcd_dcache_uncached(ed); } static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { - if ( gtd_is_control(gtd) ) { + if (gtd_is_control(gtd)) { uint8_t idx = ((uintptr_t)gtd - (uintptr_t)&ohci_data.control->gtd) / sizeof(ohci_data.control[0]); return &ohci_data.gtd_extra_control[idx]; }else { @@ -615,102 +620,77 @@ static gtd_extra_data_t *gtd_get_extra_data(ohci_gtd_t const * const gtd) { } } -static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) { // 5.2.9 OHCI sample code - // CBP is 0 mean all data is transferred - if (current_buffer == 0) return 0; + if (current_buffer == 0) { + return 0; + } return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + - tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; } -static void done_queue_isr(uint8_t hostid) -{ - (void) hostid; +static void done_queue_isr(uint8_t hostid) { + (void)hostid; // done head is written in reversed order of completion --> need to reverse the done queue first - ohci_td_item_t* td_head = list_reverse ( (ohci_td_item_t*) tu_align16(ohci_data.hcca.done_head) ); + ohci_td_item_t* td_head = list_reverse((ohci_td_item_t*)tu_align16(ohci_data.hcca.done_head)); ohci_data.hcca.done_head = 0; - while( td_head != NULL ) - { + while (td_head != NULL) { // TODO check if td_head is iso td //------------- Non ISO transfer -------------// - ohci_gtd_t * const qtd = (ohci_gtd_t *) td_head; + ohci_gtd_t* const qtd = (ohci_gtd_t*) td_head; xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; - qtd->used = 0; // free TD - if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) - { - ohci_ed_t * const ed = gtd_get_ed(qtd); - uint32_t const xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); - - // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. - // When there is a error resulting this ED is halted, and this EP still has other queued TD - // --> the Bulk list only has this halted EP queueing TDs (remaining) - // --> Bulk list will be considered as not empty by HC !!! while there is no attempt transaction on this list - // --> HC will not process Control list (due to service ratio when Bulk list not empty) - // To walk-around this, the halted ED will have TailP = HeadP (empty list condition), when clearing halt - // the TailP must be set back to NULL for processing remaining TDs - if (event != XFER_RESULT_SUCCESS) - { - ed->td_tail &= 0x0Ful; - ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue - if ( event == XFER_RESULT_STALLED ) ed->is_stalled = 1; - } - - uint8_t dir = (ed->ep_number == 0) ? (qtd->pid == PID_IN) : (ed->pid == PID_IN); - - hcd_event_xfer_complete(ed->dev_addr, tu_edpt_addr(ed->ep_number, dir), xferred_bytes, event, true); + if ((qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS)) { + const ohci_ed_t* ed = gtd_get_ed(qtd); + const ohci_ed_word0_t ed_w0 = ed->w0; + const uint32_t xferred_bytes = gtd_get_extra_data(qtd)->expected_bytes - gtd_xfer_byte_left((uint32_t)qtd->buffer_end, (uint32_t)qtd->current_buffer_pointer); + uint8_t dir = (ed_w0.ep_number == 0) ? (qtd->pid == PID_IN) : (ed_w0.pid == PID_IN); + const uint8_t ep_addr = tu_edpt_addr(ed_w0.ep_number, dir); + hcd_event_xfer_complete(ed_w0.dev_addr, ep_addr, xferred_bytes, event, true); } - td_head = (ohci_td_item_t*) _virt_addr((void *)td_head->next); + td_head = (ohci_td_item_t*)_virt_addr((void*)td_head->next); } } void hcd_int_handler(uint8_t hostid, bool in_isr) { - (void) in_isr; - - uint32_t const int_en = OHCI_REG->interrupt_enable; + (void)in_isr; + uint32_t const int_en = OHCI_REG->interrupt_enable; uint32_t const int_status = OHCI_REG->interrupt_status & int_en; - if (int_status == 0) return; + if (int_status == 0) { + return; + } // Disable MIE as per OHCI spec 5.3 OHCI_REG->interrupt_disable = OHCI_INT_MASTER_ENABLE_MASK; // Frame number overflow - if ( int_status & OHCI_INT_FRAME_OVERFLOW_MASK ) - { + if (int_status & OHCI_INT_FRAME_OVERFLOW_MASK) { ohci_data.frame_number_hi++; } //------------- RootHub status -------------// - if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) - { - for (int i = 0; i < TUP_OHCI_RHPORTS; i++) - { + if (int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK) { + for (int i = 0; i < TUP_OHCI_RHPORTS; i++) { uint32_t const rhport_status = OHCI_REG->rhport_status[i] & RHPORT_ALL_CHANGE_MASK; - if ( rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK ) - { + if (rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK) { // TODO check if remote wake-up - if ( OHCI_REG->rhport_status_bit[i].current_connect_status ) - { + if (OHCI_REG->rhport_status_bit[i].current_connect_status) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) OHCI_REG->rhport_status[i] = RHPORT_PORT_RESET_STATUS_MASK; hcd_event_device_attach(i, true); - }else - { + } else { hcd_event_device_remove(i, true); } } - if ( rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) - { - + if (rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) { } OHCI_REG->rhport_status[i] = rhport_status; // acknowledge all interrupt @@ -718,13 +698,11 @@ void hcd_int_handler(uint8_t hostid, bool in_isr) { } //------------- Transfer Complete -------------// - if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) - { + if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) { done_queue_isr(hostid); } OHCI_REG->interrupt_status = int_status; // Acknowledge handled interrupt - OHCI_REG->interrupt_enable = OHCI_INT_MASTER_ENABLE_MASK; // Enable MIE } //--------------------------------------------------------------------+ diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 94bad5df7..d9ebe1d54 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OHCI_H_ -#define _TUSB_OHCI_H_ +#ifndef TUSB_OHCI_H_ +#define TUSB_OHCI_H_ #ifdef __cplusplus extern "C" { @@ -48,6 +48,10 @@ enum { // tinyUSB's OHCI implementation caps number of EDs to 8 bits TU_VERIFY_STATIC (ED_MAX <= 256, "Reduce CFG_TUH_DEVICE_MAX or CFG_TUH_ENDPOINT_MAX"); +#define GTD_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16) +#define ED_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 16) +#define ITD_ALIGN_SIZE TU_MAX(CFG_TUH_MEM_DCACHE_LINE_SIZE, 32) + //--------------------------------------------------------------------+ // OHCI Data Structure //--------------------------------------------------------------------+ @@ -61,18 +65,35 @@ typedef struct { TU_VERIFY_STATIC( sizeof(ohci_hcca_t) == 256, "size is not correct" ); +// An OHCI host controller is controlled using data structures placed in memory (RAM). +// It needs to both read and write these data structures (as defined by the OHCI specification), +// and this can be mentally conceptualized similar to two software threads running on +// two different CPUs. In order to prevent a _data race_ where data gets corrupted, +// the CPU and the OHCI host controller need to agree on how the memory should be accessed. +// In this driver, we do this by transferring logical ownership of transfer descriptors (TDs) +// between the CPU and the OHCI host controller. Only the device which holds the logical ownership +// is allowed to read or write the TD. This ownership is not visible anywhere in the code, +// but it instead must be inferred based on the logical state of the transfer. +// +// If dcache-supporting mode is enabled, we need to do additional manual cache operations +// in order to correctly transfer this logical ownership and prevent data corruption. +// In order to do this, we also choose to align each OHCI TD so that it doesn't +// share CPU cache lines with other TDs. This is because manual cache operations +// can only be performed on cache line granularity. In other words, one cache line is +// the _smallest_ amount that can be read/written at a time. If there were to be multiple TDs +// in the same cache line, they would be required to always have the same logical ownership. +// This ends up being impossible to guarantee, so we choose a design which avoids the situation entirely. + // common link item for gtd and itd for list travel -// use as pointer only typedef struct TU_ATTR_ALIGNED(16) { uint32_t reserved[2]; volatile uint32_t next; uint32_t reserved2; }ohci_td_item_t; -typedef struct TU_ATTR_ALIGNED(16) -{ - // Word 0 - uint32_t used : 1; +typedef struct TU_ATTR_ALIGNED(GTD_ALIGN_SIZE) { + // Word 0 + uint32_t used : 1; uint32_t index : 8; // endpoint index the gtd belongs to, or device address in case of control xfer uint32_t : 9; // can be used uint32_t buffer_rounding : 1; @@ -82,56 +103,55 @@ typedef struct TU_ATTR_ALIGNED(16) volatile uint32_t error_count : 2; volatile uint32_t condition_code : 4; - // Word 1 - uint8_t* volatile current_buffer_pointer; + // Word 1 + uint8_t* volatile current_buffer_pointer; - // Word 2 : next TD - volatile uint32_t next; + // Word 2 : next TD + volatile uint32_t next; - // Word 3 - uint8_t* buffer_end; + // Word 3 + uint8_t* buffer_end; } ohci_gtd_t; +TU_VERIFY_STATIC(sizeof(ohci_gtd_t) == GTD_ALIGN_SIZE, "size is not correct" ); -TU_VERIFY_STATIC( sizeof(ohci_gtd_t) == 16, "size is not correct" ); - -typedef struct TU_ATTR_ALIGNED(16) -{ - // Word 0 - uint32_t dev_addr : 7; - uint32_t ep_number : 4; - uint32_t pid : 2; - uint32_t speed : 1; - uint32_t skip : 1; - uint32_t is_iso : 1; - uint32_t max_packet_size : 11; - // HCD: make use of 5 reserved bits - uint32_t used : 1; - uint32_t is_interrupt_xfer : 1; - uint32_t is_stalled : 1; - uint32_t : 2; - - // Word 1 - uint32_t td_tail; +typedef union { + struct { + uint32_t dev_addr : 7; + uint32_t ep_number : 4; + uint32_t pid : 2; + uint32_t speed : 1; + uint32_t skip : 1; + uint32_t is_iso : 1; + uint32_t max_packet_size : 11; + // HCD: make use of 5 reserved bits + uint32_t used : 1; + uint32_t is_interrupt_xfer : 1; + uint32_t : 3; + }; + uint32_t value; +} ohci_ed_word0_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_word0_t) == 4, "size is not correct" ); - // Word 2 - volatile union { - uint32_t address; - struct { - uint32_t halted : 1; - uint32_t toggle : 1; - uint32_t : 30; - }; - }td_head; +typedef union { + uint32_t address; + struct { + uint32_t halted : 1; + uint32_t toggle : 1; + uint32_t : 30; + }; +} ohci_ed_word2_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_word2_t) == 4, "size is not correct" ); - // Word 3: next ED - uint32_t next; +typedef struct TU_ATTR_ALIGNED(ED_ALIGN_SIZE) { + ohci_ed_word0_t w0; // Word 0 + uint32_t td_tail; // Word 1 + volatile ohci_ed_word2_t td_head; // Word 2 + uint32_t next; // Word 3 } ohci_ed_t; +TU_VERIFY_STATIC(sizeof(ohci_ed_t) == ED_ALIGN_SIZE, "size is not correct" ); -TU_VERIFY_STATIC( sizeof(ohci_ed_t) == 16, "size is not correct" ); - -typedef struct TU_ATTR_ALIGNED(32) -{ - /*---------- Word 1 ----------*/ +typedef struct TU_ATTR_ALIGNED(ITD_ALIGN_SIZE) { + /*---------- Word 1 ----------*/ uint32_t starting_frame : 16; uint32_t : 5; // can be used uint32_t delay_interrupt : 3; @@ -139,24 +159,25 @@ typedef struct TU_ATTR_ALIGNED(32) uint32_t : 1; // can be used volatile uint32_t condition_code : 4; - /*---------- Word 2 ----------*/ - uint32_t buffer_page0; // 12 lsb bits can be used - /*---------- Word 3 ----------*/ - volatile uint32_t next; + /*---------- Word 2 ----------*/ + uint32_t buffer_page0; // 12 lsb bits can be used - /*---------- Word 4 ----------*/ - uint32_t buffer_end; + /*---------- Word 3 ----------*/ + volatile uint32_t next; - /*---------- Word 5-8 ----------*/ - volatile uint16_t offset_packetstatus[8]; -} ochi_itd_t; + /*---------- Word 4 ----------*/ + uint32_t buffer_end; -TU_VERIFY_STATIC( sizeof(ochi_itd_t) == 32, "size is not correct" ); + /*---------- Word 5-8 ----------*/ + volatile uint16_t offset_packetstatus[8]; +} ohci_itd_t; +TU_VERIFY_STATIC(sizeof(ohci_itd_t) == ITD_ALIGN_SIZE, "size is not correct" ); typedef struct { uint16_t expected_bytes; // up to 8192 bytes so max is 13 bits } gtd_extra_data_t; +TU_VERIFY_STATIC(sizeof(gtd_extra_data_t) == 2, "size is not correct" ); // structure with member alignment required from large to small typedef struct TU_ATTR_ALIGNED(256) { @@ -192,10 +213,10 @@ typedef struct TU_ATTR_ALIGNED(256) { //--------------------------------------------------------------------+ typedef volatile struct { - uint32_t revision; + uint32_t revision; // 0x00 union { - uint32_t control; + uint32_t control; // 0x04 struct { uint32_t control_bulk_service_ratio : 2; uint32_t periodic_list_enable : 1; @@ -211,7 +232,7 @@ typedef volatile struct }; union { - uint32_t command_status; + uint32_t command_status; // 0x08 struct { uint32_t controller_reset : 1; uint32_t control_list_filled : 1; @@ -222,26 +243,24 @@ typedef volatile struct }command_status_bit; }; - uint32_t interrupt_status; - uint32_t interrupt_enable; - uint32_t interrupt_disable; - - uint32_t hcca; - uint32_t period_current_ed; - uint32_t control_head_ed; - uint32_t control_current_ed; - uint32_t bulk_head_ed; - uint32_t bulk_current_ed; - uint32_t done_head; - - uint32_t frame_interval; - uint32_t frame_remaining; - uint32_t frame_number; - uint32_t periodic_start; - uint32_t lowspeed_threshold; + uint32_t interrupt_status; // 0x0C + uint32_t interrupt_enable; // 0x10 + uint32_t interrupt_disable; // 0x14 + uint32_t hcca; // 0x18 + uint32_t period_current_ed; // 0x1C + uint32_t control_head_ed; // 0x20 + uint32_t control_current_ed; // 0x24 + uint32_t bulk_head_ed; // 0x28 + uint32_t bulk_current_ed; // 0x2C + uint32_t done_head; // 0x30 + uint32_t frame_interval; // 0x34 + uint32_t frame_remaining; // 0x38 + uint32_t frame_number; // 0x3C + uint32_t periodic_start; // 0x40 + uint32_t lowspeed_threshold; // 0x44 union { - uint32_t rh_descriptorA; + uint32_t rh_descriptorA; // 0x48 struct { uint32_t number_downstream_ports : 8; uint32_t power_switching_mode : 1; @@ -255,7 +274,7 @@ typedef volatile struct }; union { - uint32_t rh_descriptorB; + uint32_t rh_descriptorB; // 0x4C struct { uint32_t device_removable : 16; uint32_t port_power_control_mask : 16; @@ -263,9 +282,9 @@ typedef volatile struct }; union { - uint32_t rh_status; + uint32_t rh_status; // 0x50 struct { - uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power + uint32_t local_power_status : 1; // read Local Power Status; write: Clear Global Power uint32_t over_current_indicator : 1; uint32_t : 13; uint32_t device_remote_wakeup_enable : 1; @@ -277,7 +296,8 @@ typedef volatile struct }; union { - uint32_t rhport_status[TUP_OHCI_RHPORTS]; + uint32_t rhport_status[TUP_OHCI_RHPORTS]; // 0x54 + struct { uint32_t current_connect_status : 1; uint32_t port_enable_status : 1; @@ -304,4 +324,4 @@ TU_VERIFY_STATIC( sizeof(ohci_registers_t) == (0x54 + (4 * TUP_OHCI_RHPORTS)), " } #endif -#endif /* _TUSB_OHCI_H_ */ +#endif /* TUSB_OHCI_H_ */ diff --git a/src/portable/ohci/ohci_nxp.h b/src/portable/ohci/ohci_nxp.h new file mode 100644 index 000000000..9cba05e95 --- /dev/null +++ b/src/portable/ohci/ohci_nxp.h @@ -0,0 +1,70 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 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 TUSB_OHCI_NXP_H +#define TUSB_OHCI_NXP_H + +#if TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC40XX) + +#include "chip.h" +#define OHCI_REG ((ohci_registers_t *) LPC_USB_BASE) + +void hcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ(USB_IRQn); +} + +void hcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ(USB_IRQn); +} + +static void ohci_phy_init(uint8_t rhport) { + (void) rhport; +} + +#else + +#include "fsl_device_registers.h" + +// for LPC55 USB0 controller +#define OHCI_REG ((ohci_registers_t *) USBFSH_BASE) + +static void ohci_phy_init(uint8_t rhport) { + (void) rhport; +} + +void hcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ(USB0_IRQn); +} + +void hcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ(USB0_IRQn); +} +#endif + +#endif diff --git a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c index 60afbd435..78df2b6a6 100644 --- a/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c @@ -76,7 +76,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) { // must be called before queuing status pio_usb_device_set_address(dev_addr); - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); } // Wake up host @@ -113,16 +113,30 @@ void dcd_edpt_close_all (uint8_t rhport) (void) rhport; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; endpoint_t *ep = pio_usb_device_get_endpoint_by_address(ep_addr); return pio_usb_ll_transfer_start(ep, buffer, total_bytes); } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -//bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +//bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) //{ // (void) rhport; // (void) ep_addr; @@ -207,5 +221,4 @@ void __no_inline_not_in_flash_func(pio_usb_device_irq_handler)(uint8_t root_id) // clear all rport->ints &= ~ints; } - #endif diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c index d59a2b4ee..90eb920e0 100644 --- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c @@ -29,9 +29,20 @@ #if CFG_TUH_ENABLED && (CFG_TUSB_MCU == OPT_MCU_RP2040) && CFG_TUH_RPI_PIO_USB #include "pico.h" + #include "pio_usb.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + #include "pio_usb_ll.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index a89c2f42b..15852f29f 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -526,7 +526,8 @@ void dcd_edpt_close_all(uint8_t rhport) { reset_non_control_endpoints(); } -bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(__unused uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; assert(rhport == 0); hw_endpoint_xfer(ep_addr, buffer, total_bytes); return true; diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index ecd28973c..7caf5d68a 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -859,8 +859,24 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) _dcd.ep[dir][epn] = 0; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +#if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} +#endif + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; rusb2_reg_t* rusb = RUSB2_REG(rhport); dcd_int_disable(rhport); @@ -870,8 +886,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to return r; } -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); rusb2_reg_t* rusb = RUSB2_REG(rhport); @@ -1028,5 +1045,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/renesas/rusb2/rusb2_type.h b/src/portable/renesas/rusb2/rusb2_type.h index dd88f66a7..71837d03c 100644 --- a/src/portable/renesas/rusb2/rusb2_type.h +++ b/src/portable/renesas/rusb2/rusb2_type.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_RUSB2_TYPE_H_ -#define _TUSB_RUSB2_TYPE_H_ +#ifndef TUSB_RUSB2_TYPE_H_ +#define TUSB_RUSB2_TYPE_H_ #include <stdint.h> #include <stddef.h> @@ -1777,4 +1777,4 @@ TU_VERIFY_STATIC(offsetof(rusb2_reg_t, DPUSR1R_FS ) == 0x0404, "incorrect offset } #endif -#endif /* _TUSB_RUSB2_TYPE_H_ */ +#endif /* TUSB_RUSB2_TYPE_H_ */ diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index b16509c6f..be694edfa 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -339,14 +339,28 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) return true; } +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; // TODO not implemented yet +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { + (void) rhport; + (void) desc_ep; + return false; // TODO not implemented yet +} + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; bool ret = true; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 3b9825e25..6276f0f07 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -246,7 +246,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void)dev_addr; // Respond with status - dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK | 0x00, NULL, 0); + dcd_edpt_xfer(rhport, TUSB_DIR_IN_MASK | 0x00, NULL, 0, false); // DCD can only set address after status for this request is complete. // do it at dcd_edpt0_status_complete() @@ -293,7 +293,11 @@ static void handle_ctr_tx(uint32_t ep_id) { return; } xfer->iso_in_sending = false; +#if FSDEV_USE_SBUF_ISO == 0 uint8_t buf_id = (ep_reg & USB_EP_DTOG_TX) ? 0 : 1; +#else + uint8_t buf_id = BTABLE_BUF_TX; +#endif btable_set_count(ep_id, buf_id, 0); } @@ -678,6 +682,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet btable_set_addr(ep_idx, 1, pma_addr2); #else btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); + (void) pma_addr2; #endif xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); @@ -773,7 +778,12 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); - if (ep_is_iso(ep_reg)) { +#if FSDEV_USE_SBUF_ISO == 0 + bool const dbl_buf = ep_is_iso(ep_reg); +#else + bool const dbl_buf = false; +#endif + if (dbl_buf) { btable_set_rx_bufsize(ep_idx, 0, cnt); btable_set_rx_bufsize(ep_idx, 1, cnt); } else { @@ -787,7 +797,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const ep_num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); @@ -800,7 +811,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return edpt_xfer(rhport, ep_num, dir); } -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) { +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const ep_num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index f7ee89995..deb1de2a8 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -175,9 +175,9 @@ void dcd_int_enable(uint8_t rhport) { // shared USB/CAN IRQs to separate CAN and USB IRQs. // This dynamically checks if this remap is active to enable the right IRQs. if (CRM->intmap_bit.usbintmap) { - NVIC_DisableIRQ(USBFS_MAPH_IRQn); - NVIC_DisableIRQ(USBFS_MAPL_IRQn); - NVIC_DisableIRQ(USBFSWakeUp_IRQn); + NVIC_EnableIRQ(USBFS_MAPH_IRQn); + NVIC_EnableIRQ(USBFS_MAPL_IRQn); + NVIC_EnableIRQ(USBFSWakeUp_IRQn); } else #endif { diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 95f40269a..30ffadc35 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -200,8 +200,36 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 #include "stm32u0xx.h" + #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_BUS_32BIT + // Disable SBUF_ISO on U0 for now due to bad performance (audio glitching) + #define FSDEV_HAS_SBUF_ISO 0 + #define USB USB_DRD_FS + + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + +#elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + #include "stm32u3xx.h" #define FSDEV_PMA_SIZE (2048u) - #define FSDEV_HAS_SBUF_ISO 1 + #define FSDEV_BUS_32BIT + #define FSDEV_HAS_SBUF_ISO 1 // This is assumed to work but has not been tested... #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX @@ -336,6 +364,8 @@ static const IRQn_Type fsdev_irq[] = { USB_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 USB_DRD_FS_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32U3 + USB_FS_IRQn, #else #error Unknown arch in USB driver #endif diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 9801a485f..d43ea1dc3 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -176,7 +176,7 @@ static void USBC_ForceVbusValidToHigh(void) USBC_Writel(reg_val, USBC_REG_ISCR(USBC0_BASE)); } -void USBC_SelectBus(u32 io_type, u32 ep_type, u32 ep_index) +static void USBC_SelectBus(u32 io_type, u32 ep_type, u32 ep_index) { u32 reg_val = 0; @@ -952,7 +952,7 @@ void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; USBC_REG_set_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); - delay_ms(10); + tusb_time_delay_ms_api(10); USBC_REG_clear_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); } @@ -1082,9 +1082,25 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) musb_int_unmask(); } + #if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + #endif + // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); @@ -1102,8 +1118,9 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; bool ret; // TU_LOG1("X %x %d\r\n", ep_addr, total_bytes); @@ -1210,5 +1227,4 @@ void dcd_int_handler(uint8_t rhport) rxis &= ~TU_BIT(num); } } - #endif diff --git a/src/portable/sunxi/musb_def.h b/src/portable/sunxi/musb_def.h index 53da5ded2..ce9b89d55 100644 --- a/src/portable/sunxi/musb_def.h +++ b/src/portable/sunxi/musb_def.h @@ -26,8 +26,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MUSB_DEF -#define _TUSB_MUSB_DEF +#ifndef TUSB_MUSB_DEF +#define TUSB_MUSB_DEF #define USBC_Readb(reg) (*(volatile unsigned char *)(reg)) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f10f0bdc3..e99cd29c6 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -51,6 +51,7 @@ typedef struct { uint16_t total_len; uint16_t max_size; uint8_t interval; + uint8_t iso_retry; // ISO retry counter } xfer_ctl_t; // This variable is modified from ISR context, so it must be protected by critical section @@ -77,6 +78,7 @@ CFG_TUD_MEM_SECTION static struct { TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { #if TU_CHECK_MCU(OPT_MCU_GD32VF103) + (void) dwc2; return DWC2_EP_MAX; #else const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; @@ -84,6 +86,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc #endif } +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_enabled(dwc2_dep_t* dep) { + return (dep->ctl & EPCTL_EPENA) != 0; +} //-------------------------------------------------------------------- // DMA @@ -116,7 +124,7 @@ static void dma_setup_prepare(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { - if(dwc2->epout[0].doepctl & DOEPCTL_EPENA) { + if(edpt_is_enabled(&dwc2->epout[0])) { return; } } @@ -168,7 +176,7 @@ static void dma_setup_prepare(uint8_t rhport) { - All EP OUT shared a unique OUT FIFO which uses (for Slave or Buffer DMA, Scatt/Gather DMA use different formula): - 13 for setup packets + control words (up to 3 setup packets). - 1 for global NAK (not required/used here). - - Largest-EPsize/4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)" + - Largest-EPsize/4 + 1. (FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)" - 2 for each used OUT endpoint Therefore GRXFSIZ = 13 + 1 + 2 x (Largest-EPsize/4 + 1) + 2 x EPOUTnum @@ -199,7 +207,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { } } else { // Check IN endpoints concurrently active limit - if(dwc2_controller->ep_in_count) { + if(0 != dwc2_controller->ep_in_count) { TU_ASSERT(_dcd_data.allocated_epin_count < dwc2_controller->ep_in_count); _dcd_data.allocated_epin_count++; } @@ -216,10 +224,10 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { // Both TXFD and TXSA are in unit of 32-bit words. if (epnum == 0) { - dwc2->dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos) | _dcd_data.dfifo_top; + dwc2->dieptxf0 = ((uint32_t) fifo_size << DIEPTXF0_TX0FD_Pos) | _dcd_data.dfifo_top; } else { // DIEPTXF starts at FIFO #1. - dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | _dcd_data.dfifo_top; + dwc2->dieptxf[epnum - 1] = ((uint32_t) fifo_size << DIEPTXF_INEPTXFD_Pos) | _dcd_data.dfifo_top; } } @@ -237,10 +245,10 @@ static void dfifo_device_init(uint8_t rhport) { if (is_dma) { _dcd_data.dfifo_top -= 2 * dwc2_controller->ep_count; } - dwc2->gdfifocfg = (_dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top; + dwc2->gdfifocfg = ((uint32_t) _dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top; // Allocate FIFO for EP0 IN - dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); + (void) dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); } @@ -254,7 +262,13 @@ static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = tu_edpt_packet_size(p_endpoint_desc); - xfer->interval = p_endpoint_desc->bInterval; + + const dwc2_dsts_t dsts = {.value = dwc2->dsts}; + if (dsts.enum_speed == DCFG_SPEED_HIGH) { + xfer->interval = 1 << (p_endpoint_desc->bInterval - 1); + } else { + xfer->interval = p_endpoint_desc->bInterval; + } // Endpoint control dwc2_depctl_t depctl = {.value = 0}; @@ -281,17 +295,18 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { const uint8_t dir = tu_edpt_dir(ep_addr); dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; + const uint32_t stall_mask = (stall ? EPCTL_STALL : 0); + if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(dep->diepctl & DIEPCTL_EPENA)) { - dep->diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); + if (!edpt_is_enabled(dep)) { + dep->diepctl |= DIEPCTL_SNAK | stall_mask; } else { // Stop transmitting packets and NAK IN xfers. dep->diepctl |= DIEPCTL_SNAK; while ((dep->diepint & DIEPINT_INEPNE) == 0) {} // Disable the endpoint. - dep->diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); + dep->diepctl |= DIEPCTL_EPDIS | stall_mask; while ((dep->diepint & DIEPINT_EPDISD_Msk) == 0) {} dep->diepint = DIEPINT_EPDISD; @@ -300,9 +315,10 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { // Flush the FIFO, and wait until we have confirmed it cleared. dfifo_flush_tx(dwc2, epnum); } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(dep->doepctl & DOEPCTL_EPENA)) { - dep->doepctl |= stall ? DOEPCTL_STALL : 0; + if (!edpt_is_enabled(dep) || epnum == 0) { + // non-control not-enabled: stall if set + // For EP0 Out, keep it enabled to receive SETUP packets + dep->doepctl |= stall_mask; } else { // Asserting GONAK is required to STALL an OUT endpoint. // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt @@ -312,7 +328,7 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { while ((dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {} // Ditto here disable the endpoint. - dep->doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); + dep->doepctl |= DOEPCTL_EPDIS | stall_mask; while ((dep->doepint & DOEPINT_EPDISD_Msk) == 0) {} dep->doepint = DOEPINT_EPDISD; @@ -323,6 +339,40 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } +static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_dep_t* const epin = &dwc2->ep[0][epnum]; + xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); + + dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; + const uint16_t remain_packets = tsiz.packet_count; + + uint16_t total_bytes_written = 0; + // Process every single packet (only whole packets can be written to fifo) + for (uint16_t i = 0; i < remain_packets; i++) { + tsiz.value = epin->tsiz; + const uint16_t remain_bytes = (uint16_t) tsiz.xfer_size; + const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); + + // Check if dtxfsts has enough space available + if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { + break; + } + + // Push packet to Tx-FIFO + if (xfer->ff) { + volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); + total_bytes_written += xact_bytes; + } else { + dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); + xfer->buffer += xact_bytes; + total_bytes_written += xact_bytes; + } + } + return total_bytes_written; +} + // Since this function returns void, it is not possible to return a boolean success message // We must make sure that this function is not called when the EP is disabled // Must be called from critical section @@ -336,7 +386,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin // EP0 is limited to one packet per xfer if (epnum == 0) { - total_bytes = tu_min16(_dcd_data.ep0_pending[dir], xfer->max_size); + total_bytes = tu_min16(_dcd_data.ep0_pending[dir], CFG_TUD_ENDPOINT0_SIZE); _dcd_data.ep0_pending[dir] -= total_bytes; num_packets = 1; } else { @@ -357,10 +407,10 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin dwc2_depctl_t depctl = {.value = dep->ctl}; depctl.clear_nak = 1; depctl.enable = 1; - if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) { + if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS) { const dwc2_dsts_t dsts = {.value = dwc2->dsts}; const uint32_t odd_now = dsts.frame_number & 1u; - if (odd_now) { + if (odd_now != 0) { depctl.set_data0_iso_even = 1; } else { depctl.set_data1_iso_odd = 1; @@ -374,12 +424,21 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin } dep->diepdma = (uintptr_t) xfer->buffer; dep->diepctl = depctl.value; // enable endpoint + // Advance buffer pointer for EP0 + if (epnum == 0) { + xfer->buffer += total_bytes; + } } else { dep->diepctl = depctl.value; // enable endpoint - // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable if (dir == TUSB_DIR_IN && total_bytes != 0) { - dwc2->diepempmsk |= (1 << epnum); + const uint16_t xferred_bytes = epin_write_tx_fifo(rhport, epnum); + + // Enable TXFE interrupt if there are still data to be sent + // EP0 only sends one packet at a time, so no need to check for EP0 + if ((epnum != 0) && (xfer->total_len - xferred_bytes > 0)) { + dwc2->diepempmsk |= (1u << epnum); + } } } } @@ -402,7 +461,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Set device max speed uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; if (is_highspeed) { - dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; + // dcfg Highspeed's mask is 0 // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) @@ -456,7 +515,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos); // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) { @@ -551,7 +610,7 @@ void dcd_edpt_close_all(uint8_t rhport) { for (uint8_t n = 1; n < ep_count; n++) { for (uint8_t d = 0; d < 2; d++) { dwc2_dep_t* dep = &dwc2->ep[d][n]; - if (dep->ctl & EPCTL_EPENA) { + if (edpt_is_enabled(dep)) { dep->ctl |= EPCTL_SNAK | EPCTL_EPDIS; } xfer_status[n][1-d].max_size = 0; @@ -577,13 +636,14 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpo return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - usbd_spin_lock(false); + usbd_spin_lock(is_isr); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -591,6 +651,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer->buffer = buffer; xfer->ff = NULL; xfer->total_len = total_bytes; + xfer->iso_retry = xfer->interval; // Reset ISO retry counter to interval value // EP0 can only handle one packet if (epnum == 0) { @@ -602,7 +663,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - usbd_spin_unlock(false); + usbd_spin_unlock(is_isr); return ret; } @@ -611,7 +672,8 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 TU_ASSERT(ff->item_size == 1); @@ -620,7 +682,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - usbd_spin_lock(false); + usbd_spin_lock(is_isr); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -628,6 +690,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes; + xfer->iso_retry = xfer->interval; // Reset ISO retry counter to interval value // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode @@ -635,7 +698,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - usbd_spin_unlock(false); + usbd_spin_unlock(is_isr); return ret; } @@ -643,8 +706,12 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); edpt_disable(rhport, ep_addr, true); - if((tu_edpt_number(ep_addr) == 0) && dma_device_enabled(dwc2)) { - dma_setup_prepare(rhport); + + // For control endpoint, prepare to receive SETUP packet + if (tu_edpt_number(ep_addr) == 0) { + if (dma_device_enabled(dwc2)) { + dma_setup_prepare(rhport); + } } } @@ -681,8 +748,9 @@ static void handle_bus_reset(uint8_t rhport) { // Disable all IN endpoints for (uint8_t n = 0; n < ep_count; n++) { - if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { - dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + dwc2_dep_t* dep = &dwc2->epin[n]; + if (edpt_is_enabled(dep)) { + dep->diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; } } @@ -701,12 +769,23 @@ static void handle_bus_reset(uint8_t rhport) { dcfg.address = 0; dwc2->dcfg = dcfg.value; - // Fixed both control EP0 size to 64 bytes - dwc2->epin[0].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); - dwc2->epout[0].ctl &= ~(0x03 << DOEPCTL_MPSIZ_Pos); + // 6. Configure maximum packet size for EP0 + uint8_t mps = 0; + switch (CFG_TUD_ENDPOINT0_SIZE) { + case 8: mps = 3; break; + case 16: mps = 2; break; + case 32: mps = 1; break; + case 64: mps = 0; break; + default: mps = 0; break; + } + + dwc2->epin[0].ctl &= ~DIEPCTL0_MPSIZ_Msk; + dwc2->epout[0].ctl &= ~DOEPCTL0_MPSIZ_Msk; + dwc2->epin[0].ctl |= mps << DIEPCTL0_MPSIZ_Pos; + dwc2->epout[0].ctl |= mps << DOEPCTL0_MPSIZ_Pos; - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; + xfer_status[0][TUSB_DIR_OUT].max_size = CFG_TUD_ENDPOINT0_SIZE; + xfer_status[0][TUSB_DIR_IN].max_size = CFG_TUD_ENDPOINT0_SIZE; if(dma_device_enabled(dwc2)) { dma_setup_prepare(rhport); @@ -714,7 +793,7 @@ static void handle_bus_reset(uint8_t rhport) { dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); } - dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; + dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT | GINTMSK_IISOIXFRM; } static void handle_enum_done(uint8_t rhport) { @@ -796,23 +875,22 @@ static void handle_rxflvl_irq(uint8_t rhport) { const uint16_t byte_count = grxstsp.byte_count; xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if (byte_count) { + if (byte_count != 0) { // Read packet off RxFIFO - if (xfer->ff) { + if (xfer->ff != NULL) { tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; } + } - // short packet, minus remaining bytes (xfer_size) - if (byte_count < xfer->max_size) { - const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; - xfer->total_len -= tsiz.xfer_size; - if (epnum == 0) { - xfer->total_len -= _dcd_data.ep0_pending[TUSB_DIR_OUT]; - _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; - } + // short packet (including ZLP when byte_count == 0), minus remaining bytes (xfer_size) + if (byte_count < xfer->max_size) { + const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; + xfer->total_len -= tsiz.xfer_size; + if (epnum == 0) { + _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; } } break; @@ -824,12 +902,17 @@ static void handle_rxflvl_irq(uint8_t rhport) { // the specified OUT endpoint which will be handled by handle_epout_irq() break; - default: break; + default: break; // nothing to do } } static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { if (doepint_bm.setup_phase_done) { + // Cleanup previous pending EP0 IN transfer if any + dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; + if (edpt_is_enabled(epin0)) { + edpt_disable(rhport, 0x80, false); + } dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); return; } @@ -841,7 +924,6 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe // can is set when GRXSTS_PKTSTS_SETUP_RX is popped therefore they can bet set before/together with setup_phase_done if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { // EP0 can only handle one packet, Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); @@ -858,7 +940,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); if (diepint_bm.xfer_complete) { - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) { + if ((epnum == 0) && (0 != _dcd_data.ep0_pending[TUSB_DIR_IN])) { // EP0 can only handle one packet. Schedule another packet to be transmitted. edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); } else { @@ -869,35 +951,13 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep // TX FIFO empty bit is read-only. It will only be cleared by hardware when written bytes is more than // - 64 bytes or // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) - if (diepint_bm.txfifo_empty && (dwc2->diepempmsk & (1 << epnum))) { - dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; - const uint16_t remain_packets = tsiz.packet_count; - - // Process every single packet (only whole packets can be written to fifo) - for (uint16_t i = 0; i < remain_packets; i++) { - tsiz.value = epin->tsiz; - const uint16_t remain_bytes = (uint16_t) tsiz.xfer_size; - const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); - - // Check if dtxfsts has enough space available - if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { - break; - } - - // Push packet to Tx-FIFO - if (xfer->ff) { - volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); - } else { - dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); - xfer->buffer += xact_bytes; - } - } + if (diepint_bm.txfifo_empty && tu_bit_test(dwc2->diepempmsk, epnum)) { + epin_write_tx_fifo(rhport, epnum); // Turn off TXFE if all bytes are written. - tsiz.value = epin->tsiz; + dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; if (tsiz.xfer_size == 0) { - dwc2->diepempmsk &= ~(1 << epnum); + dwc2->diepempmsk &= ~(1u << epnum); } } } @@ -908,6 +968,11 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi dwc2_regs_t* dwc2 = DWC2_REG(rhport); if (doepint_bm.setup_phase_done) { + // Cleanup previous pending EP0 IN transfer if any + dwc2_dep_t* epin0 = &DWC2_REG(rhport)->epin[0]; + if (edpt_is_enabled(epin0)) { + edpt_disable(rhport, 0x80, false); + } dma_setup_prepare(rhport); dcd_dcache_invalidate(_dcd_usbbuf.setup_packet, 8); dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); @@ -971,7 +1036,7 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { // DAINT for a given EP clears when DEPINTx is cleared. // EPINT will be cleared when DAINT bits are cleared. for (uint8_t epnum = 0; epnum < ep_count; epnum++) { - if (dwc2->daint & TU_BIT(daint_offset + epnum)) { + if (tu_bit_test(dwc2->daint,daint_offset + epnum)) { dwc2_dep_t* epout = &ep_base[epnum]; union { uint32_t value; @@ -980,7 +1045,7 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { } intr; intr.value = epout->intr; - epout->intr = intr.value; // Clear interrupt + epout->intr = intr.value; // Clear interrupt //-V::2584::{otg_int} if (is_dma) { #if CFG_TUD_DWC2_DMA_ENABLE @@ -1003,6 +1068,43 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { } } +static void handle_incomplete_iso_in(uint8_t rhport) { + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + const dwc2_dsts_t dsts = {.value = dwc2->dsts}; + const uint32_t odd_now = dsts.frame_number & 1u; + + // Loop over all IN endpoints + const uint8_t ep_count = dwc2_ep_count(dwc2); + for (uint8_t epnum = 0; epnum < ep_count; epnum++) { + dwc2_dep_t *epin = &dwc2->epin[epnum]; + dwc2_depctl_t depctl = {.value = epin->diepctl}; + // Read DSTS and DIEPCTLn for all isochronous endpoints. If the current EP is enabled and the read value of + // DSTS.SOFFN is the targeted uframe number for this EP, then this EP has an incomplete transfer. + if (depctl.enable && depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && depctl.dpid_iso_odd == odd_now) { + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); + if (xfer->iso_retry > 0) { + xfer->iso_retry--; + // Restart ISO transfe: re-write TSIZ and CTL + dwc2_ep_tsize_t deptsiz = {.value = 0}; + deptsiz.xfer_size = xfer->total_len; + deptsiz.packet_count = tu_div_ceil(xfer->total_len, xfer->max_size); + epin->tsiz = deptsiz.value; + + if (odd_now) { + depctl.set_data0_iso_even = 1; + } else { + depctl.set_data1_iso_odd = 1; + } + epin->diepctl = depctl.value; + } else { + // too many retries, give up + edpt_disable(rhport, epnum | TUSB_DIR_IN_MASK, false); + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, 0, XFER_RESULT_FAILED, true); + } + } + } +} + /* Interrupt Hierarchy DIEPINT DIEPINT \ / @@ -1032,6 +1134,8 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_ENUMDNE) { // ENUMDNE is the end of reset where speed of the link is detected dwc2->gintsts = GINTSTS_ENUMDNE; + // There may be a pending suspend event, so we clear it first + dwc2->gintsts = GINTSTS_USBSUSP; dwc2->gintmsk |= GINTMSK_USBSUSPM; handle_enum_done(rhport); } @@ -1100,6 +1204,12 @@ void dcd_int_handler(uint8_t rhport) { // IEPINT bit read-only, clear using DIEPINTn handle_ep_irq(rhport, TUSB_DIR_IN); } + + // Incomplete isochronous IN transfer interrupt handling. + if (gintsts & GINTSTS_IISOIXFR) { + dwc2->gintsts = GINTSTS_IISOIXFR; + handle_incomplete_iso_in(rhport); + } } #if CFG_TUD_TEST_MODE diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 37b6592c4..513495eb1 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -64,58 +64,59 @@ #endif #ifdef __cplusplus - extern "C" { +extern "C" { #endif - static const dwc2_controller_t _dwc2_controller[] = { -{.reg_base = DWC2_OTG1_REG_BASE, .irqnum = OTG1_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG1_FIFO_SIZE}, +static const dwc2_controller_t _dwc2_controller[] = { + {.reg_base = DWC2_OTG1_REG_BASE, .irqnum = OTG1_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG1_FIFO_SIZE}, #if defined DWC2_OTG2_REG_BASE - {.reg_base = DWC2_OTG2_REG_BASE, .irqnum = OTG2_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG2_FIFO_SIZE} + {.reg_base = DWC2_OTG2_REG_BASE, .irqnum = OTG2_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG2_FIFO_SIZE} #endif - }; +}; - TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { - (void) role; - const IRQn_Type irqn = (IRQn_Type) _dwc2_controller[rhport].irqnum; - if (enabled) { - NVIC_EnableIRQ(irqn); - } else { - NVIC_DisableIRQ(irqn); - } - } +TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { + (void) role; + const IRQn_Type irqn = (IRQn_Type) _dwc2_controller[rhport].irqnum; + if (enabled) { + NVIC_EnableIRQ(irqn); + } else { + NVIC_DisableIRQ(irqn); + } +} - TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum); - } +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { + NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum); +} - TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable(uint8_t rhport) { - NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum); - } +TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable(uint8_t rhport) { + NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum); +} - TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { - // try to delay for 1 ms - uint32_t count = system_core_clock / 1000; - while (count--) __asm volatile("nop"); - } +TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { + // try to delay for 1 ms + uint32_t count = system_core_clock / 1000; + while (count--) __asm volatile("nop"); +} - // MCU specific PHY init, called BEFORE core reset - TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { - (void) dwc2; - // Enable on-chip HS PHY - if (hs_phy_type == GHWCFG2_HSPHY_UTMI || hs_phy_type == GHWCFG2_HSPHY_UTMI_ULPI) { - } else if (hs_phy_type == GHWCFG2_HSPHY_NOT_SUPPORTED) { - } - } +// MCU specific PHY init, called BEFORE core reset +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { + (void) dwc2; + // Enable on-chip HS PHY + if (hs_phy_type == GHWCFG2_HSPHY_UTMI || hs_phy_type == GHWCFG2_HSPHY_UTMI_ULPI) { + } else if (hs_phy_type == GHWCFG2_HSPHY_NOT_SUPPORTED) { + } +} - // MCU specific PHY update, it is called AFTER init() and core reset - TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { - (void) dwc2; - (void) hs_phy_type; +// MCU specific PHY update, it is called AFTER init() and core reset +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { + (void) dwc2; + (void) hs_phy_type; - dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN | STM32_GCCFG_DCDEN | STM32_GCCFG_PDEN; - } + dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN | STM32_GCCFG_DCDEN | STM32_GCCFG_PDEN; +} #ifdef __cplusplus } #endif -#endif /* DWC2_GD32_H_ */ +#endif /* DWC2_AT32_H_ */ diff --git a/src/portable/synopsys/dwc2/dwc2_bcm.h b/src/portable/synopsys/dwc2/dwc2_bcm.h index e5824606a..df6d4a852 100644 --- a/src/portable/synopsys/dwc2/dwc2_bcm.h +++ b/src/portable/synopsys/dwc2/dwc2_bcm.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DWC2_BCM_H_ -#define _TUSB_DWC2_BCM_H_ +#ifndef TUSB_DWC2_BCM_H_ +#define TUSB_DWC2_BCM_H_ #ifdef __cplusplus extern "C" { diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 5ff18ab94..980574e12 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -29,16 +29,6 @@ #define DWC2_COMMON_DEBUG 2 #if defined(TUP_USBIP_DWC2) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED) - -#if CFG_TUD_ENABLED -#include "device/dcd.h" -#endif - -#if CFG_TUH_ENABLED -#include "host/hcd.h" -#include "host/usbh.h" -#endif - #include "dwc2_common.h" //-------------------------------------------------------------------- diff --git a/src/portable/synopsys/dwc2/dwc2_common.h b/src/portable/synopsys/dwc2/dwc2_common.h index 33219f786..428304ba9 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.h +++ b/src/portable/synopsys/dwc2/dwc2_common.h @@ -30,6 +30,14 @@ #include "common/tusb_common.h" #include "dwc2_type.h" +#if CFG_TUD_ENABLED +#include "device/dcd.h" +#endif + +#if CFG_TUH_ENABLED +#include "host/hcd.h" +#endif + // Following symbols must be defined by port header // - _dwc2_controller[]: array of controllers // - DWC2_EP_MAX: largest EP counts of all controllers @@ -51,6 +59,8 @@ #include "dwc2_xmc.h" #elif defined(TUP_USBIP_DWC2_AT32) #include "dwc2_at32.h" +#elif defined(TUP_USBIP_DWC2_NRF) + #include "dwc2_nrf.h" #else #error "Unsupported MCUs" #endif @@ -84,13 +94,13 @@ void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr); TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_tx(dwc2_regs_t* dwc2, uint8_t fnum) { // flush TX fifo and wait for it cleared dwc2->grstctl = GRSTCTL_TXFFLSH | (fnum << GRSTCTL_TXFNUM_Pos); - while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {} + while (0 != (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk)) {} } TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) { // flush RX fifo and wait for it cleared dwc2->grstctl = GRSTCTL_RXFFLSH; - while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {} + while (0 != (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk)) {} } void dfifo_read_packet(dwc2_regs_t* dwc2, uint8_t* dst, uint16_t len); diff --git a/src/portable/synopsys/dwc2/dwc2_nrf.h b/src/portable/synopsys/dwc2/dwc2_nrf.h new file mode 100644 index 000000000..b93571f16 --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_nrf.h @@ -0,0 +1,61 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 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 TUSB_DWC2_NRF_H +#define TUSB_DWC2_NRF_H + +#include "nrf.h" + +#define DWC2_EP_MAX 16 + +static const dwc2_controller_t _dwc2_controller[] = { + { .reg_base = NRF_USBHSCORE0_NS_BASE, .irqnum = USBHS_IRQn, .ep_count = 16, .ep_fifo_size = 12288 }, +}; + +TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { + (void) rhport; + (void) role; + (void) enabled; +} + +#define dwc2_dcd_int_enable(_rhport) dwc2_int_set(_rhport, TUSB_ROLE_DEVICE, true) +#define dwc2_dcd_int_disable(_rhport) dwc2_int_set(_rhport, TUSB_ROLE_DEVICE, false) + +TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { +} + +// MCU specific PHY init, called BEFORE core reset +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { + (void)dwc2; + (void)hs_phy_type; +} + +// MCU specific PHY update, it is called AFTER init() and core reset +TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { + (void)dwc2; + (void)hs_phy_type; +} + +#endif diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 08950ccc0..9da8de41f 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -176,7 +176,9 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_ TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // try to delay for 1 ms uint32_t count = SystemCoreClock / 1000; - while (count--) __NOP(); + while (count--) { + __NOP(); + } } // MCU specific PHY init, called BEFORE core reset diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 0a8dacf5f..7693ce02a 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -92,6 +92,16 @@ enum { }; enum { + GUSBCFG_PHYSEL_HIGHSPEED = 0, + GUSBCFG_PHYSEL_FULLSPEED = 1, +}; + +enum { + GUSBCFG_PHYHS_UTMI = 0, + GUSBCFG_PHYHS_ULPI = 1, +}; + +enum { GHWCFG2_OPMODE_HNP_SRP = 0, GHWCFG2_OPMODE_SRP = 1, GHWCFG2_OPMODE_NON_HNP_NON_SRP = 2, @@ -1435,7 +1445,7 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define DAINTMSK_OEPM_Msk (0xFFFFUL << DAINTMSK_OEPM_Pos) // 0xFFFF0000 #define DAINTMSK_OEPM DAINTMSK_OEPM_Msk // OUT EP interrupt mask bits -#define DAINT_SHIFT(_dir) ((_dir == TUSB_DIR_IN) ? 0 : 16) +#define DAINT_SHIFT(_dir) (((_dir) == TUSB_DIR_IN) ? 0 : 16) #if 0 /******************** Bit definition for OTG register ********************/ @@ -1847,6 +1857,9 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define HPTXFSIZ_PTXFD HPTXFSIZ_PTXFD_Msk // Host periodic TxFIFO depth /******************** Bit definition for DIEPCTL register ********************/ +#define DIEPCTL0_MPSIZ_Pos (0U) +#define DIEPCTL0_MPSIZ_Msk (0x3UL << DIEPCTL0_MPSIZ_Pos) // 0x00000003 +#define DIEPCTL0_MPSIZ DIEPCTL0_MPSIZ_Msk // Maximum packet size(endpoint 0) #define DIEPCTL_MPSIZ_Pos (0U) #define DIEPCTL_MPSIZ_Msk (0x7FFUL << DIEPCTL_MPSIZ_Pos) // 0x000007FF #define DIEPCTL_MPSIZ DIEPCTL_MPSIZ_Msk // Maximum packet size @@ -2155,6 +2168,9 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define EPCTL_EPENA EPCTL_EPENA_Msk // Endpoint enable /******************** Bit definition for DOEPCTL register ********************/ +#define DOEPCTL0_MPSIZ_Pos (0U) +#define DOEPCTL0_MPSIZ_Msk (0x3UL << DOEPCTL0_MPSIZ_Pos) // 0x00000003 +#define DOEPCTL0_MPSIZ DOEPCTL0_MPSIZ_Msk // Maximum packet size(endpoint 0) #define DOEPCTL_MPSIZ_Pos (0U) #define DOEPCTL_MPSIZ_Msk (0x7FFUL << DOEPCTL_MPSIZ_Pos) // 0x000007FF #define DOEPCTL_MPSIZ DOEPCTL_MPSIZ_Msk // Maximum packet size //Bit 1 diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 257fa2833..b92448685 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -32,19 +32,19 @@ #error DWC2 require either CFG_TUH_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled #endif -// Debug level for DWC2 -#define DWC2_DEBUG 2 - #include "host/hcd.h" #include "host/usbh.h" #include "dwc2_common.h" -// Max number of endpoints application can open, can be larger than DWC2_CHANNEL_COUNT_MAX -#ifndef CFG_TUH_DWC2_ENDPOINT_MAX -#define CFG_TUH_DWC2_ENDPOINT_MAX 16 -#endif + // Debug level for DWC2 + #define DWC2_DEBUG 2 -#define DWC2_CHANNEL_COUNT_MAX 16 // absolute max channel count + // Max number of endpoints application can open, can be larger than DWC2_CHANNEL_COUNT_MAX + #ifndef CFG_TUH_DWC2_ENDPOINT_MAX + #define CFG_TUH_DWC2_ENDPOINT_MAX 16u + #endif + + #define DWC2_CHANNEL_COUNT_MAX 16u // absolute max channel count TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); enum { @@ -79,7 +79,8 @@ typedef struct { uint32_t speed : 2; uint32_t next_pid : 2; // PID for next transfer uint32_t next_do_ping : 1; // Do PING for next transfer if possible (highspeed OUT) - // uint32_t : 9; + uint32_t closing : 1; // endpoint is closing + // uint32_t : 8; }; uint32_t uframe_countdown; // micro-frame count down to transfer for periodic, only need 18-bit @@ -96,6 +97,7 @@ typedef struct { uint8_t err_count : 3; uint8_t period_split_nyet_count : 3; uint8_t halted_nyet : 1; + uint8_t closing : 1; // closing channel }; uint8_t result; @@ -195,8 +197,21 @@ TU_ATTR_ALWAYS_INLINE static inline void channel_dealloc(dwc2_regs_t* dwc2, uint } TU_ATTR_ALWAYS_INLINE static inline bool channel_disable(const dwc2_regs_t* dwc2, dwc2_channel_t* channel) { - // disable also require request queue - TU_ASSERT(req_queue_avail(dwc2, channel_is_periodic(channel->hcchar))); + const bool is_period = channel_is_periodic(channel->hcchar); + if (dma_host_enabled(dwc2)) { + // In buffer DMA or external DMA mode: + // - Channel disable must not be programmed for non-split periodic channels. At the end of the next uframe/frame (in + // the worst case), the controller generates a channel halted and disables the channel automatically. + // - For split enabled channels (both non-periodic and periodic), channel disable must not be programmed randomly. + // However, channel disable can be programmed for specific scenarios such as NAK and FrmOvrn. + if (is_period && (channel->hcsplt & HCSPLT_SPLITEN)) { + return true; + } + } else { + while (0 == req_queue_avail(dwc2, is_period)) { + // blocking wait for request queue available + } + } channel->hcintmsk |= HCINT_HALTED; channel->hcchar |= HCCHAR_CHDIS | HCCHAR_CHENA; // must set both CHDIS and CHENA return true; @@ -204,7 +219,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool channel_disable(const dwc2_regs_t* dwc2 // attempt to send IN token to receive data TU_ATTR_ALWAYS_INLINE static inline bool channel_send_in_token(const dwc2_regs_t* dwc2, dwc2_channel_t* channel) { - TU_ASSERT(req_queue_avail(dwc2, channel_is_periodic(channel->hcchar))); + while (0 == req_queue_avail(dwc2, channel_is_periodic(channel->hcchar))) { + // blocking wait for request queue available + } channel->hcchar |= HCCHAR_CHENA; return true; } @@ -237,13 +254,37 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t edpt_alloc(void) { return TUSB_INDEX_INVALID_8; } -// Find a endpoint that is opened previously with hcd_edpt_open() +TU_ATTR_ALWAYS_INLINE static inline void edpt_dealloc(hcd_endpoint_t *edpt) { + edpt->hcchar_bm.enable = 0; +} + +// close an opened endpoint +static void edpt_close(dwc2_regs_t *dwc2, uint8_t ep_id) { + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + edpt->closing = 1; // mark endpoint as closing + + // disable active channel belong to this endpoint + for (uint8_t ch_id = 0; ch_id < DWC2_CHANNEL_COUNT_MAX; ch_id++) { + hcd_xfer_t *xfer = &_hcd_data.xfer[ch_id]; + if (xfer->allocated && xfer->ep_id == ep_id) { + dwc2_channel_t *channel = &dwc2->channel[ch_id]; + xfer->closing = 1; + channel_disable(dwc2, channel); + return; // only 1 active channel per endpoint + } + } + + edpt_dealloc(edpt); // no active channel, safe to de-alloc now +} + +// Find an endpoint that is opened previously with hcd_edpt_open() // Note: EP0 is bidirectional TU_ATTR_ALWAYS_INLINE static inline uint8_t edpt_find_opened(uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir) { for (uint8_t i = 0; i < (uint8_t)CFG_TUH_DWC2_ENDPOINT_MAX; i++) { - const dwc2_channel_char_t* hcchar_bm = &_hcd_data.edpt[i].hcchar_bm; - if (hcchar_bm->enable && hcchar_bm->dev_addr == dev_addr && - hcchar_bm->ep_num == ep_num && (ep_num == 0 || hcchar_bm->ep_dir == ep_dir)) { + const hcd_endpoint_t *edpt = &_hcd_data.edpt[i]; + const dwc2_channel_char_t hcchar_bm = edpt->hcchar_bm; + if (hcchar_bm.enable && hcchar_bm.dev_addr == dev_addr && hcchar_bm.ep_num == ep_num && + (ep_num == 0 || hcchar_bm.ep_dir == ep_dir)) { return i; } } @@ -259,8 +300,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t cal_packet_count(uint16_t len, uint } TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t packet_count) { - if (packet_count & 0x01) { - return pid ^ 0x02; // toggle DATA0 and DATA1 + if (packet_count & 0x01u) { + return pid ^ 0x02u; // toggle DATA0 and DATA1 } else { return pid; } @@ -456,11 +497,11 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) { // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - for (uint8_t i = 0; i < (uint8_t) CFG_TUH_DWC2_ENDPOINT_MAX; i++) { - hcd_endpoint_t* edpt = &_hcd_data.edpt[i]; + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + for (uint8_t ep_id = 0; ep_id < CFG_TUH_DWC2_ENDPOINT_MAX; ep_id++) { + const hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; if (edpt->hcchar_bm.enable && edpt->hcchar_bm.dev_addr == dev_addr) { - tu_memclr(edpt, sizeof(hcd_endpoint_t)); + edpt_close(dwc2, ep_id); } } } @@ -503,25 +544,39 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* edpt->speed = bus_info.speed; edpt->next_pid = HCTSIZ_PID_DATA0; - if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { - edpt->uframe_interval = 1 << (desc_ep->bInterval - 1); - if (bus_info.speed == TUSB_SPEED_FULL) { - edpt->uframe_interval <<= 3; - } - } else if (desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) { - if (bus_info.speed == TUSB_SPEED_HIGH) { + switch (desc_ep->bmAttributes.xfer) { + case TUSB_XFER_ISOCHRONOUS: edpt->uframe_interval = 1 << (desc_ep->bInterval - 1); - } else { - edpt->uframe_interval = desc_ep->bInterval << 3; - } + if (bus_info.speed == TUSB_SPEED_FULL) { + edpt->uframe_interval <<= 3; + } + break; + + case TUSB_XFER_INTERRUPT: + if (bus_info.speed == TUSB_SPEED_HIGH) { + edpt->uframe_interval = 1 << (desc_ep->bInterval - 1); + } else { + edpt->uframe_interval = desc_ep->bInterval << 3; + } + break; + + default: + break; } return true; } bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { - (void) rhport; (void) daddr; (void) ep_addr; - return false; // TODO not implemented yet + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_dir = tu_edpt_dir(ep_addr); + const uint8_t ep_id = edpt_find_opened(daddr, ep_num, ep_dir); + TU_ASSERT(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); + + edpt_close(dwc2, ep_id); + + return true; } // clean up channel after part of transfer is done but the whole urb is not complete @@ -590,8 +645,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { channel->hcint = 0xFFFFFFFFU; // clear all channel interrupts if (dma_host_enabled(dwc2)) { - uint32_t hcintmsk = HCINT_HALTED; - channel->hcintmsk = hcintmsk; + channel->hcintmsk = HCINT_HALTED; dwc2->haintmsk |= TU_BIT(ch_id); channel->hcdma = (uint32_t) edpt->buffer; @@ -646,7 +700,6 @@ static bool edpt_xfer_kickoff(dwc2_regs_t* dwc2, uint8_t ep_id) { return channel_xfer_start(dwc2, ch_id); } -// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const uint8_t ep_num = tu_edpt_number(ep_addr); @@ -654,7 +707,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * uint8_t ep_id = edpt_find_opened(dev_addr, ep_num, ep_dir); TU_ASSERT(ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); - hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + TU_VERIFY(edpt->closing == 0); // skip if endpoint is closing edpt->buffer = buffer; edpt->buflen = buflen; @@ -754,7 +808,7 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci edpt->next_pid = hctsiz.pid; // save PID edpt->uframe_countdown = edpt->uframe_interval - ucount; // enable SOF interrupt if not already enabled - if (!(dwc2->gintmsk & GINTMSK_SOFM)) { + if (0 == (dwc2->gintmsk & GINTMSK_SOFM)) { dwc2->gintsts = GINTSTS_SOF; dwc2->gintmsk |= GINTMSK_SOFM; } @@ -801,7 +855,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; - if (byte_count) { + if (byte_count > 0) { dfifo_read_packet(dwc2, edpt->buffer + xfer->xferred_bytes, byte_count); xfer->xferred_bytes += byte_count; xfer->fifo_bytes = byte_count; @@ -837,8 +891,8 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { dwc2_channel_t* channel = &dwc2->channel[ch_id]; const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; // skip writing to FIFO if channel is expecting halted. - if (!(channel->hcintmsk & HCINT_HALTED) && (hcchar.ep_dir == TUSB_DIR_OUT)) { - hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; + if (0 == (channel->hcintmsk & HCINT_HALTED) && (hcchar.ep_dir == TUSB_DIR_OUT)) { + hcd_xfer_t *xfer = &_hcd_data.xfer[ch_id]; TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; @@ -899,6 +953,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (hcint & HCINT_XACT_ERR) { xfer->err_count++; channel->hcintmsk |= HCINT_ACK; + } else { + // nothing to do } channel_disable(dwc2, channel); @@ -910,7 +966,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h channel_disable(dwc2, channel); } else if (hcint & HCINT_NAK) { // NAK received, disable channel to flush all posted request and try again - if (hcsplt.split_en) { + if (hcsplt.split_en == 1u) { hcsplt.split_compl = 0; // restart with start-split channel->hcsplt = hcsplt.value; } @@ -919,8 +975,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (hcint & HCINT_ACK) { xfer->err_count = 0; - if (hcsplt.split_en) { - if (!hcsplt.split_compl) { + if (hcsplt.split_en == 1u) { + if (hcsplt.split_compl == 0) { // start split is ACK --> do complete split channel->hcintmsk |= HCINT_NYET; hcsplt.split_compl = 1; @@ -932,7 +988,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else { // ACK with data const uint16_t remain_packets = hctsiz.packet_count; - if (remain_packets) { + if (remain_packets > 0) { // still more packet to receive, also reset to start split hcsplt.split_compl = 0; channel->hcsplt = hcsplt.value; @@ -945,6 +1001,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h is_done = true; } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; + is_done = true; + } else if (xfer->closing == 1) { is_done = true; } else { // got here due to NAK or NYET @@ -953,6 +1011,8 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } else if (hcint & HCINT_DATATOGGLE_ERR) { xfer->err_count = 0; TU_ASSERT(false); + } else { + // nothing to do } return is_done; } @@ -977,7 +1037,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t channel_disable(dwc2, channel); } else if (hcint & HCINT_NYET) { xfer->err_count = 0; - if (hcsplt.split_en) { + if (hcsplt.split_en == 1u) { // retry complete split hcsplt.split_compl = 1; channel->hcsplt = hcsplt.value; @@ -1005,6 +1065,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t is_done = true; } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; + is_done = true; + } else if (xfer->closing == 1) { is_done = true; } else { // Got here due to NAK or NYET @@ -1013,8 +1075,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t } else if (hcint & HCINT_ACK) { xfer->err_count = 0; channel->hcintmsk &= ~HCINT_ACK; - if (hcsplt.split_en) { - if (!hcsplt.split_compl) { + if (hcsplt.split_en == 1u) { + if (hcsplt.split_compl == 0) { // ACK for start split --> do complete split hcsplt.split_compl = 1; channel->hcsplt = hcsplt.value; @@ -1026,6 +1088,8 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t channel->hctsiz &= ~HCTSIZ_DOPING; // HC already cleared PING bit, but we clear anyway channel->hcchar |= HCCHAR_CHENA; } + } else { + // nothing to do } if (is_done) { @@ -1122,6 +1186,10 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci // retry start-split in next binterval channel_xfer_in_retry(dwc2, ch_id, hcint); } + + if (xfer->closing == 1) { + is_done = true; + } } return is_done; @@ -1131,7 +1199,6 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; - const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; bool is_done = false; @@ -1183,6 +1250,10 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc channel->hcchar |= HCCHAR_CHENA; } } + + if (xfer->closing == 1) { + is_done = true; + } } else if (hcint & HCINT_ACK) { xfer->err_count = 0; channel->hcintmsk &= ~HCINT_ACK; @@ -1227,12 +1298,17 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { } else { is_done = handle_channel_in_slave(dwc2, ch_id, hcint); } - #endif + #endif } if (is_done) { - const uint8_t ep_addr = tu_edpt_addr(hcchar.ep_num, hcchar.ep_dir); - hcd_event_xfer_complete(hcchar.dev_addr, ep_addr, xfer->xferred_bytes, (xfer_result_t)xfer->result, in_isr); + if (xfer->closing == 1) { + hcd_endpoint_t *edpt = &_hcd_data.edpt[xfer->ep_id]; + edpt_dealloc(edpt); + } else { + const uint8_t ep_addr = tu_edpt_addr(hcchar.ep_num, hcchar.ep_dir); + hcd_event_xfer_complete(hcchar.dev_addr, ep_addr, xfer->xferred_bytes, (xfer_result_t)xfer->result, in_isr); + } channel_dealloc(dwc2, ch_id); } } @@ -1251,16 +1327,18 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) { const uint32_t ucount = (hprt_speed_get(dwc2) == TUSB_SPEED_HIGH ? 1 : 8); for(uint8_t ep_id = 0; ep_id < CFG_TUH_DWC2_ENDPOINT_MAX; ep_id++) { - hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - if (edpt->hcchar_bm.enable && channel_is_periodic(edpt->hcchar) && edpt->uframe_countdown > 0) { - edpt->uframe_countdown -= tu_min32(ucount, edpt->uframe_countdown); - if (edpt->uframe_countdown == 0) { - if (!edpt_xfer_kickoff(dwc2, ep_id)) { - edpt->uframe_countdown = ucount; // failed to start, try again next frame + hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id]; + if (edpt->closing == 0) { + if (edpt->hcchar_bm.enable && channel_is_periodic(edpt->hcchar) && edpt->uframe_countdown > 0) { + edpt->uframe_countdown -= tu_min32(ucount, edpt->uframe_countdown); + if (edpt->uframe_countdown == 0) { + if (!edpt_xfer_kickoff(dwc2, ep_id)) { + edpt->uframe_countdown = ucount; // failed to start, try again next frame + } } - } - more_isr = true; + more_isr = true; + } } } @@ -1272,9 +1350,9 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { uint32_t hcfg = dwc2->hcfg & ~HCFG_FSLS_PHYCLK_SEL; const dwc2_gusbcfg_t gusbcfg = {.value = dwc2->gusbcfg}; - uint32_t phy_clock; + uint32_t phy_clock; - if (gusbcfg.phy_sel) { + if (gusbcfg.phy_sel == GUSBCFG_PHYSEL_FULLSPEED) { phy_clock = 48; // dedicated FS is 48Mhz if (speed == TUSB_SPEED_LOW) { hcfg |= HCFG_FSLS_PHYCLK_SEL_6MHZ; @@ -1282,7 +1360,7 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ; } } else { - if (gusbcfg.ulpi_utmi_sel) { + if (gusbcfg.ulpi_utmi_sel == GUSBCFG_PHYHS_ULPI) { phy_clock = 60; // ULPI 8-bit is 60Mhz } else { // UTMI+ 16-bit is 30Mhz, 8-bit is 60Mhz @@ -1321,20 +1399,20 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { const dwc2_hprt_t hprt_bm = {.value = dwc2->hprt}; uint32_t hprt = hprt_bm.value & ~HPRT_W1_MASK; - if (hprt_bm.conn_detected) { + if (hprt_bm.conn_detected == 1u) { // Port Connect Detect hprt |= HPRT_CONN_DETECT; - if (hprt_bm.conn_status) { + if (hprt_bm.conn_status == 1u) { hcd_event_device_attach(rhport, in_isr); } } - if (hprt_bm.enable_change) { + if (hprt_bm.enable_change == 1u) { // Port enable change hprt |= HPRT_ENABLE_CHANGE; - if (hprt_bm.enable) { + if (hprt_bm.enable == 1u) { // Port enable const tusb_speed_t speed = hprt_speed_get(dwc2); port0_enable(dwc2, speed); @@ -1393,7 +1471,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { // Device disconnected dwc2->gintsts = GINTSTS_DISCINT; - if (!(dwc2->hprt & HPRT_CONN_STATUS)) { + if (0 == (dwc2->hprt & HPRT_CONN_STATUS)) { hcd_event_device_remove(rhport, in_isr); } } diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 3738ac0cb..90c672d19 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -113,7 +113,8 @@ void dcd_edpt_close_all (uint8_t rhport) { } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; (void) ep_addr; (void) buffer; @@ -122,7 +123,8 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } // Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) { +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; (void) ep_addr; (void) ff; diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index 64cbc5087..5f4b139d8 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -219,7 +219,7 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) USBFUNADR = dev_addr; // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) @@ -333,19 +333,29 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; } +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; +} + + void dcd_edpt_close_all (uint8_t rhport) { (void) rhport; // TODO implement dcd_edpt_close_all() } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -393,8 +403,9 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } #if 0 // TODO support dcd_edpt_xfer_fifo API -bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -821,5 +832,4 @@ void dcd_int_handler(uint8_t rhport) } } - #endif diff --git a/src/portable/valentyusb/eptri/dcd_eptri.c b/src/portable/valentyusb/eptri/dcd_eptri.c index a03c94558..1b555b3b7 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.c +++ b/src/portable/valentyusb/eptri/dcd_eptri.c @@ -375,7 +375,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { // Respond with ACK status first before changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); // Wait for the response packet to get sent while (tx_active) @@ -438,9 +438,17 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; (void) ep_addr; - // TODO implement dcd_edpt_close() +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } void dcd_edpt_close_all (uint8_t rhport) @@ -475,8 +483,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) // IN endpoints will get un-stalled when more data is written. } -bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void)rhport; uint8_t ep_num = tu_edpt_number(ep_addr); uint8_t ep_dir = tu_edpt_dir(ep_addr); @@ -659,5 +668,4 @@ void dcd_int_handler(uint8_t rhport) } } } - #endif diff --git a/src/portable/valentyusb/eptri/dcd_eptri.h b/src/portable/valentyusb/eptri/dcd_eptri.h index d67635d7c..2fe74a712 100644 --- a/src/portable/valentyusb/eptri/dcd_eptri.h +++ b/src/portable/valentyusb/eptri/dcd_eptri.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_DCD_VALENTYUSB_EPTRI_H_ -#define _TUSB_DCD_VALENTYUSB_EPTRI_H_ +#ifndef TUSB_DCD_VALENTYUSB_EPTRI_H_ +#define TUSB_DCD_VALENTYUSB_EPTRI_H_ #include "common/tusb_common.h" #ifdef __cplusplus @@ -36,4 +36,4 @@ } #endif -#endif /* _TUSB_DCD_VALENTYUSB_EPTRI_H_ */ +#endif /* TUSB_DCD_VALENTYUSB_EPTRI_H_ */ diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index c248ba14e..5cd25e33e 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -218,7 +218,7 @@ void dcd_int_disable(uint8_t rhport) { void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) dev_addr; - dcd_edpt_xfer(rhport, 0x80, NULL, 0); // zlp status response + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); // zlp status response } void dcd_remote_wakeup(uint8_t rhport) { @@ -283,13 +283,21 @@ void dcd_edpt_close_all(uint8_t rhport) { // TODO optional } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void) rhport; (void) ep_addr; - // TODO optional + (void)largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; + return false; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t ep = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); @@ -344,5 +352,4 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { } } } - #endif diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 4a208b9df..11734de37 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -27,13 +27,14 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && defined(CFG_TUD_WCH_USBIP_USBHS) && CFG_TUD_WCH_USBIP_USBHS -#include "ch32_usbhs_reg.h" +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && defined(CFG_TUD_WCH_USBIP_USBHS) && \ + (CFG_TUD_WCH_USBIP_USBHS == 1) + #include "ch32_usbhs_reg.h" -#include "device/dcd.h" + #include "device/dcd.h" -// Max number of bi-directional endpoints including EP0 -#define EP_MAX 16 + // Max number of bi-directional endpoints including EP0 + #define EP_MAX 16 typedef struct { uint8_t* buffer; @@ -203,7 +204,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void) dev_addr; // Response with zlp status - dcd_edpt_xfer(rhport, 0x80, NULL, 0); + dcd_edpt_xfer(rhport, 0x80, NULL, 0, false); } void dcd_remote_wakeup(uint8_t rhport) { @@ -288,6 +289,21 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { } } + #if 0 +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { + (void) rhport; + (void) ep_addr; + (void) largest_packet_size; + return false; +} + +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { + (void) rhport; + (void) desc_ep; + return false; +} + #endif + void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void) rhport; @@ -315,7 +331,8 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { } } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) { + (void) is_isr; (void) rhport; uint8_t const ep_num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); @@ -419,5 +436,4 @@ void dcd_int_handler(uint8_t rhport) { USBHSD->INT_FG = USBHS_SUSPEND_FLAG; /* Clear flag */ } } - #endif diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 200136906..7bbf122dd 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -36,7 +36,17 @@ #include "bsp/board_api.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #include "ch32v20x.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "ch32v20x_usb.h" #define USBFS_RX_BUF_LEN 64 diff --git a/src/tinyusb.mk b/src/tinyusb.mk index a9f623c24..8f9d52de9 100644 --- a/src/tinyusb.mk +++ b/src/tinyusb.mk @@ -12,6 +12,7 @@ TINYUSB_SRC_C += \ src/class/hid/hid_device.c \ src/class/midi/midi_device.c \ src/class/msc/msc_device.c \ + src/class/mtp/mtp_device.c \ src/class/net/ecm_rndis_device.c \ src/class/net/ncm_device.c \ src/class/usbtmc/usbtmc_device.c \ diff --git a/src/tusb.c b/src/tusb.c index 083e6d861..3852da76b 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -117,11 +117,15 @@ bool tusb_inited(void) { bool ret = false; #if CFG_TUD_ENABLED - ret = ret || tud_inited(); + if (tud_inited()) { + ret = true; + } #endif #if CFG_TUH_ENABLED - ret = ret || tuh_inited(); + if (tuh_inited()) { + ret = true; + } #endif return ret; @@ -209,7 +213,8 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; // pre-check to help reducing mutex lock - TU_VERIFY((ep_state->busy == 0) && (ep_state->claimed == 0)); + TU_VERIFY(ep_state->busy == 0); + TU_VERIFY(ep_state->claimed == 0); (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only claim the endpoint if it is not busy and not claimed yet. @@ -298,7 +303,7 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t const* p_desc = (uint8_t const*) desc_itf; uint16_t len = 0; - while (itf_count--) { + while ((itf_count--) > 0) { // Next on interface desc len += tu_desc_len(desc_itf); p_desc = tu_desc_next(p_desc); @@ -337,7 +342,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); #if OSAL_MUTEX_REQUIRED - if (ff_buf && ff_bufsize) { + if (ff_buf != NULL && ff_bufsize > 0) { osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutexdef); tu_fifo_config_mutex(&s->ff, is_tx ? new_mutex : NULL, is_tx ? NULL : new_mutex); } @@ -349,11 +354,15 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove return true; } -bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) { - (void) s; +bool tu_edpt_stream_deinit(tu_edpt_stream_t *s) { + (void)s; #if OSAL_MUTEX_REQUIRED - if (s->ff.mutex_wr) osal_mutex_delete(s->ff.mutex_wr); - if (s->ff.mutex_rd) osal_mutex_delete(s->ff.mutex_rd); + if (s->ff.mutex_wr) { + osal_mutex_delete(s->ff.mutex_wr); + } + if (s->ff.mutex_rd) { + osal_mutex_delete(s->ff.mutex_rd); + } #endif return true; } @@ -378,7 +387,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_xfer(uint8_t hwid, tu_edpt_strea #endif } else { #if CFG_TUD_ENABLED - return usbd_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count); + return usbd_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count, false); #endif } return false; @@ -403,7 +412,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_release(uint8_t hwid, tu_edpt_st bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { // ZLP condition: no pending data, last transferred bytes is multiple of packet size const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; - TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (mps - 1)))); + TU_VERIFY(tu_fifo_empty(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (mps - 1)))); TU_VERIFY(stream_claim(hwid, s)); TU_ASSERT(stream_xfer(hwid, s, 0)); return true; @@ -411,14 +420,13 @@ bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint3 uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { // skip if no data - TU_VERIFY(tu_fifo_count(&s->ff), 0); - + TU_VERIFY(tu_fifo_count(&s->ff) > 0, 0); TU_VERIFY(stream_claim(hwid, s), 0); // Pull data from FIFO -> EP buf - uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); + const uint16_t count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); - if (count) { + if (count > 0) { TU_ASSERT(stream_xfer(hwid, s, count), 0); return count; } else { @@ -429,8 +437,8 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } } -uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const* buffer, uint32_t bufsize) { - TU_VERIFY(bufsize); // TODO support ZLP +uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize) { + TU_VERIFY(bufsize > 0); // TODO support ZLP if (0 == tu_fifo_depth(&s->ff)) { // no fifo for buffered @@ -453,7 +461,7 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const* buf } uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) { - if (tu_fifo_depth(&s->ff)) { + if (tu_fifo_depth(&s->ff) > 0) { return (uint32_t) tu_fifo_remaining(&s->ff); } else { bool is_busy = true; @@ -509,7 +517,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) { - uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize); + const uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); tu_edpt_stream_read_xfer(hwid, s); return num_read; } @@ -576,8 +584,12 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) { if (i % item_per_line == 0) { // Print Ascii - if (i != 0) dump_str_line(buf8 - 16, 16); - for (uint8_t s = 0; s < indent; s++) tu_printf(" "); + if (i != 0) { + dump_str_line(buf8 - 16, 16); + } + for (uint8_t s = 0; s < indent; s++) { + tu_printf(" "); + } // print offset or absolute address tu_printf("%04X: ", 16 * i / item_per_line); } @@ -592,10 +604,12 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) { // fill up last row to 16 for printing ascii const uint32_t remain = count % 16; uint8_t nback = (uint8_t) (remain ? remain : 16); - if (remain) { + if (remain > 0) { for (uint32_t i = 0; i < 16 - remain; i++) { tu_printf(" "); - for (int j = 0; j < 2 * size; j++) tu_printf(" "); + for (int j = 0; j < 2 * size; j++) { + tu_printf(" "); + } } } diff --git a/src/tusb.h b/src/tusb.h index 92da845c0..62b3b9783 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_H_ -#define _TUSB_H_ +#ifndef TUSB_H_ +#define TUSB_H_ #ifdef __cplusplus extern "C" { @@ -88,6 +88,10 @@ #include "class/msc/msc_device.h" #endif + #if CFG_TUD_MTP + #include "class/mtp/mtp_device.h" + #endif + #if CFG_TUD_AUDIO #include "class/audio/audio_device.h" #endif @@ -174,4 +178,4 @@ bool tusb_deinit(uint8_t rhport); } #endif -#endif /* _TUSB_H_ */ +#endif /* TUSB_H_ */ diff --git a/src/tusb_option.h b/src/tusb_option.h index fe7e34111..c8265f898 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -24,14 +24,14 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OPTION_H_ -#define _TUSB_OPTION_H_ +#ifndef TUSB_OPTION_H_ +#define TUSB_OPTION_H_ #include "common/tusb_compiler.h" // Version is release as major.minor.revision eg 1.0.0 #define TUSB_VERSION_MAJOR 0 -#define TUSB_VERSION_MINOR 18 +#define TUSB_VERSION_MINOR 20 #define TUSB_VERSION_REVISION 0 #define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR * 10000 + TUSB_VERSION_MINOR * 100 + TUSB_VERSION_REVISION) @@ -62,7 +62,8 @@ #define OPT_MCU_LPC55XX OPT_MCU_LPC55 // NRF -#define OPT_MCU_NRF5X 100 ///< Nordic nRF5x series +#define OPT_MCU_NRF5X 100 ///< Nordic nRF 52,53 series +#define OPT_MCU_NRF54 101 ///< Nordic nRF54 series // SAM #define OPT_MCU_SAMD21 200 ///< MicroChip SAMD21 @@ -70,8 +71,9 @@ #define OPT_MCU_SAMG 202 ///< MicroChip SAMDG series #define OPT_MCU_SAME5X 203 ///< MicroChip SAM E5x #define OPT_MCU_SAMD11 204 ///< MicroChip SAMD11 -#define OPT_MCU_SAML22 205 ///< MicroChip SAML22 -#define OPT_MCU_SAML21 206 ///< MicroChip SAML21 +#define OPT_MCU_SAML2X 205 ///< MicroChip SAML2x +#define OPT_MCU_SAML21 OPT_MCU_SAML2X ///< SAML21 backward compatibility +#define OPT_MCU_SAML22 OPT_MCU_SAML2X ///< SAML22 backward compatibility #define OPT_MCU_SAMX7X 207 ///< MicroChip SAME70, S70, V70, V71 family // STM32 @@ -96,6 +98,7 @@ #define OPT_MCU_STM32C0 318 ///< ST C0 #define OPT_MCU_STM32N6 319 ///< ST N6 #define OPT_MCU_STM32WBA 320 ///< ST WBA +#define OPT_MCU_STM32U3 321 ///< ST U3 // Sony #define OPT_MCU_CXD56 400 ///< SONY CXD56 @@ -215,9 +218,9 @@ #define OPT_MCU_AT32F413 2506 ///< ArteryTek AT32F413 // Check if configured MCU is one of listed -// Apply _TU_CHECK_MCU with || as separator to list of input -#define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) -#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(_TU_CHECK_MCU, ||, __VA_ARGS__)) +// Apply TU_MCU_IS_EQUAL with || as separator to list of input +#define TU_MCU_IS_EQUAL(_m) (CFG_TUSB_MCU == (_m)) +#define TU_CHECK_MCU(...) (TU_ARGS_APPLY(TU_MCU_IS_EQUAL, ||, __VA_ARGS__)) //--------------------------------------------------------------------+ // Supported OS @@ -242,11 +245,11 @@ #define OPT_MODE_HOST 0x0002 ///< Host Mode // High byte is max operational speed (corresponding to tusb_speed_t) -#define OPT_MODE_DEFAULT_SPEED 0x0000 ///< Default (max) speed supported by MCU -#define OPT_MODE_LOW_SPEED 0x0100 ///< Low Speed -#define OPT_MODE_FULL_SPEED 0x0200 ///< Full Speed -#define OPT_MODE_HIGH_SPEED 0x0400 ///< High Speed -#define OPT_MODE_SPEED_MASK 0xff00 +#define OPT_MODE_DEFAULT_SPEED 0x0000u ///< Default (max) speed supported by MCU +#define OPT_MODE_LOW_SPEED 0x0100u ///< Low Speed +#define OPT_MODE_FULL_SPEED 0x0200u ///< Full Speed +#define OPT_MODE_HIGH_SPEED 0x0400u ///< High Speed +#define OPT_MODE_SPEED_MASK 0xff00u //--------------------------------------------------------------------+ // Include tusb_config.h @@ -482,6 +485,10 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif +#ifndef CFG_TUD_ENDPOINT0_BUFSIZE + #define CFG_TUD_ENDPOINT0_BUFSIZE CFG_TUD_ENDPOINT0_SIZE +#endif + #ifndef CFG_TUD_INTERFACE_MAX #define CFG_TUD_INTERFACE_MAX 16 #endif @@ -517,6 +524,10 @@ #define CFG_TUD_MSC 0 #endif +#ifndef CFG_TUD_MTP + #define CFG_TUD_MTP 0 +#endif + #ifndef CFG_TUD_HID #define CFG_TUD_HID 0 #endif @@ -721,6 +732,6 @@ // To avoid GCC compiler warnings when -pedantic option is used (strict ISO C) typedef int make_iso_compilers_happy; -#endif /* _TUSB_OPTION_H_ */ +#endif /* TUSB_OPTION_H_ */ /** @} */ diff --git a/src/typec/pd_types.h b/src/typec/pd_types.h index 1b2968f65..950f4d488 100644 --- a/src/typec/pd_types.h +++ b/src/typec/pd_types.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_PD_TYPES_H_ -#define _TUSB_PD_TYPES_H_ +#ifndef TUSB_PD_TYPES_H_ +#define TUSB_PD_TYPES_H_ #ifdef __cplusplus extern "C" { diff --git a/src/typec/tcd.h b/src/typec/tcd.h index bcbdab8ed..da7ab4b13 100644 --- a/src/typec/tcd.h +++ b/src/typec/tcd.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_TCD_H_ -#define _TUSB_TCD_H_ +#ifndef TUSB_TCD_H_ +#define TUSB_TCD_H_ #include "common/tusb_common.h" #include "pd_types.h" diff --git a/src/typec/usbc.h b/src/typec/usbc.h index 448542aab..711119596 100644 --- a/src/typec/usbc.h +++ b/src/typec/usbc.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_UTCD_H_ -#define _TUSB_UTCD_H_ +#ifndef TUSB_UTCD_H_ +#define TUSB_UTCD_H_ #include "common/tusb_common.h" #include "pd_types.h" @@ -63,7 +63,7 @@ void tuc_task (void) { tuc_task_ext(UINT32_MAX, false); } -#ifndef _TUSB_TCD_H_ +#ifndef TUSB_TCD_H_ extern void tcd_int_handler(uint8_t rhport); #endif diff --git a/test/fuzz/dcd_fuzz.cc b/test/fuzz/dcd_fuzz.cc index 046a90555..7a5d51623 100644 --- a/test/fuzz/dcd_fuzz.cc +++ b/test/fuzz/dcd_fuzz.cc @@ -104,7 +104,7 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { UNUSED(rhport); state.address = dev_addr; // Respond with status. - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false); return; } @@ -160,10 +160,11 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to // notify the stack bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, - uint16_t total_bytes) { + uint16_t total_bytes, bool is_isr) { UNUSED(rhport); UNUSED(buffer); UNUSED(total_bytes); + UNUSED(is_isr); uint8_t const dir = tu_edpt_dir(ep_addr); diff --git a/test/fuzz/device/cdc/Makefile b/test/fuzz/device/cdc/Makefile index 7071df057..d448907f0 100644 --- a/test/fuzz/device/cdc/Makefile +++ b/test/fuzz/device/cdc/Makefile @@ -2,10 +2,10 @@ include ../../make.mk INC += \ src \ - $(TOP)/hw \ + # Example source -SRC_C += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.c)) -SRC_CXX += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.cc)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(wildcard src/*.c)) +SRC_CXX += $(addprefix $(EXAMPLE_PATH)/, $(wildcard src/*.cc)) include ../../rules.mk diff --git a/test/fuzz/device/cdc/src/tusb_config.h b/test/fuzz/device/cdc/src/tusb_config.h index 10a8a825a..76f44619e 100644 --- a/test/fuzz/device/cdc/src/tusb_config.h +++ b/test/fuzz/device/cdc/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/test/fuzz/device/cdc/src/usb_descriptors.cc b/test/fuzz/device/cdc/src/usb_descriptors.cc index 0f636f05d..0d7d17b4b 100644 --- a/test/fuzz/device/cdc/src/usb_descriptors.cc +++ b/test/fuzz/device/cdc/src/usb_descriptors.cc @@ -30,10 +30,10 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_PID \ - (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | \ - _PID_MAP(VENDOR, 4)) + (0x4000 | PID_MAP(CDC, 0) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | \ + PID_MAP(VENDOR, 4)) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -148,7 +148,7 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void)index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, diff --git a/test/fuzz/device/msc/Makefile b/test/fuzz/device/msc/Makefile index 7071df057..d448907f0 100644 --- a/test/fuzz/device/msc/Makefile +++ b/test/fuzz/device/msc/Makefile @@ -2,10 +2,10 @@ include ../../make.mk INC += \ src \ - $(TOP)/hw \ + # Example source -SRC_C += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.c)) -SRC_CXX += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.cc)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(wildcard src/*.c)) +SRC_CXX += $(addprefix $(EXAMPLE_PATH)/, $(wildcard src/*.cc)) include ../../rules.mk diff --git a/test/fuzz/device/msc/src/tusb_config.h b/test/fuzz/device/msc/src/tusb_config.h index ca39c6b0a..abd8cd4ce 100644 --- a/test/fuzz/device/msc/src/tusb_config.h +++ b/test/fuzz/device/msc/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -111,4 +111,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/test/fuzz/device/msc/src/usb_descriptors.cc b/test/fuzz/device/msc/src/usb_descriptors.cc index efe4d0a3c..55c113ad7 100644 --- a/test/fuzz/device/msc/src/usb_descriptors.cc +++ b/test/fuzz/device/msc/src/usb_descriptors.cc @@ -30,10 +30,10 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_PID \ - (0x4000 | _PID_MAP(MSC, 0) | _PID_MAP(HID, 1) | _PID_MAP(MIDI, 2) | \ - _PID_MAP(VENDOR, 3)) + (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) | \ + PID_MAP(VENDOR, 3)) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -142,7 +142,7 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void)index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, diff --git a/test/fuzz/device/net/Makefile b/test/fuzz/device/net/Makefile index 2161ad3f1..45c684eec 100644 --- a/test/fuzz/device/net/Makefile +++ b/test/fuzz/device/net/Makefile @@ -8,15 +8,14 @@ CFLAGS += \ INC += \ src \ - $(TOP)/hw \ $(TOP)/lib/lwip/src/include \ $(TOP)/lib/lwip/src/include/ipv4 \ $(TOP)/lib/lwip/src/include/lwip/apps \ $(TOP)/lib/networking # Example source -SRC_C += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.c)) -SRC_CXX += $(addprefix $(CURRENT_PATH)/, $(wildcard src/*.cc)) +SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(wildcard src/*.c)) +SRC_CXX += $(addprefix $(EXAMPLE_PATH)/, $(wildcard src/*.cc)) # lwip sources SRC_C += \ diff --git a/test/fuzz/device/net/src/tusb_config.h b/test/fuzz/device/net/src/tusb_config.h index 6ad859337..4fe98e043 100644 --- a/test/fuzz/device/net/src/tusb_config.h +++ b/test/fuzz/device/net/src/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { @@ -119,4 +119,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/test/fuzz/device/net/src/usb_descriptors.cc b/test/fuzz/device/net/src/usb_descriptors.cc index 5597d49d5..301f23829 100644 --- a/test/fuzz/device/net/src/usb_descriptors.cc +++ b/test/fuzz/device/net/src/usb_descriptors.cc @@ -30,10 +30,10 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | CDC [LSB] */ -#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #define USB_PID \ - (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | \ - _PID_MAP(VENDOR, 4)) + (0x4000 | PID_MAP(CDC, 0) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | \ + PID_MAP(VENDOR, 4)) #define USB_VID 0xCafe #define USB_BCD 0x0200 @@ -148,7 +148,7 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void)index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa - // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + // Note: the descriptor type is OTHER_SPEED_CONFIG instead of CONFIG memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, diff --git a/test/fuzz/make.mk b/test/fuzz/make.mk index e9aa80bf1..733a57134 100644 --- a/test/fuzz/make.mk +++ b/test/fuzz/make.mk @@ -2,7 +2,7 @@ # Common make definition for all examples # --------------------------------------- -#-------------- TOP and CURRENT_PATH ------------ +#-------------- TOP and EXAMPLE_PATH ------------ # Set TOP to be the path to get from the current directory (where make was # invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns @@ -13,8 +13,8 @@ THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) # and Set TOP to an absolute path TOP = $(abspath $(subst make.mk,../..,$(THIS_MAKEFILE))) -# Set CURRENT_PATH to the relative path from TOP to the current directory, ie examples/device/cdc_msc_freertos -CURRENT_PATH = $(subst $(TOP)/,,$(abspath .)) +# Set EXAMPLE_PATH to the relative path from TOP to the current directory, ie examples/device/cdc_msc_freertos +EXAMPLE_PATH = $(subst $(TOP)/,,$(abspath .)) # Detect whether shell style is windows or not # https://stackoverflow.com/questions/714100/os-detecting-makefile/52062069#52062069 diff --git a/test/fuzz/rules.mk b/test/fuzz/rules.mk index 562969663..b32f8d695 100644 --- a/test/fuzz/rules.mk +++ b/test/fuzz/rules.mk @@ -31,6 +31,7 @@ SRC_C += \ src/class/hid/hid_device.c \ src/class/midi/midi_device.c \ src/class/msc/msc_device.c \ + src/class/mtp/mtp_device.c \ src/class/net/ecm_rndis_device.c \ src/class/net/ncm_device.c \ src/class/usbtmc/usbtmc_device.c \ diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 93cc0a750..3a11cee13 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -28,6 +28,7 @@ import argparse import os +import random import re import sys import time @@ -37,6 +38,9 @@ import json import glob from multiprocessing import Pool import fs +import hashlib +import ctypes +from pymtp import MTP ENUM_TIMEOUT = 30 @@ -45,6 +49,7 @@ STATUS_FAILED = "\033[31mFailed\033[0m" STATUS_SKIPPED = "\033[33mSkipped\033[0m" verbose = False +test_only = [] WCH_RISCV_CONTENT = """ adapter driver wlinke @@ -134,6 +139,24 @@ def read_disk_file(uid, lun, fname): return None +def open_mtp_dev(uid): + mtp = MTP() + # MTP seems to take a while to enumerate + timeout = 2*ENUM_TIMEOUT + while timeout > 0: + # run_cmd(f"gio mount -u mtp://TinyUsb_TinyUsb_Device_{uid}/") + for raw in mtp.detect_devices(): + mtp.device = mtp.mtp.LIBMTP_Open_Raw_Device(ctypes.byref(raw)) + if mtp.device: + sn = mtp.get_serialnumber().decode('utf-8') + #print(f'mtp serial = {sn}') + if sn == uid: + return mtp + time.sleep(1) + timeout -= 1 + return None + + # ------------------------------------------------------------- # Flashing firmware # ------------------------------------------------------------- @@ -456,7 +479,6 @@ def test_device_dfu(board): def test_device_dfu_runtime(board): uid = board['uid'] - # Wait device enum timeout = ENUM_TIMEOUT while timeout > 0: @@ -491,6 +513,65 @@ def test_device_hid_composite_freertos(id): pass +def test_device_mtp(board): + uid = board['uid'] + + # --- BEFORE: mute C-level stderr for libmtp vid/pid warnings --- + fd = sys.stderr.fileno() + _saved = os.dup(fd) + _null = os.open(os.devnull, os.O_WRONLY) + os.dup2(_null, fd) + + mtp = open_mtp_dev(uid) + + # --- AFTER: restore stderr --- + os.dup2(_saved, fd) + os.close(_null) + os.close(_saved) + + if mtp is None or mtp.device is None: + assert False, 'MTP device not found' + + try: + assert b"TinyUSB" == mtp.get_manufacturer(), 'MTP wrong manufacturer' + assert b"MTP Example" == mtp.get_modelname(), 'MTP wrong model' + assert b'1.0' == mtp.get_deviceversion(), 'MTP wrong version' + assert b'TinyUSB MTP' == mtp.get_devicename(), 'MTP wrong device name' + + # read and compare readme.txt and logo.png + f1_expect = b'TinyUSB MTP Filesystem example' + f2_md5_expect = '40ef23fc2891018d41a05d4a0d5f822f' # md5sum of logo.png + f1 = uid.encode("utf-8") + b'_file1' + f2 = uid.encode("utf-8") + b'_file2' + f3 = uid.encode("utf-8") + b'_file3' + mtp.get_file_to_file(1, f1) + with open(f1, 'rb') as file: + f1_data = file.read() + os.remove(f1) + assert f1_data == f1_expect, 'MTP file1 wrong data' + mtp.get_file_to_file(2, f2) + with open(f2, 'rb') as file: + f2_data = file.read() + os.remove(f2) + assert f2_md5_expect == hashlib.md5(f2_data).hexdigest(), 'MTP file2 wrong data' + # test send file + with open(f3, "wb") as file: + f3_data = os.urandom(random.randint(1024, 3*1024)) + file.write(f3_data) + file.close() + fid = mtp.send_file_from_file(f3, b'file3') + f3_readback = f3 + b'_readback' + mtp.get_file_to_file(fid, f3_readback) + with open(f3_readback, 'rb') as f: + f3_rb_data = f.read() + os.remove(f3_readback) + assert f3_rb_data == f3_data, 'MTP file3 wrong data' + os.remove(f3) + mtp.delete_object(fid) + finally: + mtp.disconnect() + + # ------------------------------------------------------------- # Main # ------------------------------------------------------------- @@ -503,6 +584,7 @@ device_tests = [ 'device/dfu_runtime', 'device/cdc_msc_freertos', 'device/hid_boot_interface', + # 'device/mtp' ] dual_tests = [ @@ -579,21 +661,24 @@ def test_board(board): # default to all tests test_list = [] - if 'tests' in board: - board_tests = board['tests'] - if 'device' in board_tests and board_tests['device'] == True: - test_list += list(device_tests) - if 'dual' in board_tests and board_tests['dual'] == True: - test_list += dual_tests - if 'host' in board_tests and board_tests['host'] == True: - test_list += host_test - if 'only' in board_tests: - test_list = board_tests['only'] - if 'skip' in board_tests: - for skip in board_tests['skip']: - if skip in test_list: - test_list.remove(skip) - print(f'{name:25} {skip:30} ... Skip') + if len(test_only) > 0: + test_list = test_only + else: + if 'tests' in board: + board_tests = board['tests'] + if 'device' in board_tests and board_tests['device'] == True: + test_list += list(device_tests) + if 'dual' in board_tests and board_tests['dual'] == True: + test_list += dual_tests + if 'host' in board_tests and board_tests['host'] == True: + test_list += host_test + if 'only' in board_tests: + test_list = board_tests['only'] + if 'skip' in board_tests: + for skip in board_tests['skip']: + if skip in test_list: + test_list.remove(skip) + print(f'{name:25} {skip:30} ... Skip') err_count = 0 flags_on_list = [""] @@ -615,6 +700,7 @@ def main(): Hardware test on specified boards """ global verbose + global test_only duration = time.time() @@ -622,6 +708,7 @@ def main(): parser.add_argument('config_file', help='Configuration JSON file') parser.add_argument('-b', '--board', action='append', default=[], help='Boards to test, all if not specified') parser.add_argument('-s', '--skip', action='append', default=[], help='Skip boards from test') + parser.add_argument('-t', '--test-only', action='append', default=[], help='Tests to run, all if not specified') parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output') args = parser.parse_args() @@ -629,6 +716,7 @@ def main(): boards = args.board skip_boards = args.skip verbose = args.verbose + test_only = args.test_only # if config file is not found, try to find it in the same directory as this script if not os.path.exists(config_file): diff --git a/test/hil/pymtp.py b/test/hil/pymtp.py new file mode 100644 index 000000000..8b694df94 --- /dev/null +++ b/test/hil/pymtp.py @@ -0,0 +1,1290 @@ +#!/usr/bin/env python +# +# A Ctypes wrapper to LibMTP +# Developed by: Nick Devito ([email protected]) +# (c) 2008 Nick Devito +# Released under the GPLv3 or later. +# + +""" + PyMTP is a pythonic wrapper around libmtp, making it a bit more + friendly to use in python + + Example Usage (or see examples/): + >>> import pymtp + >>> mtp = pymtp.MTP() + >>> mtp.connect() + PTP: Opening session + >>> print mtp.get_devicename() + Device name + >>> mtp.disconnect() + PTP: Closing session + >>> +""" + +__VERSION__ = "0.0.5" +__VERSION_MACRO__ = 5 +__VERSION_MINOR__ = 0 +__VERSION_MAJOR__ = 0 +__VERSION_TUPLE__ = (__VERSION_MAJOR__, __VERSION_MINOR__, __VERSION_MACRO__) +__AUTHOR__ = "Nick Devito ([email protected])" +__LICENSE__ = "GPL-3" +__DEBUG__ = 1 + +import os +import ctypes +import ctypes.util + +# NOTE: This code *may* work on windows, I don't have a win32 system to test +# this on. +_module_path = ctypes.util.find_library("mtp") +_libmtp = ctypes.CDLL(_module_path) + +# ---------- +# Error Definitions +# ---------- +class NoDeviceConnected(Exception): + """ + Raised when there isn't a device connected to the USB bus + """ + + pass + +class AlreadyConnected(Exception): + """ + Raised when we're already connected to a device and there is + an attempt to connect + """ + + pass + +class UnsupportedCommand(Exception): + """ + Raised when the connected device does not support the command + issued + """ + + pass + +class CommandFailed(Exception): + """ + Raised when the connected device returned an error when trying + to execute a command + """ + + pass + +class NotConnected(Exception): + """ + Raised when a command is called and the device is not connected + """ + + pass + +class ObjectNotFound(Exception): + """ + Raised when a command tries to get an object that doesn't exist + """ + + pass + +# ---------- +# End Error Definitions +# ---------- + +# ---------- +# Data Model Definitions +# ---------- + +class LIBMTP_Error(ctypes.Structure): + """ + LIBMTP_Error + Contains the ctypes structure for LIBMTP_error_t + """ + + def __repr__(self): + return self.errornumber + +LIBMTP_Error._fields_ = [("errornumber", ctypes.c_int), + ("error_text", ctypes.c_char_p), + ("next", ctypes.POINTER(LIBMTP_Error))] + +class LIBMTP_DeviceStorage(ctypes.Structure): + """ + LIBMTP_DeviceStorage + Contains the ctypes structure for LIBMTP_devicestorage_t + """ + + def __repr__(self): + return self.id + +LIBMTP_DeviceStorage._fields_ = [("id", ctypes.c_uint32), + ("StorageType", ctypes.c_uint16), + ("FilesystemType", ctypes.c_uint16), + ("AccessCapability", ctypes.c_uint16), + ("MaxCapacity", ctypes.c_uint64), + ("FreeSpaceInBytes", ctypes.c_uint64), + ("FreeSpaceInObjects", ctypes.c_uint64), + ("StorageDescription", ctypes.c_char_p), + ("VolumeIdentifier", ctypes.c_char_p), + ("next", ctypes.POINTER(LIBMTP_DeviceStorage)), + ("prev", ctypes.POINTER(LIBMTP_DeviceStorage))] + +class LIBMTP_DeviceEntry(ctypes.Structure): + """ + LIBMTP_DeviceEntry + Contains the ctypes structure for LIBMTP_device_entry_t + """ + + def __repr__(self): + return self.vendor + +LIBMTP_DeviceEntry._fields_ = [("vendor", ctypes.c_char_p), + ("vendor_id", ctypes.c_uint16), + ("product", ctypes.c_char_p), + ("product_id", ctypes.c_uint16), + ("device_flags", ctypes.c_uint32)] + +class LIBMTP_RawDevice(ctypes.Structure): + """ + LIBMTP_RawDevice + Contains the ctypes structure for LIBMTP_raw_device_t + """ + + def __repr__(self): + return self.device_entry + +LIBMTP_RawDevice._fields_ = [("device_entry", LIBMTP_DeviceEntry), + ("bus_location", ctypes.c_uint32), + ("devnum", ctypes.c_uint8)] + +class LIBMTP_MTPDevice(ctypes.Structure): + """ + LIBMTP_MTPDevice + Contains the ctypes structure for LIBMTP_mtpdevice_t + """ + + def __repr__(self): + return self.interface_number + +LIBMTP_MTPDevice._fields_ = [("interface_number", ctypes.c_uint8), + ("params", ctypes.c_void_p), + ("usbinfo", ctypes.c_void_p), + ("storage", ctypes.POINTER(LIBMTP_DeviceStorage)), + ("errorstack", ctypes.POINTER(LIBMTP_Error)), + ("maximum_battery_level", ctypes.c_uint8), + ("default_music_folder", ctypes.c_uint32), + ("default_playlist_folder", ctypes.c_uint32), + ("default_picture_folder", ctypes.c_uint32), + ("default_video_folder", ctypes.c_uint32), + ("default_organizer_folder", ctypes.c_uint32), + ("default_zencast_folder", ctypes.c_uint32), + ("default_album_folder", ctypes.c_uint32), + ("default_text_folder", ctypes.c_uint32), + ("cd", ctypes.c_void_p), + ("next", ctypes.POINTER(LIBMTP_MTPDevice))] + +class LIBMTP_File(ctypes.Structure): + """ + LIBMTP_File + Contains the ctypes structure for LIBMTP_file_t + """ + + def __repr__(self): + return "%s (%s)" % (self.filename, self.item_id) + +LIBMTP_File._fields_ = [("item_id", ctypes.c_uint32), + ("parent_id", ctypes.c_uint32), + ("storage_id", ctypes.c_uint32), + ("filename", ctypes.c_char_p), + ("filesize", ctypes.c_uint64), + ("modificationdate", ctypes.c_uint64), + ("filetype", ctypes.c_int), # LIBMTP_filetype_t enum + ("next", ctypes.POINTER(LIBMTP_File))] + +class LIBMTP_Track(ctypes.Structure): + """ + LIBMTP_Track + Contains the ctypes structure for LIBMTP_track_t + """ + + def __repr__(self): + return "%s - %s (%s)" % (self.artist, self.title, self.item_id) + +LIBMTP_Track._fields_ = [("item_id", ctypes.c_uint32), + ("parent_id", ctypes.c_uint32), + ("storage_id", ctypes.c_uint32), + ("title", ctypes.c_char_p), + ("artist", ctypes.c_char_p), + ("composer", ctypes.c_char_p), + ("genre", ctypes.c_char_p), + ("album", ctypes.c_char_p), + ("date", ctypes.c_char_p), + ("filename", ctypes.c_char_p), + ("tracknumber", ctypes.c_uint16), + ("duration", ctypes.c_uint32), + ("samplerate", ctypes.c_uint32), + ("nochannels", ctypes.c_uint16), + ("wavecodec", ctypes.c_uint32), + ("bitrate", ctypes.c_uint32), + ("bitratetype", ctypes.c_uint16), + ("rating", ctypes.c_uint16), + ("usecount", ctypes.c_uint32), + ("filesize", ctypes.c_uint64), + ("modificationdate", ctypes.c_uint64), + ("filetype", ctypes.c_int), # LIBMTP_filetype_t enum + ("next", ctypes.POINTER(LIBMTP_Track))] + +class LIBMTP_Playlist(ctypes.Structure): + """ + LIBMTP_Playlist + Contains the ctypes structure for LIBMTP_playlist_t + """ + + def __init__(self): + self.tracks = ctypes.pointer(ctypes.c_uint32(0)) + self.no_tracks = ctypes.c_uint32(0) + def __repr__(self): + return "%s (%s)" % (self.name, self.playlist_id) + + def __iter__(self): + """ + This allows the playlist object to act like a list with + a generator. + """ + for track in xrange(self.no_tracks): + yield self.tracks[track] + + def __getitem__(self, key): + """ + This allows the playlist to return tracks like a list + """ + + if (key > (self.no_tracks - 1)): + raise IndexError + + return self.tracks[key] + + def __setitem__(self, key, value): + """ + This allows the user to manipulate the playlist like a + list. However, this will only modify existing objects, + you can't try to set a key outside of the current size. + """ + + if (key > (self.no_tracks - 1)): + raise IndexError + + self.tracks[key] = value + + def __delitem__(self, key): + """ + This allows the user to delete an object + from the playlist + """ + + if (key > (self.no_tracks - 1)): + raise IndexError + + for i in range(key, (self.no_tracks - 1)): + self.tracks[i] = self.tracks[i + 1] + + self.no_tracks -= 1 + + def append(self, value): + """ + This function appends a track to the end of the tracks + list. + """ + if (self.tracks == None): + self.tracks = ctypes.pointer(ctypes.c_uint32(0)) + + self.no_tracks += 1 + self.tracks[(self.no_tracks - 1)] = value + + def __len__(self): + """ + This returns the number of tracks in the playlist + """ + + return self.no_tracks + +LIBMTP_Playlist._fields_ = [("playlist_id", ctypes.c_uint32), + ("parent_id", ctypes.c_uint32), + ("storage_id", ctypes.c_uint32), + ("name", ctypes.c_char_p), + ("tracks", ctypes.POINTER(ctypes.c_uint32)), + ("no_tracks", ctypes.c_uint32), + ("next", ctypes.POINTER(LIBMTP_Playlist))] + +class LIBMTP_Folder(ctypes.Structure): + """ + LIBMTP_Folder + Contains the ctypes structure for LIBMTP_folder_t + """ + + def __repr__(self): + return "%s (%s)" % (self.name, self.folder_id) + +LIBMTP_Folder._fields_ = [("folder_id", ctypes.c_uint32), + ("parent_id", ctypes.c_uint32), + ("storage_id", ctypes.c_uint32), + ("name", ctypes.c_char_p), + ("sibling", ctypes.POINTER(LIBMTP_Folder)), + ("child", ctypes.POINTER(LIBMTP_Folder))] + +# Abstracted from libmtp's LIBMTP_filetype_t. This must be kept in sync. +# first checked in 0.2.6.1 +# last checked in version 1.1.6 +LIBMTP_Filetype = { + "WAV": ctypes.c_int(0), + "MP3": ctypes.c_int(1), + "WMA": ctypes.c_int(2), + "OGG": ctypes.c_int(3), + "AUDIBLE": ctypes.c_int(4), + "MP4": ctypes.c_int(5), + "UNDEF_AUDIO": ctypes.c_int(6), + "WMV": ctypes.c_int(7), + "AVI": ctypes.c_int(8), + "MPEG": ctypes.c_int(9), + "ASF": ctypes.c_int(10), + "QT": ctypes.c_int(11), + "UNDEF_VIDEO": ctypes.c_int(12), + "JPEG": ctypes.c_int(13), + "JFIF": ctypes.c_int(14), + "TIFF": ctypes.c_int(15), + "BMP": ctypes.c_int(16), + "GIF": ctypes.c_int(17), + "PICT": ctypes.c_int(18), + "PNG": ctypes.c_int(19), + "VCALENDAR1": ctypes.c_int(20), + "VCALENDAR2": ctypes.c_int(21), + "VCARD2": ctypes.c_int(22), + "VCARD3": ctypes.c_int(23), + "WINDOWSIMAGEFORMAT": ctypes.c_int(24), + "WINEXEC": ctypes.c_int(25), + "TEXT": ctypes.c_int(26), + "HTML": ctypes.c_int(27), + "FIRMWARE": ctypes.c_int(28), + "AAC": ctypes.c_int(29), + "MEDIACARD": ctypes.c_int(30), + "FLAC": ctypes.c_int(31), + "MP2": ctypes.c_int(32), + "M4A": ctypes.c_int(33), + "DOC": ctypes.c_int(34), + "XML": ctypes.c_int(35), + "XLS": ctypes.c_int(36), + "PPT": ctypes.c_int(37), + "MHT": ctypes.c_int(38), + "JP2": ctypes.c_int(39), + "JPX": ctypes.c_int(40), + "ALBUM": ctypes.c_int(41), + "PLAYLIST": ctypes.c_int(42), + "UNKNOWN": ctypes.c_int(43), +} + +# Synced from libmtp 0.2.6.1's libmtp.h. Must be kept in sync. +LIBMTP_Error_Number = { + "NONE": ctypes.c_int(0), + "GENERAL": ctypes.c_int(1), + "PTP_LAYER": ctypes.c_int(2), + "USB_LAYER": ctypes.c_int(3), + "MEMORY_ALLOCATION": ctypes.c_int(4), + "NO_DEVICE_ATTACHED": ctypes.c_int(5), + "STORAGE_FULL": ctypes.c_int(6), + "CONNECTING": ctypes.c_int(7), + "CANCELLED": ctypes.c_int(8), +} + +# ---------- +# End Data Model Definitions +# ---------- + +# ---------- +# Type Definitions +# ---------- +_libmtp.LIBMTP_Detect_Raw_Devices.restype = ctypes.c_int # actually LIBMTP_Error_Number enum +_libmtp.LIBMTP_Get_Friendlyname.restype = ctypes.c_char_p +_libmtp.LIBMTP_Get_Serialnumber.restype = ctypes.c_char_p +_libmtp.LIBMTP_Get_Modelname.restype = ctypes.c_char_p +_libmtp.LIBMTP_Get_Manufacturername.restype = ctypes.c_char_p +_libmtp.LIBMTP_Get_Deviceversion.restype = ctypes.c_char_p +_libmtp.LIBMTP_Get_Filelisting_With_Callback.restype = ctypes.POINTER(LIBMTP_File) +_libmtp.LIBMTP_Get_Tracklisting_With_Callback.restype = ctypes.POINTER(LIBMTP_Track) +_libmtp.LIBMTP_Get_Filetype_Description.restype = ctypes.c_char_p +_libmtp.LIBMTP_Get_Filemetadata.restype = ctypes.POINTER(LIBMTP_File) +_libmtp.LIBMTP_Get_Trackmetadata.restype = ctypes.POINTER(LIBMTP_Track) +_libmtp.LIBMTP_Get_First_Device.restype = ctypes.POINTER(LIBMTP_MTPDevice) +_libmtp.LIBMTP_Get_Playlist_List.restype = ctypes.POINTER(LIBMTP_Playlist) +_libmtp.LIBMTP_Get_Playlist.restype = ctypes.POINTER(LIBMTP_Playlist) +_libmtp.LIBMTP_Get_Folder_List.restype = ctypes.POINTER(LIBMTP_Folder) +_libmtp.LIBMTP_Find_Folder.restype = ctypes.POINTER(LIBMTP_Folder) +_libmtp.LIBMTP_Get_Errorstack.restype = ctypes.POINTER(LIBMTP_Error) + +_libmtp.LIBMTP_Open_Raw_Device.restype = ctypes.POINTER(LIBMTP_MTPDevice) +_libmtp.LIBMTP_Open_Raw_Device.argtypes = [ctypes.POINTER(LIBMTP_RawDevice)] + +# This is for callbacks with the type of LIBMTP_progressfunc_t +Progressfunc = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64) + +# ---------- +# End Type Definitions +# ---------- + +class MTP: + """ + The MTP object + This is the main wrapper around libmtp + """ + + def __init__(self): + """ + Initializes the MTP object + + @rtype: None + @return: None + """ + + self.mtp = _libmtp + self.mtp.LIBMTP_Init() + self.device = None + + def debug_stack(self): + """ + Checks if __DEBUG__ is set, if so, prints and clears the + errorstack. + + @rtype: None + @return: None + """ + + if __DEBUG__: + self.mtp.LIBMTP_Dump_Errorstack() + #self.mtp.LIBMTP_Clear_Errorstack() + + def detect_devices(self): + """ + Detect if any MTP devices are connected + + @rtype: None + @return: a list of LIBMTP_RawDevice instances for devices found + + """ + + devlist = [] + device = LIBMTP_RawDevice() + devices = ctypes.pointer(device) + numdevs = ctypes.c_int(0) + err = self.mtp.LIBMTP_Detect_Raw_Devices(ctypes.byref(devices), + ctypes.byref(numdevs)) + if err == LIBMTP_Error_Number['NO_DEVICE_ATTACHED']: + return devlist + elif err == LIBMTP_Error_Number['STORAGE_FULL']: + # ignore this, we're just trying to detect here, not do anything else + pass + elif err == LIBMTP_Error_Number['CONNECTING']: + raise AlreadyConnected('CONNECTING') + elif err == LIBMTP_Error_Number['GENERAL']: + raise CommandFailed('GENERAL') + elif err == LIBMTP_Error_Number['PTP_LAYER']: + raise CommandFailed('PTP_LAYER') + elif err == LIBMTP_Error_Number['USB_LAYER']: + raise CommandFailed('USB_LAYER') + elif err == LIBMTP_Error_Number['MEMORY_ALLOCATION']: + raise CommandFailed('MEMORY_ALLOCATION') + elif err == LIBMTP_Error_Number['CANCELLED']: + raise CommandFailed('CANCELLED') + if numdevs.value == 0: + return devlist + for i in range(numdevs.value): + devlist.append(devices[i]) + return devlist + + def connect(self): + """ + Initializes the MTP connection to the device + + @rtype: None + @return: None + + """ + + if (self.device != None): + raise AlreadyConnected + + self.device = self.mtp.LIBMTP_Get_First_Device() + + if not self.device: + self.device = None + raise NoDeviceConnected + + def disconnect(self): + """ + Disconnects the MTP device and deletes the self.device object + + @rtype: None + @return: None + """ + + if (self.device == None): + raise NotConnected + + self.mtp.LIBMTP_Release_Device(self.device) + del self.device + self.device = None + + def get_devicename(self): + """ + Returns the connected device's 'friendly name' (or + known as the owner name) + + @rtype: string + @return: The connected device's 'friendly name' + """ + + if (self.device == None): + raise NotConnected + + return self.mtp.LIBMTP_Get_Friendlyname(self.device) + + def set_devicename(self, name): + """ + Changes the connected device's 'friendly name' to name + + @type name: string + @param name: The name to change the connected device's + 'friendly name' to + @rtype: None + @return: None + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Set_Friendlyname(self.device, name) + if (ret != 0): + self.debug_stack() + raise CommandFailed + + def get_serialnumber(self): + """ + Returns the connected device's serial number + + @rtype: string + @return: The connected device's serial number + """ + + if (self.device == None): + raise NotConnected + + return self.mtp.LIBMTP_Get_Serialnumber(self.device) + + def get_manufacturer(self): + """ + Return the connected device's manufacturer + + @rtype: string + @return: The connected device's manufacturer + """ + if (self.device == None): + raise NotConnected + + return self.mtp.LIBMTP_Get_Manufacturername(self.device) + + def get_batterylevel(self): + """ + Returns the connected device's maximum and current + battery levels + + @rtype: tuple + @return: The connected device's maximum and current + battery levels ([0] is maximum, [1] is current) + """ + + if (self.device == None): + raise NotConnected + + maximum_level = ctypes.c_uint8() + current_level = ctypes.c_uint8() + + ret = self.mtp.LIBMTP_Get_Batterylevel(self.device, \ + ctypes.byref(maximum_level), ctypes.byref(current_level)) + + if (ret != 0): + raise CommandFailed + + return (maximum_level.value, current_level.value) + + def get_modelname(self): + """ + Returns the connected device's model name (such + as "Zen V Plus") + + @rtype: string + @return: The connected device's model name + """ + + if (self.device == None): + raise NotConnected + + return self.mtp.LIBMTP_Get_Modelname(self.device) + + def get_deviceversion(self): + """ + Returns the connected device's version (such as + firmware/hardware version) + + @rtype: string + @return: Returns the connect device's version + information + """ + + if (self.device == None): + raise NotConnected + + return self.mtp.LIBMTP_Get_Deviceversion(self.device) + + def get_filelisting(self, callback=None): + """ + Returns the connected device's file listing as a tuple, + containing L{LIBMTP_File} objects. + + @type callback: function or None + @param callback: The function provided to libmtp to + receive callbacks from ptp. Callback must take two + arguments, total and sent (in bytes) + @rtype: tuple + @return: Returns the connect device file listing tuple + """ + + if (self.device == None): + raise NotConnected + + if (callback != None): + callback = Progressfunc(callback) + + files = self.mtp.LIBMTP_Get_Filelisting_With_Callback(self.device, callback, None) + ret = [] + next = files + + while next: + ret.append(next.contents) + if (next.contents.next == None): + break + next = next.contents.next + + return ret + + def get_filetype_description(self, filetype): + """ + Returns the description of the filetype + + @type filetype: int + @param filetype: The MTP filetype integer + @rtype: string + @return: The file type information + """ + + if (self.device == None): + raise NotConnected + + return self.mtp.LIBMTP_Get_Filetype_Description(filetype) + + def get_file_metadata(self, file_id): + """ + Returns the file metadata from the connected device + + As per the libmtp documentation, calling this function + repeatedly is not recommended, as it is slow and creates + a large amount of USB traffic. + + @type file_id: int + @param file_id: The unique numeric file id + @rtype: LIBMTP_File + @return: The file metadata + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Get_Filemetadata(self.device, file_id) + + if (not hasattr(ret, 'contents')): + raise ObjectNotFound + + return ret.contents + + def get_tracklisting(self, callback=None): + """ + Returns tracks from the connected device + + @type callback: function or None + @param callback: The function provided to libmtp to + receive callbacks from ptp. Callback must take two + arguments, total and sent (in bytes) + @rtype: tuple + @return: Returns a tuple full of L{LIBMTP_Track} objects + """ + + if (self.device == None): + raise NotConnected + + if (callback != None): + callback = Progressfunc(callback) + + tracks = self.mtp.LIBMTP_Get_Tracklisting_With_Callback(self.device, callback, None) + ret = [] + next = tracks + + while next: + ret.append(next.contents) + if (next.contents.next == None): + break + next = next.contents.next + + return ret + + def get_track_metadata(self, track_id): + """ + Returns the track metadata + + As per the libmtp documentation, calling this function repeatedly is not + recommended, as it is slow and creates a large amount of USB traffic. + + @type track_id: int + @param track_id: The unique numeric track id + @rtype: L{LIBMTP_Track} + @return: The track metadata + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Get_Trackmetadata(self.device, track_id) + + if (not hasattr(ret, 'contents')): + raise ObjectNotFound + + return ret.contents + + def get_file_to_file(self, file_id, target, callback=None): + """ + Downloads the file from the connected device and stores it at the + target location + + @type file_id: int + @param file_id: The unique numeric file id + @type target: str + @param target: The location to place the file + @type callback: function or None + @param callback: The function provided to libmtp to + receive callbacks from ptp. Callback must take two + arguments, total and sent (in bytes) + """ + + if (self.device == None): + raise NotConnected + + if (callback != None): + callback = Progressfunc(callback) + + ret = self.mtp.LIBMTP_Get_File_To_File(self.device, file_id, target, callback, None) + + if (ret != 0): + self.debug_stack() + raise CommandFailed + + def get_track_to_file(self, track_id, target, callback=None): + """ + Downloads the track from the connected device and stores it at + the target location + + @type track_id: int + @param track_id: The unique numeric track id + @type target: str + @param target: The location to place the track + @type callback: function or None + @param callback: The function provided to libmtp to + receive callbacks from ptp. Callback must take two + arguments, total and sent (in bytes) + """ + + if (self.device == None): + raise NotConnected + + if (callback != None): + callback = Progressfunc(callback) + + ret = self.mtp.LIBMTP_Get_Track_To_File(self.device, track_id, target, callback, None) + + if (ret != 0): + self.debug_stack() + raise CommandFailed + + def find_filetype(self, filename): + """ + Attempts to guess the filetype off the filename. Kind of + inaccurate and should be trusted with a grain of salt. It + works in most situations, though. + + @type filename: str + @param filename: The filename to attempt to guess from + @rtype: int + @return: The integer of the Filetype + """ + + fileext = filename.decode('utf-8').lower().split(".")[-1] + + if (fileext == "wav" or fileext == "wave"): + return LIBMTP_Filetype["WAV"] + elif (fileext == "mp3"): + return LIBMTP_Filetype["MP3"] + elif (fileext == "wma"): + return LIBMTP_Filetype["WMA"] + elif (fileext == "ogg"): + return LIBMTP_Filetype["OGG"] + elif (fileext == "mp4"): + return LIBMTP_Filetype["MP4"] + elif (fileext == "wmv"): + return LIBMTP_Filetype["WMV"] + elif (fileext == "avi"): + return LIBMTP_Filetype["AVI"] + elif (fileext == "mpeg" or fileext == "mpg"): + return LIBMTP_Filetype["MPEG"] + elif (fileext == "asf"): + return LIBMTP_Filetype["ASF"] + elif (fileext == "qt" or fileext == "mov"): + return LIBMTP_Filetype["QT"] + elif (fileext == "jpeg" or fileext == "jpg"): + return LIBMTP_Filetype["JPEG"] + elif (fileext == "jfif"): + return LIBMTP_Filetype["JFIF"] + elif (fileext == "tif" or fileext == "tiff"): + return LIBMTP_Filetype["TIFF"] + elif (fileext == "bmp"): + return LIBMTP_Filetype["BMP"] + elif (fileext == "gif"): + return LIBMTP_Filetype["GIF"] + elif (fileext == "pic" or fileext == "pict"): + return LIBMTP_Filetype["PICT"] + elif (fileext == "png"): + return LIBMTP_Filetype["PNG"] + elif (fileext == "wmf"): + return LIBMTP_Filetype["WINDOWSIMAGEFORMAT"] + elif (fileext == "ics"): + return LIBMTP_Filetype["VCALENDAR2"] + elif (fileext == "exe" or fileext == "com" or fileext == "bat"\ + or fileext == "dll" or fileext == "sys"): + return LIBMTP_Filetype["WINEXEC"] + elif (fileext == "aac"): + return LIBMTP_Filetype["AAC"] + elif (fileext == "mp2"): + return LIBMTP_Filetype["MP2"] + elif (fileext == "flac"): + return LIBMTP_Filetype["FLAC"] + elif (fileext == "m4a"): + return LIBMTP_Filetype["M4A"] + elif (fileext == "doc"): + return LIBMTP_Filetype["DOC"] + elif (fileext == "xml"): + return LIBMTP_Filetype["XML"] + elif (fileext == "xls"): + return LIBMTP_Filetype["XLS"] + elif (fileext == "ppt"): + return LIBMTP_Filetype["PPT"] + elif (fileext == "mht"): + return LIBMTP_Filetype["MHT"] + elif (fileext == "jp2"): + return LIBMTP_Filetype["JP2"] + elif (fileext == "jpx"): + return LIBMTP_Filetype["JPX"] + else: + return LIBMTP_Filetype["UNKNOWN"] + + def send_file_from_file(self, source, target, callback=None): + """ + Sends a file from the filesystem to the connected device + and stores it at the target filename inside the parent. + + This will attempt to "guess" the filetype with + find_filetype() + + @type source: str + @param source: The path on the filesystem where the file resides + @type target: str + @param target: The target filename on the device + @type callback: function or None + @param callback: The function provided to libmtp to + receive callbacks from ptp. Callback function must + take two arguments, sent and total (in bytes) + @rtype: int + @return: The object ID of the new file + """ + + if (self.device == None): + raise NotConnected + + if (os.path.isfile(source) == False): + raise IOError + + if (callback != None): + callback = Progressfunc(callback) + + metadata = LIBMTP_File(filename=target, \ + filetype=self.find_filetype(source), \ + filesize=os.stat(source).st_size) + + ret = self.mtp.LIBMTP_Send_File_From_File(self.device, source, \ + ctypes.pointer(metadata), callback, None) + + if (ret != 0): + self.debug_stack() + raise CommandFailed + + return metadata.item_id + + def send_track_from_file(self, source, target, metadata, callback=None): + """ + Sends a track from the filesystem to the connected + device + + @type source: str + @param source: The path where the track resides + @type target: str + @param target: The target filename on the device + @type metadata: LIBMTP_Track + @param metadata: The track metadata + @type callback: function or None + @param callback: The function provided to libmtp to + receive callbacks from ptp. Callback function must + take two arguments, sent and total (in bytes) + @rtype: int + @return: The object ID of the new track + """ + + if (self.device == None): + raise NotConnected + + if (os.path.exists(source) == None): + raise IOError + + if callback: + callback = Progressfunc(callback) + + metadata.filename = target + metadata.filetype = self.find_filetype(source) + metadata.filesize = os.stat(source).st_size + + ret = self.mtp.LIBMTP_Send_Track_From_File(self.device, source, \ + ctypes.pointer(metadata), callback, None) + + if (ret != 0): + self.debug_stack() + raise CommandFailed + + return metadata.item_id + + def get_freespace(self): + """ + Returns the amount of free space on the connected device + @rtype: long + @return: The amount of free storage in bytes + """ + + if (self.device == None): + raise NotConnected + + self.mtp.LIBMTP_Get_Storage(self.device, 0) + return self.device.contents.storage.contents.FreeSpaceInBytes + + def get_totalspace(self): + """ + Returns the total space on the connected device + @rtype: long + @return: The amount of total storage in bytes + """ + + if (self.device == None): + raise NotConnected + + self.mtp.LIBMTP_Get_Storage(self.device, 0) + return self.device.contents.storage.contents.MaxCapacity + + def get_usedspace(self): + """ + Returns the amount of used space on the connected device + + @rtype: long + @return: The amount of used storage in bytes + """ + + if (self.device == None): + raise NotConnected + + self.mtp.LIBMTP_Get_Storage(self.device, 0) + storage = self.device.contents.storage.contents + return (storage.MaxCapacity - storage.FreeSpaceInBytes) + + def get_usedspace_percent(self): + """ + Returns the amount of used space as a percentage + + @rtype: float + @return: The percentage of used storage + """ + + if (self.device == None): + raise NotConnected + + self.mtp.LIBMTP_Get_Storage(self.device, 0) + storage = self.device.contents.storage.contents + + # Why don't we call self.get_totalspace/self.get_usedspace + # here? That would require 3 *more* calls to + # LIBMTP_Get_Storage + usedspace = storage.MaxCapacity - storage.FreeSpaceInBytes + return ((float(usedspace) / float(storage.MaxCapacity)) * 100) + + def delete_object(self, object_id): + """ + Deletes the object off the connected device. + + @type object_id: int + @param object_id: The unique object identifier + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Delete_Object(self.device, object_id) + + if (ret != 0): + self.debug_stack() + raise CommandFailed + + def get_playlists(self): + """ + Returns a tuple filled with L{LIBMTP_Playlist} objects + from the connected device. + + The main gotcha of this function is that the tracks + variable of LIBMTP_Playlist isn't iterable (without + segfaults), so, you have to iterate over the no_tracks + (through range or xrange) and access it that way (i.e. + tracks[track_id]). Kind of sucks. + + @rtype: tuple + @return: Tuple filled with LIBMTP_Playlist objects + """ + + if (self.device == None): + raise NotConnected + + playlists = self.mtp.LIBMTP_Get_Playlist_List(self.device) + ret = [] + next = playlists + + while next: + ret.append(next.contents) + if (next.contents.next == None): + break + next = next.contents.next + + return ret + + def get_playlist(self, playlist_id): + """ + Returns a L{LIBMTP_Playlist} object of the requested + playlist_id from the connected device + + @type playlist_id: int + @param playlist_id: The unique playlist identifier + @rtype: LIBMTP_Playlist + @return: The playlist object + """ + + if (self.device == None): + raise NotConnected + + try: + ret = self.mtp.LIBMTP_Get_Playlist(self.device, playlist_id).contents + except ValueError: + raise ObjectNotFound + + return ret + + def create_new_playlist(self, metadata): + """ + Creates a new playlist based on the metadata object + passed. + + @type metadata: LIBMTP_Playlist + @param metadata: A LIBMTP_Playlist object describing + the playlist + @rtype: int + @return: The object ID of the new playlist + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Create_New_Playlist(self.device, ctypes.pointer(metadata)) + + if (ret != 0): + self.debug_stack() + raise CommandFailed + + return metadata.playlist_id + + def update_playlist(self, metadata): + """ + Updates a playlist based on the supplied metadata. + + When updating the tracks field in a playlist, this + function will replace the playlist's tracks with + the tracks supplied in the metadata object. This + means that the previous tracks in the playlist + will be overwritten. + + @type metadata: LIBMTP_Playlist + @param metadata: A LIBMTP_Playlist object describing + the updates to the playlist. + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Update_Playlist(self.device, ctypes.pointer(metadata)) + + if (ret != 0): + self.debug_stack() + raise CommandFailed + + def get_folder_list(self): + """ + Returns a pythonic dict of the folders on the + device. + + @rtype: dict + @return: A dict of the folders on the device where + the folder ID is the key. + """ + + if (self.device == None): + raise NotConnected + + folders = self.mtp.LIBMTP_Get_Folder_List(self.device) + next = folders + # List of folders, key being the folder ID + ret = {} + # Iterate over the folders to grab the first-level parents + while True: + next = next.contents + scanned = True + + # Check if this ID exists, if not, add it + # and trigger a scan of the children + if not (ret.has_key(next.folder_id)): + ret[next.folder_id] = next + scanned = False + + if ((scanned == False) and (next.child)): + ## Scan the children + next = next.child + + elif (next.sibling): + ## Scan the siblings + next = next.sibling + + elif (next.parent_id != 0): + ## If we have no children/siblings to visit, + ## and we aren't at the parent, go back to + ## the parent. + next = self.mtp.LIBMTP_Find_Folder(folders, int(next.parent_id)) + + else: + ## We have scanned everything, let's go home. + break + + return ret + + def get_parent_folders(self): + """ + Returns a list of only the parent folders. + @rtype: list + @return: Returns a list of the parent folders + """ + + if (self.device == None): + raise NotConnected + folders = self.mtp.LIBMTP_Get_Folder_List(self.device) + next = folders + # A temporary holding space, this makes checking folder + # IDs easier + tmp = {} + + while True: + next = next.contents + ## Check if this folder is in the dict + if not (tmp.has_key(next.folder_id)): + tmp[next.folder_id] = next + + # Check for siblings + if (next.sibling): + ## Scan the sibling + next = next.sibling + else: + ## We're done here. + break + + ## convert the dict into a list + ret = [] + for key in tmp: + ret.append(tmp[key]) + + return ret + + def create_folder(self, name, parent=0, storage=0): + """ + This creates a new folder in the parent. If the parent + is 0, it will go in the main directory. + + @type name: str + @param name: The name for the folder + @type parent: int + @param parent: The parent ID or 0 for main directory + @type storage: int + @param storage: The storage id or 0 to create the new folder + on the primary storage + @rtype: int + @return: Returns the object ID of the new folder + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Create_Folder(self.device, name, parent, storage) + + if (ret == 0): + self.debug_stack() + raise CommandFailed + + return ret + + def get_errorstack(self): + """ + Returns the connected device's errorstack from + LIBMTP. + @rtype: L{LIBMTP_Error} + @return: An array of LIBMTP_Errors. + """ + + if (self.device == None): + raise NotConnected + + ret = self.mtp.LIBMTP_Get_Errorstack(self.device) + + if (ret != 0): + raise CommandFailed + + return ret diff --git a/test/unit-test/test/device/msc/test_msc_device.c b/test/unit-test/test/device/msc/test_msc_device.c index 49843a921..ea02b7050 100644 --- a/test/unit-test/test/device/msc/test_msc_device.c +++ b/test/unit-test/test/device/msc/test_msc_device.c @@ -256,7 +256,7 @@ void test_msc(void) dcd_edpt_open_ExpectAndReturn(rhport, (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep), true); // Prepare SCSI command - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), false, true); dcd_edpt_xfer_IgnoreArg_buffer(); dcd_edpt_xfer_ReturnMemThruPtr_buffer( (uint8_t*) &cbw_read10, sizeof(msc_cbw_t)); @@ -264,20 +264,20 @@ void test_msc(void) dcd_event_xfer_complete(rhport, EDPT_MSC_OUT, sizeof(msc_cbw_t), 0, true); // control status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, false, true); // SCSI Data transfer - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 512, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 512, false, true); dcd_edpt_xfer_IgnoreArg_buffer(); dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 512, 0, true); // complete // SCSI Status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 13, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_IN, NULL, 13, false, true); dcd_edpt_xfer_IgnoreArg_buffer(); dcd_event_xfer_complete(rhport, EDPT_MSC_IN, 13, 0, true); // Prepare for next command - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_MSC_OUT, NULL, sizeof(msc_cbw_t), false, true); dcd_edpt_xfer_IgnoreArg_buffer(); tud_task(); diff --git a/test/unit-test/test/device/usbd/test_usbd.c b/test/unit-test/test/device/usbd/test_usbd.c index f0153da3f..3a2cf3217 100644 --- a/test/unit-test/test/device/usbd/test_usbd.c +++ b/test/unit-test/test/device/usbd/test_usbd.c @@ -151,11 +151,11 @@ void test_usbd_get_device_descriptor(void) dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false); // data - dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*)&data_desc_device, sizeof(tusb_desc_device_t), sizeof(tusb_desc_device_t), true); + dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*)&data_desc_device, sizeof(tusb_desc_device_t), sizeof(tusb_desc_device_t), false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, sizeof(tusb_desc_device_t), 0, false); // status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_device, 1); @@ -184,11 +184,11 @@ void test_usbd_get_configuration_descriptor(void) dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_configuration, false); // data - dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*) data_desc_configuration, total_len, total_len, true); + dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*) data_desc_configuration, total_len, total_len, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, total_len, 0, false); // status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1); @@ -227,20 +227,20 @@ void test_usbd_control_in_zlp(void) // 1st transaction dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN, - zlp_desc_configuration, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true); + zlp_desc_configuration, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false); // 2nd transaction dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, EDPT_CTRL_IN, - zlp_desc_configuration + CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, true); + zlp_desc_configuration + CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, CFG_TUD_ENDPOINT0_SIZE, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, CFG_TUD_ENDPOINT0_SIZE, 0, false); // Expect Zero length Packet - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_IN, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_IN, 0, 0, false); // Status - dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, true); + dcd_edpt_xfer_ExpectAndReturn(rhport, EDPT_CTRL_OUT, NULL, 0, false, true); dcd_event_xfer_complete(rhport, EDPT_CTRL_OUT, 0, 0, false); dcd_edpt0_status_complete_ExpectWithArray(rhport, &req_get_desc_configuration, 1); diff --git a/test/unit-test/test/support/tusb_config.h b/test/unit-test/test/support/tusb_config.h index 00818fae5..dee24f65d 100644 --- a/test/unit-test/test/support/tusb_config.h +++ b/test/unit-test/test/support/tusb_config.h @@ -23,8 +23,8 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ // testing framework #include "unity.h" @@ -103,4 +103,4 @@ } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif /* TUSB_CONFIG_H_ */ diff --git a/tools/file2carray.py b/tools/file2carray.py new file mode 100644 index 000000000..7150364bf --- /dev/null +++ b/tools/file2carray.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import argparse +import random +import os +import sys +import time +import subprocess +from pathlib import Path +from multiprocessing import Pool +from weakref import finalize + + +def print_carray(f, payload): + while len(payload) > 0: + f.write('\n ') + f.write(', '.join('0x{:02x}'.format(x) for x in payload[0:16])) + f.write(',') + payload = payload[16:] + f.write('\n') + + +def main(): + parser = argparse.ArgumentParser(description='Convert binary files to C array format') + parser.add_argument('files', nargs='+', help='Binary files to convert') + args = parser.parse_args() + + files = args.files + for fin_name in files: + if not os.path.isfile(fin_name): + print(f"File {fin_name} does not exist") + continue + + with open(fin_name, 'rb') as fin: + contents = fin.read() + fout_name = fin_name + '.h' + with open(fout_name, 'w') as fout: + print(f"Converting {fin_name} to {fout_name}") + fout.write(f'enum {{ BINDATA_LEN = {len(contents)} }};\n') + fout.write(f'const size_t bindata_len = BINDATA_LEN;\n') + fout.write(f'const uint8_t bindata[] __attribute__((aligned(16))) = {{') + print_carray(fout, contents) + fout.write('};\n') + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/gen_doc.py b/tools/gen_doc.py index ab07bc116..3920531d5 100755 --- a/tools/gen_doc.py +++ b/tools/gen_doc.py @@ -23,7 +23,7 @@ def gen_deps_doc(): Dependencies ************ -MCU low-level peripheral driver and external libraries for building TinyUSB examples +MCU low-level peripheral drivers and external libraries for building TinyUSB examples {tabulate(df, headers="keys", tablefmt='rst')} """ diff --git a/tools/gen_presets.py b/tools/gen_presets.py index 94b8d16b0..94a9361db 100755 --- a/tools/gen_presets.py +++ b/tools/gen_presets.py @@ -5,13 +5,20 @@ from pathlib import Path def main(): board_list = [] + board_list_esp = [] - # Find all board.cmake files + # Find all board.cmake files, exclude espressif for root, dirs, files in os.walk("hw/bsp"): for file in files: - if file == "board.cmake": + if file == "board.cmake" and "espressif" not in root: board_list.append(os.path.basename(root)) + # Find all espressif boards + for root, dirs, files in os.walk("hw/bsp/espressif"): + for file in files: + if file == "board.cmake": + board_list_esp.append(os.path.basename(root)) + print('Generating presets for the following boards:') print(board_list) @@ -29,8 +36,17 @@ def main(): "cacheVariables": { "CMAKE_DEFAULT_BUILD_TYPE": "RelWithDebInfo", "BOARD": r"${presetName}" + }}, + {"name": "default single config", + "hidden": True, + "description": r"Configure preset for the ${presetName} board", + "generator": "Ninja", + "binaryDir": r"${sourceDir}/build/${presetName}", + "cacheVariables": { + "BOARD": r"${presetName}" }}] + # Add non-espressif boards presets['configurePresets'].extend( sorted( [ @@ -43,6 +59,22 @@ def main(): ) ) + # Add espressif boards with single config generator + presets['configurePresets'].extend( + sorted( + [ + { + 'name': board, + 'inherits': 'default single config' + } + for board in board_list_esp + ], key=lambda x: x['name'] + ) + ) + + # Combine all boards + board_list.extend(board_list_esp) + # Build presets # no inheritance since 'name' doesn't support macro expansion presets['buildPresets'] = sorted( diff --git a/tools/get_deps.py b/tools/get_deps.py index 0828140c1..35f3b3e92 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -47,11 +47,11 @@ deps_optional = { 'b93e856211060ae825216c6a1d6aa347ec758843', 'mm32'], 'hw/mcu/nordic/nrfx': ['https://github.com/NordicSemiconductor/nrfx.git', - '7c47cc0a56ce44658e6da2458e86cd8783ccc4a2', + '11f57e578c7feea13f21c79ea0efab2630ac68c7', 'nrf'], 'hw/mcu/nuvoton': ['https://github.com/majbthrd/nuc_driver.git', '2204191ec76283371419fbcec207da02e1bc22fa', - 'nuc'], + 'nuc100_120 nuc121_125 nuc126 nuc505'], 'hw/mcu/nxp/lpcopen': ['https://github.com/hathach/nxp_lpcopen.git', 'b41cf930e65c734d8ec6de04f1d57d46787c76ae', 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43'], @@ -124,6 +124,9 @@ deps_optional = { 'hw/mcu/st/cmsis_device_n6': ['https://github.com/STMicroelectronics/cmsis-device-n6.git', '7bcdc944fbf7cf5928d3c1d14054ca13261d33ec', 'stm32n6'], + 'hw/mcu/st/cmsis-device-u0': ['https://github.com/STMicroelectronics/cmsis-device-u0.git', + 'e3a627c6a5bc4eb2388e1885a95cc155e1672253', + 'stm32u0'], 'hw/mcu/st/cmsis_device_u5': ['https://github.com/STMicroelectronics/cmsis_device_u5.git', '6e67187dec98035893692ab2923914cb5f4e0117', 'stm32u5'], @@ -190,6 +193,9 @@ deps_optional = { 'hw/mcu/st/stm32n6xx_hal_driver': ['https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git', 'bc6c41f8f67d61b47af26695d0bf67762a000666', 'stm32n6'], + 'hw/mcu/st/stm32u0xx_hal_driver': ['https://github.com/STMicroelectronics/stm32u0xx-hal-driver.git', + 'cbfb5ac654256445237fd32b3587ac6a238d24f1', + 'stm32u0'], 'hw/mcu/st/stm32u5xx_hal_driver': ['https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git', '2c5e2568fbdb1900a13ca3b2901fdd302cac3444', 'stm32u5'], @@ -240,12 +246,12 @@ deps_optional = { 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x ' 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 ' 'stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 ' - 'stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u5 stm32wb stm32wba' + 'stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u0 stm32u5 stm32wb stm32wba' 'sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg ' 'tm4c '], 'lib/CMSIS_6': ['https://github.com/ARM-software/CMSIS_6.git', - 'b0bbb0423b278ca632cfe1474eb227961d835fd2', - 'ra'], + '6f0a58d01aa9bd2feba212097f9afe7acd991d52', + 'ra stm32n6'], 'lib/sct_neopixel': ['https://github.com/gsteiert/sct_neopixel.git', 'e73e04ca63495672d955f9268e003cffe168fcd8', 'lpc55'], diff --git a/tools/iar_gen.py b/tools/iar_gen.py index 8d45659db..571febb2c 100755 --- a/tools/iar_gen.py +++ b/tools/iar_gen.py @@ -74,7 +74,7 @@ def ListPath(path, blacklist=[]): print('</group>') def List(): - ListPath('src', [ 'template.c', 'dcd_synopsys.c', 'dcd_esp32sx.c' ]) + ListPath('src', [ 'template.c' ]) ListPath('lib/SEGGER_RTT') if __name__ == "__main__": diff --git a/tools/iar_template.ipcf b/tools/iar_template.ipcf index 33a6ef045..2581a4702 100644 --- a/tools/iar_template.ipcf +++ b/tools/iar_template.ipcf @@ -58,6 +58,11 @@ <path>$TUSB_DIR$/src/class/msc/msc_device.h</path> <path>$TUSB_DIR$/src/class/msc/msc_host.h</path> </group> + <group name="src/class/mtp"> + <path>$TUSB_DIR$/src/class/mtp/mtp_device.c</path> + <path>$TUSB_DIR$/src/class/mtp/mtp.h</path> + <path>$TUSB_DIR$/src/class/mtp/mtp_device.h</path> + </group> <group name="src/class/net"> <path>$TUSB_DIR$/src/class/net/ecm_rndis_device.c</path> <path>$TUSB_DIR$/src/class/net/ncm_device.c</path> diff --git a/tools/make_release.py b/tools/make_release.py index c1caf3300..71c1e6f64 100755 --- a/tools/make_release.py +++ b/tools/make_release.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 import re import gen_doc +import gen_presets -version = '0.18.0' +version = '0.20.0' print('version {}'.format(version)) ver_id = version.split('.') @@ -45,9 +46,24 @@ with open(f_library_json, 'w') as f: f.write(fdata) ################### -# docs/info/changelog.rst +# sonar-project.properties ################### +f_sonar_properties = 'sonar-project.properties' +with open(f_sonar_properties) as f: + fdata = f.read() +fdata = re.sub(r'(sonar\.projectVersion=)\d+\.\d+\.\d+', r'\g<1>{}'.format(version), fdata) + +with open(f_sonar_properties, 'w') as f: + f.write(fdata) +# gen docs gen_doc.gen_deps_doc() +gen_doc.gen_boards_doc() +# gen presets +gen_presets.main() + +##################(ver# +# docs/info/changelog.rst +################### print("Update docs/info/changelog.rst") |
