summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2025-04-18 14:54:20 +0200
committerHiFiPhile <[email protected]>2025-04-18 14:54:20 +0200
commit4c6736c2779b990e5f97aef7dd1480bf196fede1 (patch)
treee8684c56dad5753e1e94cd2c0727f04d0c4cba2c
parent2064ee470d6c7b434d6b3aafe017ed60c3b17ab5 (diff)
parente44f556a951451fd9123cb822683faac324e0450 (diff)
Merge branch 'master' into dwc2-proper-attach-debouncing
Signed-off-by: HiFiPhile <[email protected]>
-rw-r--r--.circleci/config.yml2
-rw-r--r--.circleci/config2.yml13
-rw-r--r--.github/actions/setup_toolchain/action.yml11
-rw-r--r--.github/actions/setup_toolchain/download/action.yml16
-rw-r--r--.github/actions/setup_toolchain/toolchain.json9
-rw-r--r--.github/workflows/build.yml47
-rw-r--r--.github/workflows/build_util.yml2
-rwxr-xr-x.github/workflows/ci_set_matrix.py7
-rw-r--r--.github/workflows/hil_test.yml4
-rw-r--r--examples/build_system/make/cpu/cortex-m4.mk4
-rw-r--r--examples/device/cdc_msc/src/msc_disk.c193
-rw-r--r--examples/device/msc_dual_lun/src/msc_disk_dual.c29
-rw-r--r--examples/host/msc_file_explorer/Makefile2
-rw-r--r--hw/bsp/BoardPresets.json36
-rw-r--r--hw/bsp/broadcom_32bit/family.mk2
-rw-r--r--hw/bsp/broadcom_64bit/family.mk2
-rw-r--r--hw/bsp/espressif/boards/espressif_p4_function_ev/board.h7
-rw-r--r--hw/bsp/espressif/boards/espressif_s2_devkitc/board.h10
-rw-r--r--hw/bsp/espressif/boards/espressif_s3_devkitc/board.h2
-rw-r--r--hw/bsp/espressif/boards/espressif_s3_devkitm/board.h5
-rw-r--r--hw/bsp/espressif/boards/family.c8
-rw-r--r--hw/bsp/espressif/family.cmake2
-rw-r--r--hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk2
-rw-r--r--hw/bsp/lpc15/family.mk2
-rw-r--r--hw/bsp/lpc17/family.mk2
-rw-r--r--hw/bsp/lpc18/family.mk2
-rw-r--r--hw/bsp/lpc40/family.mk2
-rw-r--r--hw/bsp/lpc43/family.mk6
-rw-r--r--hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake2
-rw-r--r--hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.h70
-rw-r--r--hw/bsp/rp2040/skip_ci.txt7
-rw-r--r--hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk7
-rw-r--r--hw/bsp/stm32f2/family.mk13
-rw-r--r--hw/bsp/stm32f3/boards/stm32f303disco/board.mk4
-rw-r--r--hw/bsp/stm32f3/family.mk18
-rw-r--r--hw/bsp/stm32f4/family.mk1
-rw-r--r--hw/bsp/stm32h7/boards/stm32h743eval/board.h10
-rw-r--r--hw/bsp/stm32h7/family.c4
-rw-r--r--hw/bsp/stm32h7/family.mk4
-rw-r--r--hw/bsp/stm32l0/boards/stm32l052dap52/board.mk3
-rw-r--r--hw/bsp/stm32l0/boards/stm32l0538disco/board.mk4
-rw-r--r--hw/bsp/stm32l0/family.mk19
-rw-r--r--hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk4
-rw-r--r--hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk4
-rw-r--r--hw/bsp/stm32u5/boards/stm32u575eval/board.mk4
-rw-r--r--hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk4
-rw-r--r--hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk4
-rw-r--r--hw/bsp/stm32u5/family.mk7
-rw-r--r--hw/bsp/stm32wb/family.mk21
-rw-r--r--src/class/msc/msc_device.c5
-rw-r--r--src/common/tusb_debug.h6
-rw-r--r--src/host/usbh.c122
-rw-r--r--src/portable/synopsys/dwc2/dcd_dwc2.c104
-rw-r--r--src/portable/synopsys/dwc2/dwc2_common.c16
-rw-r--r--src/portable/synopsys/dwc2/dwc2_type.h947
-rw-r--r--src/portable/synopsys/dwc2/hcd_dwc2.c257
-rw-r--r--src/portable/template/hcd_template.c5
-rw-r--r--src/tusb_option.h2
-rwxr-xr-xtest/hil/hil_test.py103
-rw-r--r--test/hil/tinyusb.json22
-rwxr-xr-xtools/build.py7
61 files changed, 1189 insertions, 1050 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index fd5631e2e..0b11b50e4 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -20,12 +20,12 @@ jobs:
BUILDSYSTEM_TOOLCHAIN=(
"cmake arm-clang"
+ "cmake esp-idf"
"make aarch64-gcc"
"make arm-gcc"
"make msp430-gcc"
"make riscv-gcc"
"make rx-gcc"
- "cmake esp-idf"
)
# only build IAR if not forked PR, since IAR token is not shared
diff --git a/.circleci/config2.yml b/.circleci/config2.yml
index 3b0294168..d86a3f662 100644
--- a/.circleci/config2.yml
+++ b/.circleci/config2.yml
@@ -10,17 +10,7 @@ commands:
- run:
name: Set toolchain url and key
command: |
- TOOLCHAIN_JSON='{
- "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz",
- "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz",
- "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v13.2.1-1.1/xpack-arm-none-eabi-gcc-13.2.1-1.1-linux-x64.tar.gz",
- "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://updates.iar.com/FileStore/STANDARD/001/003/322/cxarm-9.60.3.deb"
- }'
- toolchain_url=$(echo $TOOLCHAIN_JSON | jq -r '.["<< parameters.toolchain >>"]')
-
+ toolchain_url=$(jq -r '."<< parameters.toolchain >>"' .github/actions/setup_toolchain/toolchain.json)
# only cache if not a github link
if [[ $toolchain_url != "https://github.com"* ]]; then
echo "<< parameters.toolchain >>-$toolchain_url" > toolchain_key
@@ -121,7 +111,6 @@ commands:
TOOLCHAIN_OPTION="--toolchain clang"
elif [ << parameters.toolchain >> == arm-iar ]; then
TOOLCHAIN_OPTION="--toolchain iar"
- echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL
iccarm --version
elif [ << parameters.toolchain >> == arm-gcc ]; then
TOOLCHAIN_OPTION="--toolchain gcc"
diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml
index 8305daa24..850a3a06f 100644
--- a/.github/actions/setup_toolchain/action.yml
+++ b/.github/actions/setup_toolchain/action.yml
@@ -28,18 +28,10 @@ runs:
- name: Get Toolchain URL
if: >-
inputs.toolchain != 'arm-gcc' &&
- inputs.toolchain != 'arm-iar' &&
inputs.toolchain != 'esp-idf'
id: set-toolchain-url
run: |
- TOOLCHAIN_JSON='{
- "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz",
- "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz",
- "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"
- }'
- TOOLCHAIN_URL=$(echo $TOOLCHAIN_JSON | jq -r '.["${{ inputs.toolchain }}"]')
+ TOOLCHAIN_URL=$(jq -r '."${{ inputs.toolchain }}"' .github/actions/setup_toolchain/toolchain.json)
echo "toolchain_url=$TOOLCHAIN_URL"
echo "toolchain_url=$TOOLCHAIN_URL" >> $GITHUB_OUTPUT
shell: bash
@@ -47,7 +39,6 @@ runs:
- name: Download Toolchain
if: >-
inputs.toolchain != 'arm-gcc' &&
- inputs.toolchain != 'arm-iar' &&
inputs.toolchain != 'esp-idf'
uses: ./.github/actions/setup_toolchain/download
with:
diff --git a/.github/actions/setup_toolchain/download/action.yml b/.github/actions/setup_toolchain/download/action.yml
index 813197208..ce9643010 100644
--- a/.github/actions/setup_toolchain/download/action.yml
+++ b/.github/actions/setup_toolchain/download/action.yml
@@ -23,17 +23,25 @@ runs:
if: steps.cache-toolchain-download.outputs.cache-hit != 'true'
run: |
mkdir -p ~/cache/${{ inputs.toolchain }}
- wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.tar.gz
+
if [[ ${{ inputs.toolchain }} == rx-gcc ]]; then
- mv toolchain.tar.gz toolchain.run
+ wget --progress=dot:giga ${{ inputs.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
else
+ wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.tar.gz
tar -C ~/cache/${{ inputs.toolchain }} -xaf toolchain.tar.gz
fi
shell: bash
- - name: Set Toolchain Path
+ - name: Setup Toolchain
run: |
- echo >> $GITHUB_PATH `echo ~/cache/${{ inputs.toolchain }}/*/bin`
+ if [[ ${{ inputs.toolchain }} == arm-iar ]]; then
+ sudo apt-get install -y ~/cache/${{ inputs.toolchain }}/cxarm.deb
+ echo >> $GITHUB_PATH "/opt/iar/cxarm/arm/bin"
+ else
+ echo >> $GITHUB_PATH `echo ~/cache/${{ inputs.toolchain }}/*/bin`
+ fi
shell: bash
diff --git a/.github/actions/setup_toolchain/toolchain.json b/.github/actions/setup_toolchain/toolchain.json
new file mode 100644
index 000000000..4e65f1cbe
--- /dev/null
+++ b/.github/actions/setup_toolchain/toolchain.json
@@ -0,0 +1,9 @@
+{
+ "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz",
+ "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz",
+ "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v13.2.1-1.1/xpack-arm-none-eabi-gcc-13.2.1-1.1-linux-x64.tar.gz",
+ "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"
+}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 547763bd8..17d578e4d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -85,7 +85,7 @@ jobs:
- 'msp430-gcc'
- 'riscv-gcc'
- 'rx-gcc'
- - 'esp-idf' # build-system is ignored
+ - 'esp-idf'
with:
build-system: 'make'
toolchain: ${{ matrix.toolchain }}
@@ -110,37 +110,26 @@ jobs:
one-per-family: true
# ---------------------------------------
- # Build IAR on HFP self-hosted
- # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo
+ # Build IAR
+ # Since IAR Token secret is not passed to forked PR, only build non-forked PR with make.
+ # cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family
# ---------------------------------------
arm-iar:
- if: github.repository_owner == 'hathach' && github.event_name == 'push'
+ if: false # disable for now since we got reach capacity limit too often
+ #if: github.event_name == 'push' && github.repository_owner == 'hathach'
needs: set-matrix
- runs-on: [self-hosted, Linux, X64, hifiphile]
- env:
- BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'], ' ') }}
- IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }}
- IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }}
- steps:
- - name: Clean workspace
- run: |
- echo "Cleaning up previous run"
- rm -rf "${{ github.workspace }}"
- mkdir -p "${{ github.workspace }}"
-
- - name: Toolchain version
- run: |
- echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL
- iccarm --version
-
- - name: Checkout TinyUSB
- uses: actions/checkout@v4
-
- - name: Get Dependencies
- run: python3 tools/get_deps.py $BUILD_ARGS
-
- - name: Build
- run: python3 tools/build.py --one-per-family --toolchain iar $BUILD_ARGS
+ uses: ./.github/workflows/build_util.yml
+ secrets: inherit
+ strategy:
+ fail-fast: false
+ matrix:
+ build-system:
+ - 'make'
+ with:
+ build-system: ${{ matrix.build-system }}
+ toolchain: 'arm-iar'
+ build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }}
+ one-per-family: true
# ---------------------------------------
# Zephyr
diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml
index 2de68c6f3..a2c96f3c0 100644
--- a/.github/workflows/build_util.yml
+++ b/.github/workflows/build_util.yml
@@ -58,6 +58,8 @@ jobs:
shell: bash
- name: Build
+ env:
+ IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }}
run: |
if [ "${{ inputs.toolchain }}" == "esp-idf" ]; then
docker run --rm -v $PWD:/project -w /project espressif/idf:tinyusb python tools/build.py ${{ matrix.arg }}
diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py
index 410508246..fa73dc1b6 100755
--- a/.github/workflows/ci_set_matrix.py
+++ b/.github/workflows/ci_set_matrix.py
@@ -44,9 +44,10 @@ family_list = {
"stm32l0 stm32l4": ["arm-gcc", "arm-clang", "arm-iar"],
"stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"],
"xmc4000": ["arm-gcc"],
- "-bespressif_kaluga_1": ["esp-idf"],
- "-bespressif_s3_devkitm": ["esp-idf"],
- "-bespressif_p4_function_ev": ["esp-idf"],
+ "-bespressif_s2_devkitc": ["esp-idf"],
+ # S3, P4 will be built by hil test
+ # "-bespressif_s3_devkitm": ["esp-idf"],
+ # "-bespressif_p4_function_ev": ["esp-idf"],
}
diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml
index c890933ec..0ad37ffce 100644
--- a/.github/workflows/hil_test.yml
+++ b/.github/workflows/hil_test.yml
@@ -90,13 +90,12 @@ jobs:
# ---------------------------------------
# Hardware in the loop (HIL)
# self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json
- # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo
+ # Since IAR Token secret is not passed to forked PR, only build non-forked PR
# ---------------------------------------
hil-hfp:
if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false
runs-on: [self-hosted, Linux, X64, hifiphile]
env:
- IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }}
IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }}
steps:
- name: Clean workspace
@@ -107,7 +106,6 @@ jobs:
- name: Toolchain version
run: |
- echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL
iccarm --version
- name: Checkout TinyUSB
diff --git a/examples/build_system/make/cpu/cortex-m4.mk b/examples/build_system/make/cpu/cortex-m4.mk
index 4e16819d1..57d6e126d 100644
--- a/examples/build_system/make/cpu/cortex-m4.mk
+++ b/examples/build_system/make/cpu/cortex-m4.mk
@@ -12,8 +12,8 @@ else ifeq ($(TOOLCHAIN),clang)
-mfpu=fpv4-sp-d16 \
else ifeq ($(TOOLCHAIN),iar)
- CFLAGS += --cpu cortex-m4 --fpu VFPv4
- ASFLAGS += --cpu cortex-m4 --fpu VFPv4
+ CFLAGS += --cpu cortex-m4 --fpu VFPv4-SP
+ ASFLAGS += --cpu cortex-m4 --fpu VFPv4-SP
else
$(error "TOOLCHAIN is not supported")
diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c
index d325d77fa..9645f4bfc 100644
--- a/examples/device/cdc_msc/src/msc_disk.c
+++ b/examples/device/cdc_msc/src/msc_disk.c
@@ -40,17 +40,15 @@ static bool ejected = false;
If you find any bugs or get any questions, feel free to file an\r\n\
issue at github.com/hathach/tinyusb"
-enum
-{
- DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount
+enum {
+ DISK_BLOCK_NUM = 16,// 8KB is the smallest size that windows allow to mount
DISK_BLOCK_SIZE = 512
};
#ifdef CFG_EXAMPLE_MSC_READONLY
const
#endif
-uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
-{
+uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = {
//------------- Block0: Boot Sector -------------//
// byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM;
// sector_per_cluster = 1; reserved_sectors = 1;
@@ -59,60 +57,59 @@ 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 -------------//
@@ -121,23 +118,21 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
// Invoked when received SCSI_CMD_INQUIRY
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
-void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
-{
+void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
(void) lun;
const char vid[] = "TinyUSB";
const char pid[] = "Mass Storage";
const char rev[] = "1.0";
- memcpy(vendor_id , vid, strlen(vid));
- memcpy(product_id , pid, strlen(pid));
+ memcpy(vendor_id, vid, strlen(vid));
+ memcpy(product_id, pid, strlen(pid));
memcpy(product_rev, rev, strlen(rev));
}
// 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)
-{
+bool tud_msc_test_unit_ready_cb(uint8_t lun) {
(void) lun;
// RAM disk is ready until ejected
@@ -152,29 +147,24 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun)
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
// Application update block count and block size
-void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* 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;
+ *block_size = DISK_BLOCK_SIZE;
}
// Invoked when received Start Stop Unit command
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
-bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
-{
+bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
(void) lun;
(void) power_condition;
- if ( load_eject )
- {
- if (start)
- {
+ if (load_eject) {
+ if (start) {
// load disk storage
- }else
- {
+ } else {
// unload disk storage
ejected = true;
}
@@ -185,52 +175,51 @@ 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 ) {
+ if (lba >= DISK_BLOCK_NUM) {
return -1;
}
// Check for overflow of offset + bufsize
- if ( offset + bufsize > DISK_BLOCK_SIZE ) {
+ if (offset + bufsize > DISK_BLOCK_SIZE) {
return -1;
}
- uint8_t const* addr = msc_disk[lba] + offset;
+ uint8_t const *addr = msc_disk[lba] + offset;
memcpy(buffer, addr, bufsize);
return (int32_t) bufsize;
}
-bool tud_msc_is_writable_cb (uint8_t lun)
-{
+bool tud_msc_is_writable_cb(uint8_t lun) {
(void) lun;
-#ifdef CFG_EXAMPLE_MSC_READONLY
+ #ifdef CFG_EXAMPLE_MSC_READONLY
return false;
-#else
+ #else
return true;
-#endif
+ #endif
}
// 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;
+ #ifndef CFG_EXAMPLE_MSC_READONLY
+ uint8_t *addr = msc_disk[lba] + offset;
memcpy(addr, buffer, bufsize);
-#else
- (void) lba; (void) offset; (void) buffer;
-#endif
+ #else
+ (void) lba;
+ (void) offset;
+ (void) buffer;
+ #endif
return (int32_t) bufsize;
}
@@ -238,42 +227,18 @@ 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)
-{
- // read10 & write10 has their own callback and MUST not be handled here
-
- void const* response = NULL;
- int32_t resplen = 0;
+int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) {
+ (void) buffer;
+ (void) bufsize;
- // 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 (int32_t) resplen;
}
#endif
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 b44b77c6c..1f7fb98c7 100644
--- a/examples/device/msc_dual_lun/src/msc_disk_dual.c
+++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c
@@ -55,8 +55,7 @@ If you find any bugs or get any questions, feel free to file an\r\n\
issue at github.com/hathach/tinyusb"
-MSC_CONST uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
-{
+MSC_CONST uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = {
//------------- Block0: Boot Sector -------------//
// byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM;
// sector_per_cluster = 1; reserved_sectors = 1;
@@ -283,9 +282,11 @@ bool tud_msc_is_writable_cb(uint8_t lun) {
// 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) {
// out of ramdisk
- if (lba >= DISK_BLOCK_NUM) return -1;
+ if (lba >= DISK_BLOCK_NUM) {
+ return -1;
+ }
-#if defined(CFG_EXAMPLE_MSC_READONLY) || defined(CFG_EXAMPLE_MSC_DUAL_READONLY)
+ #if defined(CFG_EXAMPLE_MSC_READONLY) || defined(CFG_EXAMPLE_MSC_DUAL_READONLY)
(void) lun;
(void) lba;
(void) offset;
@@ -302,11 +303,8 @@ 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 (MUST not be handled here)
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) {
- 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:
@@ -316,19 +314,6 @@ int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, u
// negative means error -> tinyusb could stall and/or response with failed status
return -1;
}
-
- // 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 resplen;
}
#endif
diff --git a/examples/host/msc_file_explorer/Makefile b/examples/host/msc_file_explorer/Makefile
index c7d6a7cae..f0872376f 100644
--- a/examples/host/msc_file_explorer/Makefile
+++ b/examples/host/msc_file_explorer/Makefile
@@ -22,6 +22,6 @@ SRC_C += \
$(FATFS_PATH)/ffunicode.c \
# suppress warning caused by fatfs
-CFLAGS += -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=cast-qual
include ../../build_system/make/rules.mk
diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json
index fee8f2c97..24da362da 100644
--- a/hw/bsp/BoardPresets.json
+++ b/hw/bsp/BoardPresets.json
@@ -13,20 +13,30 @@
}
},
{
+ "name": "default single",
+ "hidden": true,
+ "description": "Configure preset for the ${presetName} board",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build/${presetName}",
+ "cacheVariables": {
+ "BOARD": "${presetName}"
+ }
+ },
+ {
"name": "adafruit_clue",
"inherits": "default"
},
{
"name": "adafruit_feather_esp32_v2",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "adafruit_feather_esp32s2",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "adafruit_feather_esp32s3",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "adafruit_magtag_29gray",
@@ -34,7 +44,7 @@
},
{
"name": "adafruit_metro_esp32s2",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "apard32690",
@@ -130,39 +140,39 @@
},
{
"name": "espressif_addax_1",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_c3_devkitc",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_c6_devkitc",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_kaluga_1",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_p4_function_ev",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_s2_devkitc",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_s3_devkitc",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_s3_devkitm",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "espressif_saola_1",
- "inherits": "default"
+ "inherits": "default single"
},
{
"name": "f1c100s",
diff --git a/hw/bsp/broadcom_32bit/family.mk b/hw/bsp/broadcom_32bit/family.mk
index a282e9961..9d4a3b76c 100644
--- a/hw/bsp/broadcom_32bit/family.mk
+++ b/hw/bsp/broadcom_32bit/family.mk
@@ -15,7 +15,7 @@ CFLAGS += \
CROSS_COMPILE = arm-none-eabi-
# mcu driver cause following warnings
-CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls
+CFLAGS_GCC += -Wno-error=cast-qual -Wno-error=redundant-decls
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
diff --git a/hw/bsp/broadcom_64bit/family.mk b/hw/bsp/broadcom_64bit/family.mk
index 37d381f9f..1ce80e22b 100644
--- a/hw/bsp/broadcom_64bit/family.mk
+++ b/hw/bsp/broadcom_64bit/family.mk
@@ -14,7 +14,7 @@ CFLAGS += \
CROSS_COMPILE = aarch64-none-elf-
# mcu driver cause following warnings
-CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls
+CFLAGS_GCC += -Wno-error=cast-qual -Wno-error=redundant-decls
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
diff --git a/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h b/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h
index 6f3229b70..40c4963d9 100644
--- a/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h
+++ b/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h
@@ -41,9 +41,10 @@
#define BUTTON_PIN 35
#define BUTTON_STATE_ACTIVE 0
-// For CI hardware test, to test both device and host on the same HS port with help of
-#define HIL_DEVICE_HOST_MUX_PIN 47
-#define HIL_DEVICE_STATE 1
+// For CI hardware test, to test both device and host on the same HS port with help of TS3USB30
+// https://www.adafruit.com/product/5871
+#define HIL_TS3USB30_MODE_PIN 47
+#define HIL_TS3USB30_MODE_DEVICE 1
#ifdef __cplusplus
}
diff --git a/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h
index 9c197591f..499a626a6 100644
--- a/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h
+++ b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h
@@ -36,13 +36,19 @@
extern "C" {
#endif
-// Note: On the production version (v1.2) WS2812 is connected to GPIO 18,
-// however earlier revision v1.1 WS2812 is connected to GPIO 17
#define NEOPIXEL_PIN 18
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 36
+#define MAX3421_MOSI_PIN 35
+#define MAX3421_MISO_PIN 37
+#define MAX3421_CS_PIN 15
+#define MAX3421_INTR_PIN 14
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h
index 6d7a94668..d2483c84f 100644
--- a/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h
+++ b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h
@@ -36,7 +36,7 @@
extern "C" {
#endif
-#define NEOPIXEL_PIN 48
+#define NEOPIXEL_PIN 38
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0
diff --git a/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h
index d01fdbe5b..5c1914ebe 100644
--- a/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h
+++ b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h
@@ -49,6 +49,11 @@
#define MAX3421_CS_PIN 15
#define MAX3421_INTR_PIN 14
+// For CI hardware test, to test both device and host on the same HS port with help of TS3USB30
+// https://www.adafruit.com/product/5871
+#define HIL_TS3USB30_MODE_PIN 47
+#define HIL_TS3USB30_MODE_DEVICE 1
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c
index 7049c0415..cf11e2441 100644
--- a/hw/bsp/espressif/boards/family.c
+++ b/hw/bsp/espressif/boards/family.c
@@ -92,10 +92,10 @@ void board_init(void) {
usb_init();
#endif
-#ifdef HIL_DEVICE_HOST_MUX_PIN
- gpio_reset_pin(HIL_DEVICE_HOST_MUX_PIN);
- gpio_set_direction(HIL_DEVICE_HOST_MUX_PIN, GPIO_MODE_OUTPUT);
- gpio_set_level(HIL_DEVICE_HOST_MUX_PIN, CFG_TUD_ENABLED ? HIL_DEVICE_STATE : (1-HIL_DEVICE_STATE));
+#ifdef HIL_TS3USB30_MODE_PIN
+ gpio_reset_pin(HIL_TS3USB30_MODE_PIN);
+ gpio_set_direction(HIL_TS3USB30_MODE_PIN, GPIO_MODE_OUTPUT);
+ gpio_set_level(HIL_TS3USB30_MODE_PIN, CFG_TUD_ENABLED ? HIL_TS3USB30_MODE_DEVICE : (1-HIL_TS3USB30_MODE_DEVICE));
#endif
#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
diff --git a/hw/bsp/espressif/family.cmake b/hw/bsp/espressif/family.cmake
index daa12cdb4..b544689d9 100644
--- a/hw/bsp/espressif/family.cmake
+++ b/hw/bsp/espressif/family.cmake
@@ -34,6 +34,6 @@ endif ()
set(EXTRA_COMPONENT_DIRS "src" "${CMAKE_CURRENT_LIST_DIR}/boards" "${CMAKE_CURRENT_LIST_DIR}/components")
# set SDKCONFIG for each IDF Target
-set(SDKCONFIG ${CMAKE_SOURCE_DIR}/sdkconfig.${IDF_TARGET})
+set(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk
index c4dc65b63..fb3eb2a03 100644
--- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk
+++ b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk
@@ -3,7 +3,7 @@ MCU = K32L2A41A
CFLAGS += -DCPU_K32L2A41VLH1A
# mcu driver cause following warnings
-CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast-qual
# All source paths should be relative to the top level.
LD_FILE = $(MCU_DIR)/gcc/K32L2A41xxxxA_flash.ld
diff --git a/hw/bsp/lpc15/family.mk b/hw/bsp/lpc15/family.mk
index b83e008e8..3b63580c0 100644
--- a/hw/bsp/lpc15/family.mk
+++ b/hw/bsp/lpc15/family.mk
@@ -15,7 +15,7 @@ CFLAGS += \
LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
# mcu driver cause following warnings
-CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=cast-qual
MCU_DIR = hw/mcu/nxp/lpcopen/lpc15xx/lpc_chip_15xx
diff --git a/hw/bsp/lpc17/family.mk b/hw/bsp/lpc17/family.mk
index d719a47b7..551eb9e62 100644
--- a/hw/bsp/lpc17/family.mk
+++ b/hw/bsp/lpc17/family.mk
@@ -13,7 +13,7 @@ CFLAGS += \
-DRTC_EV_SUPPORT=0
# lpc_types.h cause following errors
-CFLAGS += -Wno-error=strict-prototypes -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=strict-prototypes -Wno-error=cast-qual
# caused by freeRTOS port !!
CFLAGS += -Wno-error=maybe-uninitialized
diff --git a/hw/bsp/lpc18/family.mk b/hw/bsp/lpc18/family.mk
index f120f63b2..87b831255 100644
--- a/hw/bsp/lpc18/family.mk
+++ b/hw/bsp/lpc18/family.mk
@@ -12,7 +12,7 @@ CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_LPC18XX
# mcu driver cause following warnings
-CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=unused-parameter -Wno-error=cast-qual
LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs
diff --git a/hw/bsp/lpc40/family.mk b/hw/bsp/lpc40/family.mk
index ef9fe57b2..06155c760 100644
--- a/hw/bsp/lpc40/family.mk
+++ b/hw/bsp/lpc40/family.mk
@@ -13,7 +13,7 @@ CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_LPC40XX
# mcu driver cause following warnings
-CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=cast-qual
+CFLAGS_GCC += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=cast-qual
LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs
diff --git a/hw/bsp/lpc43/family.mk b/hw/bsp/lpc43/family.mk
index e1406aae7..4a2ba6ec3 100644
--- a/hw/bsp/lpc43/family.mk
+++ b/hw/bsp/lpc43/family.mk
@@ -5,14 +5,14 @@ include ${TOP}/${BOARD_PATH}/board.mk
CPU_CORE ?= cortex-m4
CFLAGS += \
- -flto \
- -nostdlib \
-DCORE_M4 \
-D__USE_LPCOPEN \
-DCFG_TUSB_MCU=OPT_MCU_LPC43XX
# mcu driver cause following warnings
-CFLAGS += \
+CFLAGS_GCC += \
+ -flto \
+ -nostdlib \
-Wno-error=unused-parameter \
-Wno-error=cast-qual \
-Wno-error=incompatible-pointer-types \
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake
new file mode 100644
index 000000000..97621d855
--- /dev/null
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake
@@ -0,0 +1,2 @@
+set(PICO_PLATFORM rp2040)
+set(PICO_BOARD pico_w)
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.h
new file mode 100644
index 000000000..8af32fc9e
--- /dev/null
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.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.
+ */
+
+/* metadata:
+ name: Pico
+ url: https://www.raspberrypi.com/products/raspberry-pi-pico/
+*/
+
+#ifndef TUSB_BOARD_H
+#define TUSB_BOARD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// UART and LED are already defined in pico-sdk board
+
+//--------------------------------------------------------------------+
+// PIO_USB
+//--------------------------------------------------------------------+
+// default to pico brain tester
+#define PICO_DEFAULT_PIO_USB_DP_PIN 20
+#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 22
+#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
+
+//--------------------------------------------------------------------
+// USB Host MAX3421E
+//--------------------------------------------------------------------
+
+#ifdef PICO_DEFAULT_SPI
+#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2
+#else
+#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1
+#endif
+
+#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN
+#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN
+#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN
+#define MAX3421_CS_PIN 10
+#define MAX3421_INTR_PIN 9
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/skip_ci.txt b/hw/bsp/rp2040/skip_ci.txt
new file mode 100644
index 000000000..fe99c9f65
--- /dev/null
+++ b/hw/bsp/rp2040/skip_ci.txt
@@ -0,0 +1,7 @@
+# boards in this files are skipped when running CI with this family
+adafruit_feather_rp2040_usb_host
+adafruit_fruit_jam
+adafruit_metro_rp2350
+feather_rp2040_max3421
+pico_sdk
+raspberry_pi_pico_w
diff --git a/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk b/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk
index ba185d199..6e681ef57 100644
--- a/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk
+++ b/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk
@@ -1,12 +1,9 @@
-CFLAGS += \
- -DSTM32F207xx \
+MCU_VARIANT = stm32f207xx
+CFLAGS += -DSTM32F207xx
# All source paths should be relative to the top level.
LD_FILE = $(BOARD_PATH)/STM32F207ZGTx_FLASH.ld
-SRC_S += \
- $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f207xx.s
-
# For flash-jlink target
JLINK_DEVICE = stm32f207zg
diff --git a/hw/bsp/stm32f2/family.mk b/hw/bsp/stm32f2/family.mk
index 7af9a76a0..e8f02548d 100644
--- a/hw/bsp/stm32f2/family.mk
+++ b/hw/bsp/stm32f2/family.mk
@@ -1,5 +1,4 @@
ST_FAMILY = f2
-
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
@@ -14,11 +13,10 @@ CPU_CORE ?= cortex-m3
CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_STM32F2
+# mcu driver cause following warnings
CFLAGS_GCC += \
-flto \
-
-# mcu driver cause following warnings
-CFLAGS_GCC += -Wno-error=sign-compare
+ -Wno-error=sign-compare
LDFLAGS_GCC += \
-nostdlib -nostartfiles \
@@ -40,3 +38,10 @@ INC += \
$(TOP)/$(ST_CMSIS)/Include \
$(TOP)/$(ST_HAL_DRIVER)/Inc \
$(TOP)/$(BOARD_PATH)
+
+# 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/stm32f3/boards/stm32f303disco/board.mk b/hw/bsp/stm32f3/boards/stm32f303disco/board.mk
index e387f2d54..6b9a3e283 100644
--- a/hw/bsp/stm32f3/boards/stm32f303disco/board.mk
+++ b/hw/bsp/stm32f3/boards/stm32f303disco/board.mk
@@ -1,12 +1,10 @@
+MCU_VARIANT = stm32f303xc
CFLAGS += \
-DSTM32F303xC \
# All source paths should be relative to the top level.
LD_FILE = $(BOARD_PATH)/STM32F303VCTx_FLASH.ld
-SRC_S += \
- $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f303xc.s
-
# For flash-jlink target
JLINK_DEVICE = stm32f303vc
diff --git a/hw/bsp/stm32f3/family.mk b/hw/bsp/stm32f3/family.mk
index 4fe3aa99d..13734583a 100644
--- a/hw/bsp/stm32f3/family.mk
+++ b/hw/bsp/stm32f3/family.mk
@@ -1,22 +1,17 @@
ST_FAMILY = f3
-
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
-DEPS_SUBMODULES += \
- lib/CMSIS_5 \
- $(ST_CMSIS) \
- $(ST_HAL_DRIVER)
-
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS += \
- -flto \
-DCFG_TUSB_MCU=OPT_MCU_STM32F3
# mcu driver cause following warnings
-CFLAGS += -Wno-error=unused-parameter
+CFLAGS_GCC += \
+ -flto \
+ -Wno-error=unused-parameter
LDFLAGS_GCC += \
-nostdlib -nostartfiles \
@@ -36,3 +31,10 @@ INC += \
$(TOP)/$(ST_CMSIS)/Include \
$(TOP)/$(ST_HAL_DRIVER)/Inc \
$(TOP)/$(BOARD_PATH)
+
+# 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/stm32f4/family.mk b/hw/bsp/stm32f4/family.mk
index 51ff43a60..c3c41dc3f 100644
--- a/hw/bsp/stm32f4/family.mk
+++ b/hw/bsp/stm32f4/family.mk
@@ -1,6 +1,5 @@
UF2_FAMILY_ID = 0x57755a57
ST_FAMILY = f4
-DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/board.h b/hw/bsp/stm32h7/boards/stm32h743eval/board.h
index 334876e51..7c3f6414a 100644
--- a/hw/bsp/stm32h7/boards/stm32h743eval/board.h
+++ b/hw/bsp/stm32h7/boards/stm32h743eval/board.h
@@ -184,7 +184,7 @@ static MFXSTM32L152_Object_t mfx_obj = { 0 };
static MFXSTM32L152_IO_Mode_t* mfx_io = NULL;
static uint32_t mfx_vbus_pin[2] = { MFXSTM32L152_GPIO_PIN_7, MFXSTM32L152_GPIO_PIN_9 };
-int32_t board_i2c_init(void) {
+static int32_t board_i2c_init(void) {
__HAL_RCC_I2C1_CLK_ENABLE();
__HAL_RCC_I2C1_FORCE_RESET();
__HAL_RCC_I2C1_RELEASE_RESET();
@@ -200,16 +200,16 @@ int32_t board_i2c_init(void) {
return 0;
}
-int32_t board_i2c_deinit(void) {
+static int32_t board_i2c_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;
}
@@ -249,7 +249,7 @@ static inline void board_init2(void) {
}
// VBUS1 is actually controlled by USB3320C PHY (using dwc2 drivebus signal)
-void board_vbus_set(uint8_t rhport, bool state) {
+static void TU_ATTR_UNUSED board_vbus_set(uint8_t rhport, bool state) {
if (mfx_io) {
mfx_io->IO_WritePin(&mfx_obj, mfx_vbus_pin[rhport], state);
}
diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c
index e5228b29b..f8723b0c7 100644
--- a/hw/bsp/stm32h7/family.c
+++ b/hw/bsp/stm32h7/family.c
@@ -80,7 +80,7 @@ void OTG_HS_IRQHandler(void) {
}
#ifdef TRACE_ETM
-void trace_etm_init(void) {
+static void trace_etm_init(void) {
// H7 trace pin is PE2 to PE6
GPIO_InitTypeDef gpio_init;
gpio_init.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
@@ -94,7 +94,7 @@ void trace_etm_init(void) {
DBGMCU->CR |= DBGMCU_CR_DBG_TRACECKEN | DBGMCU_CR_DBG_CKD1EN | DBGMCU_CR_DBG_CKD3EN;
}
#else
- #define trace_etm_init()
+#define trace_etm_init()
#endif
void board_init(void) {
diff --git a/hw/bsp/stm32h7/family.mk b/hw/bsp/stm32h7/family.mk
index 29b83cf7d..19a085424 100644
--- a/hw/bsp/stm32h7/family.mk
+++ b/hw/bsp/stm32h7/family.mk
@@ -45,11 +45,9 @@ CFLAGS += \
-DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \
# GCC Flags
-CFLAGS_GCC += \
- -flto \
-
# suppress warning caused by vendor mcu driver
CFLAGS_GCC += \
+ -flto \
-Wno-error=cast-align \
-Wno-error=unused-parameter \
diff --git a/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk b/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk
index 0b1348474..e63b41f12 100644
--- a/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk
+++ b/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk
@@ -1,10 +1,9 @@
+MCU_VARIANT = stm32l052xx
CFLAGS += \
-DSTM32L052xx
LD_FILE = $(BOARD_PATH)/STM32L052K8Ux_FLASH.ld
-SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l052xx.s
-
# For flash-jlink target
JLINK_DEVICE = stm32l052k8
diff --git a/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk b/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk
index deed519ba..f3e6978b0 100644
--- a/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk
+++ b/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk
@@ -1,12 +1,10 @@
+MCU_VARIANT = stm32l053xx
CFLAGS += \
-DSTM32L053xx
# All source paths should be relative to the top level.
LD_FILE = $(BOARD_PATH)/STM32L053C8Tx_FLASH.ld
-SRC_S += \
- $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l053xx.s
-
# For flash-jlink target
JLINK_DEVICE = STM32L053R8
diff --git a/hw/bsp/stm32l0/family.mk b/hw/bsp/stm32l0/family.mk
index fe7561fc2..921b1b413 100644
--- a/hw/bsp/stm32l0/family.mk
+++ b/hw/bsp/stm32l0/family.mk
@@ -1,9 +1,4 @@
ST_FAMILY = l0
-DEPS_SUBMODULES += \
- lib/CMSIS_5 \
- hw/mcu/st/cmsis_device_$(ST_FAMILY) \
- hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
-
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
@@ -11,20 +6,17 @@ include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m0plus
CFLAGS += \
- -flto \
-DCFG_EXAMPLE_MSC_READONLY \
-DCFG_EXAMPLE_VIDEO_READONLY \
-DCFG_TUSB_MCU=OPT_MCU_STM32L0
# mcu driver cause following warnings
CFLAGS_GCC += \
+ -flto \
-Wno-error=unused-parameter \
-Wno-error=redundant-decls \
-Wno-error=cast-align \
-
-ifeq ($(TOOLCHAIN),gcc)
-CFLAGS_GCC += -Wno-error=maybe-uninitialized
-endif
+ -Wno-error=maybe-uninitialized \
CFLAGS_CLANG += \
-Wno-error=parentheses-equality
@@ -48,3 +40,10 @@ INC += \
$(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/stm32u5/boards/b_u585i_iot2a/board.mk b/hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk
index ae63afef3..0a2c47030 100644
--- a/hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk
+++ b/hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk
@@ -1,11 +1,9 @@
+MCU_VARIANT = stm32u585xx
CFLAGS += \
-DSTM32U585xx \
# All source paths should be relative to the top level.
LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld
-SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s
-
-MCU_VARIANT = stm32u585xx
# For flash-jlink target
JLINK_DEVICE = stm32u585zi
diff --git a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk
index 072c595fb..0aba57ce4 100644
--- a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk
+++ b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk
@@ -1,11 +1,9 @@
+MCU_VARIANT = stm32u545xx
CFLAGS += \
-DSTM32U545xx \
# All source paths should be relative to the top level.
LD_FILE = ${FAMILY_PATH}/linker/STM32U545xx_FLASH.ld
-SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u545xx.s
-
-MCU_VARIANT = stm32u545xx
# For flash-jlink target
JLINK_DEVICE = stm32u545re
diff --git a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk
index fee56f2ba..4bc9fea10 100644
--- a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk
+++ b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk
@@ -1,11 +1,9 @@
+MCU_VARIANT = stm32u575xx
CFLAGS += \
-DSTM32U575xx \
# All source paths should be relative to the top level.
LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld
-SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s
-
-MCU_VARIANT = stm32u575xx
# For flash-jlink target
JLINK_DEVICE = stm32u575ai
diff --git a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk
index c83ec3999..d09dc5c46 100644
--- a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk
+++ b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk
@@ -1,11 +1,9 @@
+MCU_VARIANT = stm32u575xx
CFLAGS += \
-DSTM32U575xx \
# All source paths should be relative to the top level.
LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld
-SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s
-
-MCU_VARIANT = stm32u575xx
# For flash-jlink target
JLINK_DEVICE = stm32u575zi
diff --git a/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk
index 4bebe3330..c9fdbac1a 100644
--- a/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk
+++ b/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk
@@ -1,3 +1,4 @@
+MCU_VARIANT = stm32u5a5xx
CFLAGS += \
-DSTM32U5A5xx \
-DHSE_VALUE=16000000UL \
@@ -5,8 +6,5 @@ CFLAGS += \
# All source paths should be relative to the top level.
LD_FILE = ${BOARD_PATH}/STM32U5A5ZJTXQ_FLASH.ld
-SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u5a5xx.s
-
-MCU_VARIANT = stm32u5a5xx
# For flash-jlink target
JLINK_DEVICE = stm32u575zi
diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk
index 05fe4608a..7fc728dcf 100644
--- a/hw/bsp/stm32u5/family.mk
+++ b/hw/bsp/stm32u5/family.mk
@@ -57,5 +57,12 @@ INC += \
$(TOP)/$(ST_HAL_DRIVER)/Inc \
$(TOP)/$(BOARD_PATH)
+# 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
+
# flash target using on-board stlink
flash: flash-stlink
diff --git a/hw/bsp/stm32wb/family.mk b/hw/bsp/stm32wb/family.mk
index de8372eea..a80ff6f5b 100644
--- a/hw/bsp/stm32wb/family.mk
+++ b/hw/bsp/stm32wb/family.mk
@@ -9,14 +9,12 @@ include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m4
CFLAGS += \
- -flto \
- -nostdlib -nostartfiles \
-DCFG_TUSB_MCU=OPT_MCU_STM32WB
-# suppress warning caused by vendor mcu driver
-CFLAGS += -Wno-error=cast-align -Wno-unused-parameter
-
-LD_FILE ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash_cm4.ld
+CFLAGS_GCC += \
+ -flto \
+ -nostdlib -nostartfiles \
+ -Wno-error=cast-align -Wno-unused-parameter
LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
@@ -25,19 +23,26 @@ SRC_C += \
$(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_pwr.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_gpio.c
-SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_${MCU_VARIANT}_cm4.s
-
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)_cm4.s
+SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT)_cm4.s
+
+# Linker
+LD_FILE_GCC ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash_cm4.ld
+LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash_cm4.icf
+
# flash target using on-board stlink
flash: flash-stlink
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index 6670045aa..87c77c9a7 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -344,7 +344,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
msc_csw_t * p_csw = &p_msc->csw;
switch (p_msc->stage) {
- case MSC_STAGE_CMD:
+ case MSC_STAGE_CMD: {
//------------- new CBW received -------------//
// Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it
if (ep_addr != p_msc->ep_out) {
@@ -441,7 +441,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
}
}
}
- break;
+ break;
+ }
case MSC_STAGE_DATA:
TU_LOG_DRV(" SCSI Data [Lun%u]\r\n", p_cbw->lun);
diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h
index 2e9f1d9cd..1d0c6f1ad 100644
--- a/src/common/tusb_debug.h
+++ b/src/common/tusb_debug.h
@@ -108,15 +108,13 @@ typedef struct {
} tu_lookup_table_t;
static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) {
- tu_static char not_found[11];
-
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);
-
return not_found;
}
diff --git a/src/host/usbh.c b/src/host/usbh.c
index 4b0f4d488..5ce325762 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -1372,9 +1372,13 @@ enum {
ENUM_HUB_CLEAR_RESET_2,
ENUM_SET_ADDR,
ENUM_GET_DEVICE_DESC,
+ ENUM_GET_STRING_LANGUAGE_ID_LEN,
ENUM_GET_STRING_LANGUAGE_ID,
+ ENUM_GET_STRING_MANUFACTURER_LEN,
ENUM_GET_STRING_MANUFACTURER,
+ ENUM_GET_STRING_PRODUCT_LEN,
ENUM_GET_STRING_PRODUCT,
+ ENUM_GET_STRING_SERIAL_LEN,
ENUM_GET_STRING_SERIAL,
ENUM_GET_9BYTE_CONFIG_DESC,
ENUM_GET_FULL_CONFIG_DESC,
@@ -1416,6 +1420,9 @@ static void process_enumeration(tuh_xfer_t* xfer) {
uint8_t const daddr = xfer->daddr;
uintptr_t const state = xfer->user_data;
usbh_device_t* dev = get_device(daddr);
+ if (daddr > 0) {
+ TU_ASSERT(dev,);
+ }
uint16_t langid = 0x0409; // default is English
switch (state) {
@@ -1474,30 +1481,6 @@ static void process_enumeration(tuh_xfer_t* xfer) {
break;
}
-#if 0
- case ENUM_RESET_2:
- // TODO not used by now, but may be needed for some devices !?
- // Reset device again before Set Address
- TU_LOG_USBH("Port reset2 \r\n");
- if (_dev0.hub_addr == 0) {
- // connected directly to roothub
- hcd_port_reset( _dev0.rhport );
- tusb_time_delay_ms_api(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
- // sof of controller may not running while resetting
- hcd_port_reset_end(_dev0.rhport);
- // TODO: fall through to SET ADDRESS, refactor later
- }
-#if CFG_TUH_HUB
- else {
- // after RESET_DELAY the hub_port_reset() already complete
- TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port,
- process_enumeration, ENUM_HUB_GET_STATUS_2), );
- break;
- }
-#endif
- TU_ATTR_FALLTHROUGH;
-#endif
-
case ENUM_SET_ADDR:
enum_request_set_addr((tusb_desc_device_t*) _usbh_epbuf.ctrl);
break;
@@ -1520,14 +1503,15 @@ static void process_enumeration(tuh_xfer_t* xfer) {
// Get full device descriptor
TU_LOG_USBH("Get Device Descriptor\r\n");
TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t),
- process_enumeration, ENUM_GET_STRING_LANGUAGE_ID),);
+ process_enumeration, ENUM_GET_STRING_LANGUAGE_ID_LEN),);
break;
}
- case ENUM_GET_STRING_LANGUAGE_ID: {
+ // For string descriptor (langid, manufacturer, product, serila): always get the first 2 bytes
+ // to determine the length first. otherwise, some device may have buffer overflow.
+ case ENUM_GET_STRING_LANGUAGE_ID_LEN: {
// save the received device descriptor
- TU_ASSERT(dev,);
- tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
+ tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl;
dev->vid = desc_device->idVendor;
dev->pid = desc_device->idProduct;
dev->i_manufacturer = desc_device->iManufacturer;
@@ -1535,50 +1519,88 @@ static void process_enumeration(tuh_xfer_t* xfer) {
dev->i_serial = desc_device->iSerialNumber;
dev->bNumConfigurations = desc_device->bNumConfigurations;
- tuh_enum_descriptor_device_cb(daddr, desc_device); // callback
+ tuh_enum_descriptor_device_cb(daddr, desc_device);// callback
- tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
- process_enumeration, ENUM_GET_STRING_MANUFACTURER);
+ tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, 2,
+ process_enumeration, ENUM_GET_STRING_LANGUAGE_ID);
break;
}
- case ENUM_GET_STRING_MANUFACTURER: {
- TU_ASSERT(dev,);
- const tusb_desc_string_t* desc_langid = (tusb_desc_string_t const*) _usbh_epbuf.ctrl;
+ case ENUM_GET_STRING_LANGUAGE_ID: {
+ const uint8_t str_len = xfer->buffer[0];
+ tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, str_len,
+ process_enumeration, ENUM_GET_STRING_MANUFACTURER_LEN);
+ break;
+ }
+
+ case ENUM_GET_STRING_MANUFACTURER_LEN: {
+ const tusb_desc_string_t* desc_langid = (const tusb_desc_string_t *) _usbh_epbuf.ctrl;
if (desc_langid->bLength >= 4) {
- langid = tu_le16toh(desc_langid->utf16le[0]);
+ langid = tu_le16toh(desc_langid->utf16le[0]); // previous request is langid
}
if (dev->i_manufacturer != 0) {
- tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
- process_enumeration, ENUM_GET_STRING_PRODUCT);
+ tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, 2,
+ process_enumeration, ENUM_GET_STRING_MANUFACTURER);
+ break;
+ }else {
+ TU_ATTR_FALLTHROUGH;
+ }
+ }
+
+ case ENUM_GET_STRING_MANUFACTURER: {
+ if (dev->i_manufacturer != 0) {
+ langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request
+ const uint8_t str_len = xfer->buffer[0];
+ tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, str_len,
+ process_enumeration, ENUM_GET_STRING_PRODUCT_LEN);
break;
} else {
TU_ATTR_FALLTHROUGH;
}
}
- case ENUM_GET_STRING_PRODUCT: {
- TU_ASSERT(dev,);
- if (state == ENUM_GET_STRING_PRODUCT) {
- langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
+ case ENUM_GET_STRING_PRODUCT_LEN:
+ if (dev->i_product != 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->i_product, langid, _usbh_epbuf.ctrl, 2,
+ process_enumeration, ENUM_GET_STRING_PRODUCT);
+ break;
+ } else {
+ TU_ATTR_FALLTHROUGH;
}
+
+ case ENUM_GET_STRING_PRODUCT: {
if (dev->i_product != 0) {
- tuh_descriptor_get_string(daddr, dev->i_product, 0x0409, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
- process_enumeration, ENUM_GET_STRING_SERIAL);
+ langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request
+ const uint8_t str_len = xfer->buffer[0];
+ tuh_descriptor_get_string(daddr, dev->i_product, langid, _usbh_epbuf.ctrl, str_len,
+ process_enumeration, ENUM_GET_STRING_SERIAL_LEN);
break;
} else {
TU_ATTR_FALLTHROUGH;
}
}
- case ENUM_GET_STRING_SERIAL: {
- TU_ASSERT(dev,);
- if (state == ENUM_GET_STRING_SERIAL) {
- langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
+ case ENUM_GET_STRING_SERIAL_LEN:
+ if (dev->i_serial != 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->i_serial, langid, _usbh_epbuf.ctrl, 2,
+ process_enumeration, ENUM_GET_STRING_SERIAL);
+ break;
+ } else {
+ TU_ATTR_FALLTHROUGH;
}
+
+ case ENUM_GET_STRING_SERIAL: {
if (dev->i_serial != 0) {
- tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
- process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC);
+ langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request
+ const uint8_t str_len = xfer->buffer[0];
+ tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, str_len,
+ process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC);
break;
} else {
TU_ATTR_FALLTHROUGH;
@@ -1627,8 +1649,6 @@ static void process_enumeration(tuh_xfer_t* xfer) {
case ENUM_CONFIG_DRIVER: {
TU_LOG_USBH("Device configured\r\n");
- TU_ASSERT(dev,);
-
dev->configured = 1;
// Parse configuration & set up drivers
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index c461d9a79..52d675611 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -41,12 +41,6 @@
#include "device/dcd.h"
#include "dwc2_common.h"
-#if TU_CHECK_MCU(OPT_MCU_GD32VF103)
- #define DWC2_EP_COUNT(_dwc2) DWC2_EP_MAX
-#else
- #define DWC2_EP_COUNT(_dwc2) ((_dwc2)->ghwcfg2_bm.num_dev_ep + 1)
-#endif
-
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
@@ -79,6 +73,16 @@ CFG_TUD_MEM_SECTION static struct {
TUD_EPBUF_DEF(setup_packet, 8);
} _dcd_usbbuf;
+TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) {
+ #if TU_CHECK_MCU(OPT_MCU_GD32VF103)
+ return DWC2_EP_MAX;
+ #else
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ return ghwcfg2.num_dev_ep + 1;
+ #endif
+}
+
+
//--------------------------------------------------------------------
// DMA
//--------------------------------------------------------------------
@@ -102,7 +106,8 @@ bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) {
TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) {
(void) dwc2;
// Internal DMA only
- return CFG_TUD_DWC2_DMA_ENABLE && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA;
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ return CFG_TUD_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA;
}
static void dma_setup_prepare(uint8_t rhport) {
@@ -250,20 +255,15 @@ static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint
xfer->interval = p_endpoint_desc->bInterval;
// Endpoint control
- union {
- uint32_t value;
- dwc2_depctl_t bm;
- } depctl;
- depctl.value = 0;
-
- depctl.bm.mps = xfer->max_size;
- depctl.bm.active = 1;
- depctl.bm.type = p_endpoint_desc->bmAttributes.xfer;
+ dwc2_depctl_t depctl = {.value = 0};
+ depctl.mps = xfer->max_size;
+ depctl.active = 1;
+ depctl.type = p_endpoint_desc->bmAttributes.xfer;
if (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) {
- depctl.bm.set_data0_iso_even = 1;
+ depctl.set_data0_iso_even = 1;
}
if (dir == TUSB_DIR_IN) {
- depctl.bm.tx_fifo_num = epnum;
+ depctl.tx_fifo_num = epnum;
}
dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum];
@@ -343,31 +343,22 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin
}
// transfer size: A full OUT transfer (multiple packets, possibly) triggers XFRC.
- union {
- uint32_t value;
- dwc2_ep_tsize_t bm;
- } deptsiz;
- deptsiz.value = 0;
- deptsiz.bm.xfer_size = total_bytes;
- deptsiz.bm.packet_count = num_packets;
-
+ dwc2_ep_tsize_t deptsiz = {.value = 0};
+ deptsiz.xfer_size = total_bytes;
+ deptsiz.packet_count = num_packets;
dep->tsiz = deptsiz.value;
// control
- union {
- dwc2_depctl_t bm;
- uint32_t value;
- } depctl;
- depctl.value = dep->ctl;
-
- depctl.bm.clear_nak = 1;
- depctl.bm.enable = 1;
- if (depctl.bm.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) {
- const uint32_t odd_now = (dwc2->dsts_bm.frame_number & 1u);
+ dwc2_depctl_t depctl = {.value = dep->ctl};
+ depctl.clear_nak = 1;
+ depctl.enable = 1;
+ if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) {
+ const dwc2_dsts_t dsts = {.value = dwc2->dsts};
+ const uint32_t odd_now = dsts.frame_number & 1u;
if (odd_now) {
- depctl.bm.set_data0_iso_even = 1;
+ depctl.set_data0_iso_even = 1;
} else {
- depctl.bm.set_data1_iso_odd = 1;
+ depctl.set_data1_iso_odd = 1;
}
}
@@ -410,7 +401,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
// 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)
- if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ if (ghwcfg2.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
dcfg |= DCFG_XCVRDLY;
}
} else {
@@ -641,7 +633,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
// 7.4.1 Initialization on USB Reset
static void handle_bus_reset(uint8_t rhport) {
dwc2_regs_t *dwc2 = DWC2_REG(rhport);
- const uint8_t ep_count = DWC2_EP_COUNT(dwc2);
+ const uint8_t ep_count = dwc2_ep_count(dwc2);
tu_memclr(xfer_status, sizeof(xfer_status));
@@ -671,7 +663,9 @@ static void handle_bus_reset(uint8_t rhport) {
dfifo_device_init(rhport);
// 5. Reset device address
- dwc2->dcfg_bm.address = 0;
+ dwc2_dcfg_t dcfg = {.value = dwc2->dcfg};
+ dcfg.address = 0;
+ dwc2->dcfg = dcfg.value;
// Fixed both control EP0 size to 64 bytes
dwc2->epin[0].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos);
@@ -691,8 +685,9 @@ static void handle_bus_reset(uint8_t rhport) {
static void handle_enum_done(uint8_t rhport) {
dwc2_regs_t *dwc2 = DWC2_REG(rhport);
+ const dwc2_dsts_t dsts = {.value = dwc2->dsts};
tusb_speed_t speed;
- switch (dwc2->dsts_bm.enum_speed) {
+ switch (dsts.enum_speed) {
case DCFG_SPEED_HIGH:
speed = TUSB_SPEED_HIGH;
break;
@@ -737,12 +732,12 @@ static void handle_rxflvl_irq(uint8_t rhport) {
const volatile uint32_t* rx_fifo = dwc2->fifo[0];
// Pop control word off FIFO
- const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm;
- const uint8_t epnum = grxstsp_bm.ep_ch_num;
+ const dwc2_grxstsp_t grxstsp = {.value = dwc2->grxstsp};
+ const uint8_t epnum = grxstsp.ep_ch_num;
dwc2_dep_t* epout = &dwc2->epout[epnum];
- switch (grxstsp_bm.packet_status) {
+ switch (grxstsp.packet_status) {
case GRXSTS_PKTSTS_GLOBAL_OUT_NAK:
// Global OUT NAK: do nothing
break;
@@ -764,7 +759,7 @@ static void handle_rxflvl_irq(uint8_t rhport) {
case GRXSTS_PKTSTS_RX_DATA: {
// Out packet received
- const uint16_t byte_count = grxstsp_bm.byte_count;
+ const uint16_t byte_count = grxstsp.byte_count;
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
if (byte_count) {
@@ -778,7 +773,8 @@ static void handle_rxflvl_irq(uint8_t rhport) {
// short packet, minus remaining bytes (xfer_size)
if (byte_count < xfer->max_size) {
- xfer->total_len -= epout->tsiz_bm.xfer_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;
@@ -840,11 +836,13 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep
// - 64 bytes or
// - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL)
if (diepint_bm.txfifo_empty && (dwc2->diepempmsk & (1 << epnum))) {
- const uint16_t remain_packets = epin->tsiz_bm.packet_count;
+ 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++) {
- const uint16_t remain_bytes = (uint16_t) epin->tsiz_bm.xfer_size;
+ 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
@@ -863,7 +861,8 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep
}
// Turn off TXFE if all bytes are written.
- if (epin->tsiz_bm.xfer_size == 0) {
+ tsiz.value = epin->tsiz;
+ if (tsiz.xfer_size == 0) {
dwc2->diepempmsk &= ~(1 << epnum);
}
}
@@ -894,7 +893,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
// determine actual received bytes
- const uint16_t remain = epout->tsiz_bm.xfer_size;
+ const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz};
+ const uint16_t remain = tsiz.xfer_size;
xfer->total_len -= remain;
// this is ZLP, so prepare EP0 for next setup
@@ -930,7 +930,7 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin
static void handle_ep_irq(uint8_t rhport, uint8_t dir) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
const bool is_dma = dma_device_enabled(dwc2);
- const uint8_t ep_count = DWC2_EP_COUNT(dwc2);
+ const uint8_t ep_count = dwc2_ep_count(dwc2);
const uint8_t daint_offset = (dir == TUSB_DIR_IN) ? DAINT_IEPINT_Pos : DAINT_OEPINT_Pos;
dwc2_dep_t* ep_base = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][0];
diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c
index f80ae9acb..f6ed8fc98 100644
--- a/src/portable/synopsys/dwc2/dwc2_common.c
+++ b/src/portable/synopsys/dwc2/dwc2_common.c
@@ -88,11 +88,13 @@ static void phy_fs_init(dwc2_regs_t* dwc2) {
static void phy_hs_init(dwc2_regs_t* dwc2) {
uint32_t gusbcfg = dwc2->gusbcfg;
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ const dwc2_ghwcfg4_t ghwcfg4 = {.value = dwc2->ghwcfg4};
// De-select FS PHY
gusbcfg &= ~GUSBCFG_PHYSEL;
- if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
+ if (ghwcfg2.hs_phy_type == GHWCFG2_HSPHY_ULPI) {
TU_LOG(DWC2_COMMON_DEBUG, "Highspeed ULPI PHY init\r\n");
// Select ULPI PHY (external)
@@ -116,7 +118,7 @@ static void phy_hs_init(dwc2_regs_t* dwc2) {
gusbcfg &= ~GUSBCFG_ULPI_UTMI_SEL;
// Set 16-bit interface if supported
- if (dwc2->ghwcfg4_bm.phy_data_width) {
+ if (ghwcfg4.phy_data_width) {
gusbcfg |= GUSBCFG_PHYIF16; // 16 bit
} else {
gusbcfg &= ~GUSBCFG_PHYIF16; // 8 bit
@@ -127,7 +129,7 @@ static void phy_hs_init(dwc2_regs_t* dwc2) {
dwc2->gusbcfg = gusbcfg;
// mcu specific phy init
- dwc2_phy_init(dwc2, dwc2->ghwcfg2_bm.hs_phy_type);
+ dwc2_phy_init(dwc2, ghwcfg2.hs_phy_type);
// Reset core after selecting PHY
reset_core(dwc2);
@@ -136,11 +138,11 @@ static void phy_hs_init(dwc2_regs_t* dwc2) {
// - 9 if using 8-bit PHY interface
// - 5 if using 16-bit PHY interface
gusbcfg &= ~GUSBCFG_TRDT_Msk;
- gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos;
+ gusbcfg |= (ghwcfg4.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos;
dwc2->gusbcfg = gusbcfg;
// MCU specific PHY update post reset
- dwc2_phy_update(dwc2, dwc2->ghwcfg2_bm.hs_phy_type);
+ dwc2_phy_update(dwc2, ghwcfg2.hs_phy_type);
}
static bool check_dwc2(dwc2_regs_t* dwc2) {
@@ -171,7 +173,6 @@ static bool check_dwc2(dwc2_regs_t* dwc2) {
//--------------------------------------------------------------------
bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) {
(void)dwc2;
-
#if CFG_TUD_ENABLED
if (role == TUSB_ROLE_DEVICE && !TUD_OPT_HIGH_SPEED) {
return false;
@@ -183,7 +184,8 @@ bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) {
}
#endif
- return dwc2->ghwcfg2_bm.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED;
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ return ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED;
}
/* dwc2 has several PHYs option
diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h
index 812096759..34e046346 100644
--- a/src/portable/synopsys/dwc2/dwc2_type.h
+++ b/src/portable/synopsys/dwc2/dwc2_type.h
@@ -184,415 +184,470 @@ enum {
//--------------------------------------------------------------------
// Common Register Bitfield
//--------------------------------------------------------------------
-typedef struct TU_ATTR_PACKED {
- uint32_t ses_req_scs : 1; // 0 Session request success
- uint32_t ses_req : 1; // 1 Session request
- uint32_t vbval_ov_en : 1; // 2 VBUS valid override enable
- uint32_t vbval_ov_val : 1; // 3 VBUS valid override value
- uint32_t aval_ov_en : 1; // 4 A-peripheral session valid override enable
- uint32_t aval_ov_al : 1; // 5 A-peripheral session valid override value
- uint32_t bval_ov_en : 1; // 6 B-peripheral session valid override enable
- uint32_t bval_ov_val : 1; // 7 B-peripheral session valid override value
- uint32_t hng_scs : 1; // 8 Host negotiation success
- uint32_t hnp_rq : 1; // 9 HNP (host negotiation protocol) request
- uint32_t host_set_hnp_en : 1; // 10 Host set HNP enable
- uint32_t dev_hnp_en : 1; // 11 Device HNP enabled
- uint32_t embedded_host_en : 1; // 12 Embedded host enable
- uint32_t rsv13_14 : 2; // 13.14 Reserved
- uint32_t dbnc_filter_bypass : 1; // 15 Debounce filter bypass
- uint32_t cid_status : 1; // 16 Connector ID status
- uint32_t dbnc_done : 1; // 17 Debounce done
- uint32_t ases_valid : 1; // 18 A-session valid
- uint32_t bses_valid : 1; // 19 B-session valid
- uint32_t otg_ver : 1; // 20 OTG version 0: v1.3, 1: v2.0
- uint32_t current_mode : 1; // 21 Current mode of operation. Only from v3.00a
- uint32_t mult_val_id_bc : 5; // 22..26 Multi-valued input pin ID battery charger
- uint32_t chirp_en : 1; // 27 Chirp detection enable
- uint32_t rsv28_30 : 3; // 28.30: Reserved
- uint32_t test_mode_corr_eusb2 : 1; // 31 Test mode control for eUSB2 PHY
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t ses_req_scs : 1; // 0 Session request success
+ uint32_t ses_req : 1; // 1 Session request
+ uint32_t vbval_ov_en : 1; // 2 VBUS valid override enable
+ uint32_t vbval_ov_val : 1; // 3 VBUS valid override value
+ uint32_t aval_ov_en : 1; // 4 A-peripheral session valid override enable
+ uint32_t aval_ov_al : 1; // 5 A-peripheral session valid override value
+ uint32_t bval_ov_en : 1; // 6 B-peripheral session valid override enable
+ uint32_t bval_ov_val : 1; // 7 B-peripheral session valid override value
+ uint32_t hng_scs : 1; // 8 Host negotiation success
+ uint32_t hnp_rq : 1; // 9 HNP (host negotiation protocol) request
+ uint32_t host_set_hnp_en : 1; // 10 Host set HNP enable
+ uint32_t dev_hnp_en : 1; // 11 Device HNP enabled
+ uint32_t embedded_host_en : 1; // 12 Embedded host enable
+ uint32_t rsv13_14 : 2; // 13.14 Reserved
+ uint32_t dbnc_filter_bypass : 1; // 15 Debounce filter bypass
+ uint32_t cid_status : 1; // 16 Connector ID status
+ uint32_t dbnc_done : 1; // 17 Debounce done
+ uint32_t ases_valid : 1; // 18 A-session valid
+ uint32_t bses_valid : 1; // 19 B-session valid
+ uint32_t otg_ver : 1; // 20 OTG version 0: v1.3, 1: v2.0
+ uint32_t current_mode : 1; // 21 Current mode of operation. Only from v3.00a
+ uint32_t mult_val_id_bc : 5; // 22..26 Multi-valued input pin ID battery charger
+ uint32_t chirp_en : 1; // 27 Chirp detection enable
+ uint32_t rsv28_30 : 3; // 28.30: Reserved
+ uint32_t test_mode_corr_eusb2 : 1; // 31 Test mode control for eUSB2 PHY
+ };
} dwc2_gotgctl_t;
TU_VERIFY_STATIC(sizeof(dwc2_gotgctl_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t rsv0_1 : 2; // 0..1 Reserved
- uint32_t ses_end_det : 1; // 2 Session end detected
- uint32_t rsv3_7 : 5; // 3..7 Reserved
- uint32_t srs_status_change : 1; // 8 Session request success status change
- uint32_t hns_status_change : 1; // 9 Host negotiation success status change
- uint32_t rsv10_16 : 7; // 10..16 Reserved
- uint32_t hng_det : 1; // 17 Host negotiation detected
- uint32_t adev_timeout_change : 1; // 18 A-device timeout change
- uint32_t dbnc_done : 1; // 19 Debounce done
- uint32_t mult_val_lp_change : 1; // 20 Multi-valued input pin change
- uint32_t rsv21_31 :11; // 21..31 Reserved
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t rsv0_1 : 2; // 0..1 Reserved
+ uint32_t ses_end_det : 1; // 2 Session end detected
+ uint32_t rsv3_7 : 5; // 3..7 Reserved
+ uint32_t srs_status_change : 1; // 8 Session request success status change
+ uint32_t hns_status_change : 1; // 9 Host negotiation success status change
+ uint32_t rsv10_16 : 7; // 10..16 Reserved
+ uint32_t hng_det : 1; // 17 Host negotiation detected
+ uint32_t adev_timeout_change : 1; // 18 A-device timeout change
+ uint32_t dbnc_done : 1; // 19 Debounce done
+ uint32_t mult_val_lp_change : 1; // 20 Multi-valued input pin change
+ uint32_t rsv21_31 :11; // 21..31 Reserved
+ };
} dwc2_gotgint_t;
TU_VERIFY_STATIC(sizeof(dwc2_gotgint_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t gintmask : 1; // 0 Global interrupt mask
- uint32_t hbst_len : 4; // 1..4 Burst length/type
- uint32_t dma_en : 1; // 5 DMA enable
- uint32_t rsv6 : 1; // 6 Reserved
- uint32_t nptxf_empty_lvl : 1; // 7 Non-periodic Tx FIFO empty level
- uint32_t ptxf_empty_lvl : 1; // 8 Periodic Tx FIFO empty level
- uint32_t rsv9_20 : 12; // 9.20: Reserved
- uint32_t remote_mem_support : 1; // 21 Remote memory support
- uint32_t notify_all_dma_write : 1; // 22 Notify all DMA writes
- uint32_t ahb_single : 1; // 23 AHB single
- uint32_t inv_desc_endian : 1; // 24 Inverse descriptor endian
- uint32_t rsv25_31 : 7; // 25..31 Reserved
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t gintmask : 1; // 0 Global interrupt mask
+ uint32_t hbst_len : 4; // 1..4 Burst length/type
+ uint32_t dma_en : 1; // 5 DMA enable
+ uint32_t rsv6 : 1; // 6 Reserved
+ uint32_t nptxf_empty_lvl : 1; // 7 Non-periodic Tx FIFO empty level
+ uint32_t ptxf_empty_lvl : 1; // 8 Periodic Tx FIFO empty level
+ uint32_t rsv9_20 : 12; // 9.20: Reserved
+ uint32_t remote_mem_support : 1; // 21 Remote memory support
+ uint32_t notify_all_dma_write : 1; // 22 Notify all DMA writes
+ uint32_t ahb_single : 1; // 23 AHB single
+ uint32_t inv_desc_endian : 1; // 24 Inverse descriptor endian
+ uint32_t rsv25_31 : 7; // 25..31 Reserved
+ };
} dwc2_gahbcfg_t;
TU_VERIFY_STATIC(sizeof(dwc2_gahbcfg_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t timeout_cal : 3; /* 0..2 Timeout calibration.
- The USB standard timeout value for high-speed operation is 736 to 816 (inclusive) bit times. The USB standard
- timeout value for full- speed operation is 16 to 18 (inclusive) bit times. The application must program this field
- based on the speed of enumeration. The number of bit times added per PHY clock are as follows:
- - High-speed: PHY clock One 30-MHz = 16 bit times, One 60-MHz = 8 bit times
- - Full-speed: PHY clock One 30-MHz = 0.4 bit times, One 60-MHz = 0.2 bit times, One 48-MHz = 0.25 bit times */
- uint32_t phy_if16 : 1; // 3 PHY interface. 0: 8 bits, 1: 16 bits
- uint32_t ulpi_utmi_sel : 1; // 4 ULPI/UTMI select. 0: UTMI+, 1: ULPI
- uint32_t fs_intf_sel : 1; // 5 Fullspeed serial interface select. 0: 6-pin, 1: 3-pin
- uint32_t phy_sel : 1; // 6 HS/FS PHY selection. 0: HS UTMI+ or ULPI, 1: FS serial transceiver
- uint32_t ddr_sel : 1; // 7 ULPI DDR select. 0: Single data rate 8-bit, 1: Double data rate 4-bit
- uint32_t srp_capable : 1; // 8 SRP-capable
- uint32_t hnp_capable : 1; // 9 HNP-capable
- uint32_t turnaround_time : 4; // 10..13 Turnaround time. 9: 8-bit UTMI+, 5: 16-bit UTMI+
- uint32_t rsv14 : 1; // 14 Reserved
- uint32_t phy_low_power_clk_sel : 1; /* 15 PHY low-power clock select either 480-MHz or 48-MHz (low-power) PHY mode.
- In FS/LS modes, the PHY can usually operate on a 48-MHz clock to save power. This bit is valid only for UTMI+ PHYs.
- - 0: 480 Mhz internal PLL: the UTMI interface operates at either 60 MHz (8 bit) or 30 MHz (16-bit)
- - 1 48 Mhz external clock: the UTMI interface operates at 48 MHz in FS mode and at either 48 or 6 MHz in LS mode */
- uint32_t otg_i2c_sel : 1; // 16 OTG I2C interface select. 0: UTMI-FS, 1: I2C for OTG signals
- uint32_t ulpi_fsls : 1; /* 17 ULPI FS/LS select. 0: ULPI, 1: ULPI FS/LS.
- valid only when the FS serial transceiver is selected on the ULPI PHY. */
- uint32_t ulpi_auto_resume : 1; // 18 ULPI Auto-resume
- uint32_t ulpi_clk_sus_m : 1; // 19 ULPI Clock SuspendM
- uint32_t ulpi_ext_vbus_drv : 1; // 20 ULPI External VBUS Drive
- uint32_t ulpi_int_vbus_indicator : 1; // 21 ULPI Internal VBUS Indicator
- uint32_t term_sel_dl_pulse : 1; // 22 TermSel DLine pulsing
- uint32_t indicator_complement : 1; // 23 Indicator complement
- uint32_t indicator_pass_through : 1; // 24 Indicator pass through
- uint32_t ulpi_if_protect_disable : 1; // 25 ULPI interface protect disable
- uint32_t ic_usb_capable : 1; // 26 IC_USB Capable
- uint32_t ic_usb_traf_ctl : 1; // 27 IC_USB Traffic Control
- uint32_t tx_end_delay : 1; // 28 TX end delay
- uint32_t force_host_mode : 1; // 29 Force host mode
- uint32_t force_dev_mode : 1; // 30 Force device mode
- uint32_t corrupt_tx_pkt : 1; // 31 Corrupt Tx packet. 0: normal, 1: debug
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t timeout_cal : 3; /* 0..2 Timeout calibration.
+ The USB standard timeout value for high-speed operation is 736 to 816 (inclusive) bit times. The USB standard
+ timeout value for full- speed operation is 16 to 18 (inclusive) bit times. The application must program this field
+ based on the speed of enumeration. The number of bit times added per PHY clock are as follows:
+ - High-speed: PHY clock One 30-MHz = 16 bit times, One 60-MHz = 8 bit times
+ - Full-speed: PHY clock One 30-MHz = 0.4 bit times, One 60-MHz = 0.2 bit times, One 48-MHz = 0.25 bit times */
+ uint32_t phy_if16 : 1; // 3 PHY interface. 0: 8 bits, 1: 16 bits
+ uint32_t ulpi_utmi_sel : 1; // 4 ULPI/UTMI select. 0: UTMI+, 1: ULPI
+ uint32_t fs_intf_sel : 1; // 5 Fullspeed serial interface select. 0: 6-pin, 1: 3-pin
+ uint32_t phy_sel : 1; // 6 HS/FS PHY selection. 0: HS UTMI+ or ULPI, 1: FS serial transceiver
+ uint32_t ddr_sel : 1; // 7 ULPI DDR select. 0: Single data rate 8-bit, 1: Double data rate 4-bit
+ uint32_t srp_capable : 1; // 8 SRP-capable
+ uint32_t hnp_capable : 1; // 9 HNP-capable
+ uint32_t turnaround_time : 4; // 10..13 Turnaround time. 9: 8-bit UTMI+, 5: 16-bit UTMI+
+ uint32_t rsv14 : 1; // 14 Reserved
+ uint32_t phy_low_power_clk_sel : 1; /* 15 PHY low-power clock select either 480-MHz or 48-MHz (low-power) PHY mode.
+ In FS/LS modes, the PHY can usually operate on a 48-MHz clock to save power. This bit is valid only for UTMI+ PHYs.
+ - 0: 480 Mhz internal PLL: the UTMI interface operates at either 60 MHz (8 bit) or 30 MHz (16-bit)
+ - 1 48 Mhz external clock: the UTMI interface operates at 48 MHz in FS mode and at either 48 or 6 MHz in LS mode */
+ uint32_t otg_i2c_sel : 1; // 16 OTG I2C interface select. 0: UTMI-FS, 1: I2C for OTG signals
+ uint32_t ulpi_fsls : 1; /* 17 ULPI FS/LS select. 0: ULPI, 1: ULPI FS/LS.
+ valid only when the FS serial transceiver is selected on the ULPI PHY. */
+ uint32_t ulpi_auto_resume : 1; // 18 ULPI Auto-resume
+ uint32_t ulpi_clk_sus_m : 1; // 19 ULPI Clock SuspendM
+ uint32_t ulpi_ext_vbus_drv : 1; // 20 ULPI External VBUS Drive
+ uint32_t ulpi_int_vbus_indicator : 1; // 21 ULPI Internal VBUS Indicator
+ uint32_t term_sel_dl_pulse : 1; // 22 TermSel DLine pulsing
+ uint32_t indicator_complement : 1; // 23 Indicator complement
+ uint32_t indicator_pass_through : 1; // 24 Indicator pass through
+ uint32_t ulpi_if_protect_disable : 1; // 25 ULPI interface protect disable
+ uint32_t ic_usb_capable : 1; // 26 IC_USB Capable
+ uint32_t ic_usb_traf_ctl : 1; // 27 IC_USB Traffic Control
+ uint32_t tx_end_delay : 1; // 28 TX end delay
+ uint32_t force_host_mode : 1; // 29 Force host mode
+ uint32_t force_dev_mode : 1; // 30 Force device mode
+ uint32_t corrupt_tx_pkt : 1; // 31 Corrupt Tx packet. 0: normal, 1: debug
+ };
} dwc2_gusbcfg_t;
TU_VERIFY_STATIC(sizeof(dwc2_gusbcfg_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t core_soft_rst : 1; // 0 Core Soft Reset
- uint32_t piufs_soft_rst : 1; // 1 PIU FS Dedicated Controller Soft Reset
- uint32_t frame_counter_rst : 1; // 2 Frame Counter Reset (host)
- uint32_t intoken_q_flush : 1; // 3 IN Token Queue Flush
- uint32_t rx_fifo_flush : 1; // 4 RX FIFO Flush
- uint32_t tx_fifo_flush : 1; // 5 TX FIFO Flush
- uint32_t tx_fifo_num : 5; // 6..10 TX FIFO Number
- uint32_t rsv11_28 :18; // 11..28 Reserved
- uint32_t core_soft_rst_done : 1; // 29 Core Soft Reset Done, from v4.20a
- uint32_t dma_req : 1; // 30 DMA Request
- uint32_t ahb_idle : 1; // 31 AHB Idle
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t core_soft_rst : 1; // 0 Core Soft Reset
+ uint32_t piufs_soft_rst : 1; // 1 PIU FS Dedicated Controller Soft Reset
+ uint32_t frame_counter_rst : 1; // 2 Frame Counter Reset (host)
+ uint32_t intoken_q_flush : 1; // 3 IN Token Queue Flush
+ uint32_t rx_fifo_flush : 1; // 4 RX FIFO Flush
+ uint32_t tx_fifo_flush : 1; // 5 TX FIFO Flush
+ uint32_t tx_fifo_num : 5; // 6..10 TX FIFO Number
+ uint32_t rsv11_28 :18; // 11..28 Reserved
+ uint32_t core_soft_rst_done : 1; // 29 Core Soft Reset Done, from v4.20a
+ uint32_t dma_req : 1; // 30 DMA Request
+ uint32_t ahb_idle : 1; // 31 AHB Idle
+ };
} dwc2_grstctl_t;
TU_VERIFY_STATIC(sizeof(dwc2_grstctl_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t ep_ch_num : 4; // 0..3 Endpoint/Channel Number
- uint32_t byte_count :11; // 4..14 Byte Count
- uint32_t dpid : 2; // 15..16 Data PID
- uint32_t packet_status : 4; // 17..20 Packet Status
- uint32_t frame_number : 4; // 21..24 Frame Number
- uint32_t rsv25_31 : 7; // 25..31 Reserved
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t ep_ch_num : 4; // 0..3 Endpoint/Channel Number
+ uint32_t byte_count :11; // 4..14 Byte Count
+ uint32_t dpid : 2; // 15..16 Data PID
+ uint32_t packet_status : 4; // 17..20 Packet Status
+ uint32_t frame_number : 4; // 21..24 Frame Number
+ uint32_t rsv25_31 : 7; // 25..31 Reserved
+ };
} dwc2_grxstsp_t;
TU_VERIFY_STATIC(sizeof(dwc2_grxstsp_t) == 4, "incorrect size");
-// Hardware Configuration
-typedef struct TU_ATTR_PACKED {
- uint32_t op_mode : 3; // 0..2 HNP/SRP Host/Device/OTG mode
- uint32_t arch : 2; // 3..4 Slave/External/Internal DMA
- uint32_t single_point : 1; // 5 0: support hub and split | 1: no hub, no split
- uint32_t hs_phy_type : 2; // 6..7 0: not supported | 1: UTMI+ | 2: ULPI | 3: UTMI+ and ULPI
- uint32_t fs_phy_type : 2; // 8..9 0: not supported | 1: dedicated | 2: UTMI+ | 3: ULPI
- uint32_t num_dev_ep : 4; // 10..13 Number of device endpoints (excluding EP0)
- uint32_t num_host_ch : 4; // 14..17 Number of host channel (excluding control)
- uint32_t period_channel_support : 1; // 18 Support Periodic OUT Host Channel
- uint32_t enable_dynamic_fifo : 1; // 19 Dynamic FIFO Sizing Enabled
- uint32_t mul_proc_intrpt : 1; // 20 Multi-Processor Interrupt enabled (OTG_MULTI_PROC_INTRPT)
- uint32_t reserved21 : 1; // 21 reserved
- uint32_t nptx_q_depth : 2; // 22..23 Non-periodic request queue depth: 0 = 2. 1 = 4, 2 = 8
- uint32_t ptx_q_depth : 2; // 24..25 Host periodic request queue depth: 0 = 2. 1 = 4, 2 = 8
- uint32_t token_q_depth : 5; // 26..30 Device IN token sequence learning queue depth: 0-30
- uint32_t otg_enable_ic_usb : 1; // 31 IC_USB mode specified for mode of operation
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t op_mode : 3; // 0..2 HNP/SRP Host/Device/OTG mode
+ uint32_t arch : 2; // 3..4 Slave/External/Internal DMA
+ uint32_t single_point : 1; // 5 0: support hub and split | 1: no hub, no split
+ uint32_t hs_phy_type : 2; // 6..7 0: not supported | 1: UTMI+ | 2: ULPI | 3: UTMI+ and ULPI
+ uint32_t fs_phy_type : 2; // 8..9 0: not supported | 1: dedicated | 2: UTMI+ | 3: ULPI
+ uint32_t num_dev_ep : 4; // 10..13 Number of device endpoints (excluding EP0)
+ uint32_t num_host_ch : 4; // 14..17 Number of host channel (excluding control)
+ uint32_t period_channel_support : 1; // 18 Support Periodic OUT Host Channel
+ uint32_t enable_dynamic_fifo : 1; // 19 Dynamic FIFO Sizing Enabled
+ uint32_t mul_proc_intrpt : 1; // 20 Multi-Processor Interrupt enabled (OTG_MULTI_PROC_INTRPT)
+ uint32_t reserved21 : 1; // 21 reserved
+ uint32_t nptx_q_depth : 2; // 22..23 Non-periodic request queue depth: 0 = 2. 1 = 4, 2 = 8
+ uint32_t ptx_q_depth : 2; // 24..25 Host periodic request queue depth: 0 = 2. 1 = 4, 2 = 8
+ uint32_t token_q_depth : 5; // 26..30 Device IN token sequence learning queue depth: 0-30
+ uint32_t otg_enable_ic_usb : 1; // 31 IC_USB mode specified for mode of operation
+ };
} dwc2_ghwcfg2_t;
TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg2_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t xfer_size_width : 4; // 0..3 Transfer size counter in bits = 11 + n (max 19 bits)
- uint32_t packet_size_width : 3; // 4..6 Packet size counter in bits = 4 + n (max 10 bits)
- uint32_t otg_enable : 1; // 7 OTG capable
- uint32_t i2c_enable : 1; // 8 I2C interface is available
- uint32_t vendor_ctrl_itf : 1; // 9 Vendor control interface is available
- uint32_t optional_feature_removed : 1; // 10 remove User ID, GPIO, SOF toggle & counter to save gate count
- uint32_t synch_reset : 1; // 11 0: async reset | 1: synch reset
- uint32_t otg_adp_support : 1; // 12 ADP logic is present along with HSOTG controller
- uint32_t otg_enable_hsic : 1; // 13 1: HSIC-capable with shared UTMI PHY interface | 0: non-HSIC
- uint32_t battery_charger_support : 1; // s14 upport battery charger
- uint32_t lpm_mode : 1; // 15 LPM mode
- uint32_t dfifo_depth : 16; // DFIFO depth - EP_LOC_CNT in terms of 32-bit words
-}dwc2_ghwcfg3_t;
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t xfer_size_width : 4; // 0..3 Transfer size counter in bits = 11 + n (max 19 bits)
+ uint32_t packet_size_width : 3; // 4..6 Packet size counter in bits = 4 + n (max 10 bits)
+ uint32_t otg_enable : 1; // 7 OTG capable
+ uint32_t i2c_enable : 1; // 8 I2C interface is available
+ uint32_t vendor_ctrl_itf : 1; // 9 Vendor control interface is available
+ uint32_t optional_feature_removed : 1; // 10 remove User ID, GPIO, SOF toggle & counter to save gate count
+ uint32_t synch_reset : 1; // 11 0: async reset | 1: synch reset
+ uint32_t otg_adp_support : 1; // 12 ADP logic is present along with HSOTG controller
+ uint32_t otg_enable_hsic : 1; // 13 1: HSIC-capable with shared UTMI PHY interface | 0: non-HSIC
+ uint32_t battery_charger_support : 1; // s14 upport battery charger
+ uint32_t lpm_mode : 1; // 15 LPM mode
+ uint32_t dfifo_depth : 16; // DFIFO depth - EP_LOC_CNT in terms of 32-bit words
+ };
+} dwc2_ghwcfg3_t;
TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg3_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t num_dev_period_in_ep : 4; // 0..3 Number of Device Periodic IN Endpoints
- uint32_t partial_powerdown : 1; // 4 Partial Power Down Enabled
- uint32_t ahb_freq_min : 1; // 5 1: minimum of AHB frequency is less than 60 MHz
- uint32_t hibernation : 1; // 6 Hibernation feature is enabled
- uint32_t extended_hibernation : 1; // 7 Extended Hibernation feature is enabled
- uint32_t reserved8 : 1; // 8 Reserved
- uint32_t enhanced_lpm_support1 : 1; // 9 Enhanced LPM Support1
- uint32_t service_interval_flow : 1; // 10 Service Interval flow is supported
- uint32_t ipg_isoc_support : 1; // 11 Interpacket GAP ISO OUT worst-case is supported
- uint32_t acg_support : 1; // 12 Active clock gating is supported
- uint32_t enhanced_lpm_support : 1; // 13 Enhanced LPM Support
- uint32_t phy_data_width : 2; // 14..15 0: 8 bits | 1: 16 bits | 2: 8/16 software selectable
- uint32_t ctrl_ep_num : 4; // 16..19 Number of Device control endpoints in addition to EP0
- uint32_t iddg_filter : 1; // 20 IDDG Filter Enabled
- uint32_t vbus_valid_filter : 1; // 21 VBUS Valid Filter Enabled
- uint32_t a_valid_filter : 1; // 22 A Valid Filter Enabled
- uint32_t b_valid_filter : 1; // 23 B Valid Filter Enabled
- uint32_t session_end_filter : 1; // 24 Session End Filter Enabled
- uint32_t dedicated_fifos : 1; // 25 Dedicated tx fifo for device IN Endpoint
- uint32_t num_dev_in_eps : 4; // 26..29 Number of Device IN Endpoints including EP0
- uint32_t dma_desc_enabled : 1; // scatter/gather DMA configuration enabled
- uint32_t dma_desc_dynamic : 1; // Dynamic scatter/gather DMA
-}dwc2_ghwcfg4_t;
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t num_dev_period_in_ep : 4; // 0..3 Number of Device Periodic IN Endpoints
+ uint32_t partial_powerdown : 1; // 4 Partial Power Down Enabled
+ uint32_t ahb_freq_min : 1; // 5 1: minimum of AHB frequency is less than 60 MHz
+ uint32_t hibernation : 1; // 6 Hibernation feature is enabled
+ uint32_t extended_hibernation : 1; // 7 Extended Hibernation feature is enabled
+ uint32_t reserved8 : 1; // 8 Reserved
+ uint32_t enhanced_lpm_support1 : 1; // 9 Enhanced LPM Support1
+ uint32_t service_interval_flow : 1; // 10 Service Interval flow is supported
+ uint32_t ipg_isoc_support : 1; // 11 Interpacket GAP ISO OUT worst-case is supported
+ uint32_t acg_support : 1; // 12 Active clock gating is supported
+ uint32_t enhanced_lpm_support : 1; // 13 Enhanced LPM Support
+ uint32_t phy_data_width : 2; // 14..15 0: 8 bits | 1: 16 bits | 2: 8/16 software selectable
+ uint32_t ctrl_ep_num : 4; // 16..19 Number of Device control endpoints in addition to EP0
+ uint32_t iddg_filter : 1; // 20 IDDG Filter Enabled
+ uint32_t vbus_valid_filter : 1; // 21 VBUS Valid Filter Enabled
+ uint32_t a_valid_filter : 1; // 22 A Valid Filter Enabled
+ uint32_t b_valid_filter : 1; // 23 B Valid Filter Enabled
+ uint32_t session_end_filter : 1; // 24 Session End Filter Enabled
+ uint32_t dedicated_fifos : 1; // 25 Dedicated tx fifo for device IN Endpoint
+ uint32_t num_dev_in_eps : 4; // 26..29 Number of Device IN Endpoints including EP0
+ uint32_t dma_desc_enabled : 1; // scatter/gather DMA configuration enabled
+ uint32_t dma_desc_dynamic : 1; // Dynamic scatter/gather DMA
+ };
+} dwc2_ghwcfg4_t;
TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg4_t) == 4, "incorrect size");
-//--------------------------------------------------------------------
-// Host Register Bitfield
-//--------------------------------------------------------------------
-
-typedef struct TU_ATTR_PACKED {
- uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO
- uint32_t req_queue_available : 8; // 16..23 Number of spaces available in the NPT transmit request queue for both IN and OU
- // 24..31 is top entry in the request queue that is currently being processed by the MAC
- uint32_t qtop_terminate : 1; // 24 Last entry for selected channel
- uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command
- uint32_t qtop_ch_num : 4; // 27..30 Channel number
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO
+ uint32_t req_queue_available : 8; // 16..23 Number of spaces available in the NPT transmit request queue for both IN and OU
+ // 24..31 is top entry in the request queue that is currently being processed by the MAC
+ uint32_t qtop_terminate : 1; // 24 Last entry for selected channel
+ uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command
+ uint32_t qtop_ch_num : 4; // 27..30 Channel number
+ };
} dwc2_hnptxsts_t;
TU_VERIFY_STATIC(sizeof(dwc2_hnptxsts_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO
- uint32_t req_queue_available : 7; // 16..22 Number of spaces available in the PTX transmit request queue
- uint32_t qtop_terminate : 1; // 23 Last entry for selected channel
- uint32_t qtop_last_period : 1; // 24 Last entry for selected channel is a periodic entry
- uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command
- uint32_t qtop_ch_num : 4; // 27..30 Channel number
- uint32_t qtop_odd_frame : 1; // 31 Send in odd frame
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t fifo_available :16; // 0..15 Number of words available in the Tx FIFO
+ uint32_t req_queue_available : 7; // 16..22 Number of spaces available in the PTX transmit request queue
+ uint32_t qtop_terminate : 1; // 23 Last entry for selected channel
+ uint32_t qtop_last_period : 1; // 24 Last entry for selected channel is a periodic entry
+ uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command
+ uint32_t qtop_ch_num : 4; // 27..30 Channel number
+ uint32_t qtop_odd_frame : 1; // 31 Send in odd frame
+ };
} dwc2_hptxsts_t;
TU_VERIFY_STATIC(sizeof(dwc2_hptxsts_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t conn_status : 1; // 0 Port connect status
- uint32_t conn_detected : 1; // 1 Port connect detected
- uint32_t enable : 1; // 2 Port enable status
- uint32_t enable_change : 1; // 3 Port enable change
- uint32_t over_current_active : 1; // 4 Port Over-current active
- uint32_t over_current_change : 1; // 5 Port Over-current change
- uint32_t resume : 1; // 6 Port resume
- uint32_t suspend : 1; // 7 Port suspend
- uint32_t reset : 1; // 8 Port reset
- uint32_t rsv9 : 1; // 9 Reserved
- uint32_t line_status : 2; // 10..11 Line status
- uint32_t power : 1; // 12 Port power
- uint32_t test_control : 4; // 13..16 Port Test control
- uint32_t speed : 2; // 17..18 Port speed
- uint32_t rsv19_31 :13; // 19..31 Reserved
-}dwc2_hprt_t;
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t conn_status : 1; // 0 Port connect status
+ uint32_t conn_detected : 1; // 1 Port connect detected
+ uint32_t enable : 1; // 2 Port enable status
+ uint32_t enable_change : 1; // 3 Port enable change
+ uint32_t over_current_active : 1; // 4 Port Over-current active
+ uint32_t over_current_change : 1; // 5 Port Over-current change
+ uint32_t resume : 1; // 6 Port resume
+ uint32_t suspend : 1; // 7 Port suspend
+ uint32_t reset : 1; // 8 Port reset
+ uint32_t rsv9 : 1; // 9 Reserved
+ uint32_t line_status : 2; // 10..11 Line status
+ uint32_t power : 1; // 12 Port power
+ uint32_t test_control : 4; // 13..16 Port Test control
+ uint32_t speed : 2; // 17..18 Port speed
+ uint32_t rsv19_31 :13; // 19..31 Reserved
+ };
+} dwc2_hprt_t;
TU_VERIFY_STATIC(sizeof(dwc2_hprt_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t ep_size : 11; // 0..10 Maximum packet size
- uint32_t ep_num : 4; // 11..14 Endpoint number
- uint32_t ep_dir : 1; // 15 Endpoint direction
- uint32_t rsv16 : 1; // 16 Reserved
- uint32_t low_speed_dev : 1; // 17 Low-speed device
- uint32_t ep_type : 2; // 18..19 Endpoint type
- uint32_t err_multi_count : 2; // 20..21 Error (splitEn = 1) / Multi (SplitEn = 0) count
- uint32_t dev_addr : 7; // 22..28 Device address
- uint32_t odd_frame : 1; // 29 Odd frame
- uint32_t disable : 1; // 30 Channel disable
- uint32_t enable : 1; // 31 Channel enable
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t ep_size : 11; // 0..10 Maximum packet size
+ uint32_t ep_num : 4; // 11..14 Endpoint number
+ uint32_t ep_dir : 1; // 15 Endpoint direction
+ uint32_t rsv16 : 1; // 16 Reserved
+ uint32_t low_speed_dev : 1; // 17 Low-speed device
+ uint32_t ep_type : 2; // 18..19 Endpoint type
+ uint32_t err_multi_count : 2; // 20..21 Error (splitEn = 1) / Multi (SplitEn = 0) count
+ uint32_t dev_addr : 7; // 22..28 Device address
+ uint32_t odd_frame : 1; // 29 Odd frame
+ uint32_t disable : 1; // 30 Channel disable
+ uint32_t enable : 1; // 31 Channel enable
+ };
} dwc2_channel_char_t;
TU_VERIFY_STATIC(sizeof(dwc2_channel_char_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t hub_port : 7; // 0..6 Hub port number
- uint32_t hub_addr : 7; // 7..13 Hub address
- uint32_t xact_pos : 2; // 14..15 Transaction position
- uint32_t split_compl : 1; // 16 Split completion
- uint32_t rsv17_30 : 14; // 17..30 Reserved
- uint32_t split_en : 1; // 31 Split enable
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t hub_port : 7; // 0..6 Hub port number
+ uint32_t hub_addr : 7; // 7..13 Hub address
+ uint32_t xact_pos : 2; // 14..15 Transaction position
+ uint32_t split_compl : 1; // 16 Split completion
+ uint32_t rsv17_30 : 14; // 17..30 Reserved
+ uint32_t split_en : 1; // 31 Split enable
+ };
} dwc2_channel_split_t;
TU_VERIFY_STATIC(sizeof(dwc2_channel_split_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t xfer_size : 19; // 0..18 Transfer size in bytes
- uint32_t packet_count : 10; // 19..28 Number of packets
- uint32_t pid : 2; // 29..30 Packet ID
- uint32_t do_ping : 1; // 31 Do PING
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t xfer_size : 19; // 0..18 Transfer size in bytes
+ uint32_t packet_count : 10; // 19..28 Number of packets
+ uint32_t pid : 2; // 29..30 Packet ID
+ uint32_t do_ping : 1; // 31 Do PING
+ };
} dwc2_channel_tsize_t;
TU_VERIFY_STATIC(sizeof(dwc2_channel_tsize_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t num : 16; // 0..15 Frame number
- uint32_t remainning : 16; // 16..31 Frame remaining
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t num : 16; // 0..15 Frame number
+ uint32_t remainning : 16; // 16..31 Frame remaining
+ };
} dwc2_hfnum_t;
TU_VERIFY_STATIC(sizeof(dwc2_hfnum_t) == 4, "incorrect size");
// Host Channel
typedef struct {
- union {
- volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics
- volatile dwc2_channel_char_t hcchar_bm;
- };
- union {
- volatile uint32_t hcsplt; // 504 + 20*ch Host Channel Split Control
- volatile dwc2_channel_split_t hcsplt_bm;
- };
- volatile uint32_t hcint; // 508 + 20*ch Host Channel Interrupt
- volatile uint32_t hcintmsk; // 50C + 20*ch Host Channel Interrupt Mask
- union {
- volatile uint32_t hctsiz; // 510 + 20*ch Host Channel Transfer Size
- volatile dwc2_channel_tsize_t hctsiz_bm;
- };
- volatile uint32_t hcdma; // 514 + 20*ch Host Channel DMA Address
- uint32_t reserved518; // 518 + 20*ch
- volatile uint32_t hcdmab; // 51C + 20*ch Host Channel DMA Address
+ volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics
+ volatile uint32_t hcsplt; // 504 + 20*ch Host Channel Split Control
+ volatile uint32_t hcint; // 508 + 20*ch Host Channel Interrupt
+ volatile uint32_t hcintmsk; // 50C + 20*ch Host Channel Interrupt Mask
+ volatile uint32_t hctsiz; // 510 + 20*ch Host Channel Transfer Size
+ volatile uint32_t hcdma; // 514 + 20*ch Host Channel DMA Address
+ uint32_t reserved518; // 518 + 20*ch
+ volatile uint32_t hcdmab; // 51C + 20*ch Host Channel DMA Address
} dwc2_channel_t;
//--------------------------------------------------------------------
// Device Register Bitfield
//--------------------------------------------------------------------
-typedef struct TU_ATTR_PACKED {
- uint32_t speed : 2; // 0..1 Speed
- uint32_t nzsts_out_handshake : 1; // 2 Non-zero-length status OUT handshake
- uint32_t en_32khz_suspsend : 1; // 3 Enable 32-kHz SUSPEND mode
- uint32_t address : 7; // 4..10 Device address
- uint32_t period_frame_interval : 2; // 11..12 Periodic frame interval
- uint32_t en_out_nak : 1; // 13 Enable Device OUT NAK
- uint32_t xcvr_delay : 1; // 14 Transceiver delay
- uint32_t erratic_int_mask : 1; // 15 Erratic interrupt mask
- uint32_t rsv16 : 1; // 16 Reserved
- uint32_t ipg_iso_support : 1; // 17 Interpacket gap ISO support
- uint32_t epin_mismatch_count : 5; // 18..22 EP IN mismatch count
- uint32_t dma_desc : 1; // 23 Enable scatter/gatter DMA descriptor
- uint32_t period_schedule_interval : 2; // 24..25 Periodic schedule interval for scatter/gatter DMA
- uint32_t resume_valid : 6; // 26..31 Resume valid period
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t speed : 2; // 0..1 Speed
+ uint32_t nzsts_out_handshake : 1; // 2 Non-zero-length status OUT handshake
+ uint32_t en_32khz_suspsend : 1; // 3 Enable 32-kHz SUSPEND mode
+ uint32_t address : 7; // 4..10 Device address
+ uint32_t period_frame_interval : 2; // 11..12 Periodic frame interval
+ uint32_t en_out_nak : 1; // 13 Enable Device OUT NAK
+ uint32_t xcvr_delay : 1; // 14 Transceiver delay
+ uint32_t erratic_int_mask : 1; // 15 Erratic interrupt mask
+ uint32_t rsv16 : 1; // 16 Reserved
+ uint32_t ipg_iso_support : 1; // 17 Interpacket gap ISO support
+ uint32_t epin_mismatch_count : 5; // 18..22 EP IN mismatch count
+ uint32_t dma_desc : 1; // 23 Enable scatter/gather DMA descriptor
+ uint32_t period_schedule_interval : 2; // 24..25 Periodic schedule interval for scatter/gather DMA
+ uint32_t resume_valid : 6; // 26..31 Resume valid period
+ };
} dwc2_dcfg_t;
TU_VERIFY_STATIC(sizeof(dwc2_dcfg_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t remote_wakeup_signal : 1; // 0 Remote wakeup signal
- uint32_t soft_disconnet : 1; // 1 Soft disconnect
- uint32_t gnp_in_nak_status : 1; // 2 Global non-periodic NAK IN status
- uint32_t gout_nak_status : 1; // 3 Global OUT NAK status
- uint32_t test_control : 3; // 4..6 Test control
- uint32_t set_gnp_in_nak : 1; // 7 Set global non-periodic IN NAK
- uint32_t clear_gnp_in_nak : 1; // 8 Clear global non-periodic IN NAK
- uint32_t set_gout_nak : 1; // 9 Set global OUT NAK
- uint32_t clear_gout_nak : 1; // 10 Clear global OUT NAK
- uint32_t poweron_prog_done : 1; // 11 Power-on programming done
- uint32_t rsv12 : 1; // 12 Reserved
- uint32_t global_multi_count : 2; // 13..14 Global multi-count
- uint32_t ignore_frame_number : 1; // 15 Ignore frame number
- uint32_t nak_on_babble : 1; // 16 NAK on babble
- uint32_t en_cont_on_bna : 1; // 17 Enable continue on BNA
- uint32_t deep_sleep_besl_reject : 1; // 18 Deep sleep BESL reject
- uint32_t service_interval : 1; // 19 Service interval for ISO IN endpoint
- uint32_t rsv20_31 :12; // 20..31 Reserved
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t remote_wakeup_signal : 1; // 0 Remote wakeup signal
+ uint32_t soft_disconnet : 1; // 1 Soft disconnect
+ uint32_t gnp_in_nak_status : 1; // 2 Global non-periodic NAK IN status
+ uint32_t gout_nak_status : 1; // 3 Global OUT NAK status
+ uint32_t test_control : 3; // 4..6 Test control
+ uint32_t set_gnp_in_nak : 1; // 7 Set global non-periodic IN NAK
+ uint32_t clear_gnp_in_nak : 1; // 8 Clear global non-periodic IN NAK
+ uint32_t set_gout_nak : 1; // 9 Set global OUT NAK
+ uint32_t clear_gout_nak : 1; // 10 Clear global OUT NAK
+ uint32_t poweron_prog_done : 1; // 11 Power-on programming done
+ uint32_t rsv12 : 1; // 12 Reserved
+ uint32_t global_multi_count : 2; // 13..14 Global multi-count
+ uint32_t ignore_frame_number : 1; // 15 Ignore frame number
+ uint32_t nak_on_babble : 1; // 16 NAK on babble
+ uint32_t en_cont_on_bna : 1; // 17 Enable continue on BNA
+ uint32_t deep_sleep_besl_reject : 1; // 18 Deep sleep BESL reject
+ uint32_t service_interval : 1; // 19 Service interval for ISO IN endpoint
+ uint32_t rsv20_31 :12; // 20..31 Reserved
+ };
} dwc2_dctl_t;
TU_VERIFY_STATIC(sizeof(dwc2_dctl_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t suspend_status : 1; // 0 Suspend status
- uint32_t enum_speed : 2; // 1..2 Enumerated speed
- uint32_t erratic_err : 1; // 3 Erratic error
- uint32_t rsv4_7 : 4; // 4..7 Reserved
- uint32_t frame_number : 14; // 8..21 Frame/MicroFrame number
- uint32_t line_status : 2; // 22..23 Line status
- uint32_t rsv24_31 : 8; // 24..31 Reserved
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t suspend_status : 1; // 0 Suspend status
+ uint32_t enum_speed : 2; // 1..2 Enumerated speed
+ uint32_t erratic_err : 1; // 3 Erratic error
+ uint32_t rsv4_7 : 4; // 4..7 Reserved
+ uint32_t frame_number :14; // 8..21 Frame/MicroFrame number
+ uint32_t line_status : 2; // 22..23 Line status
+ uint32_t rsv24_31 : 8; // 24..31 Reserved
+ };
} dwc2_dsts_t;
TU_VERIFY_STATIC(sizeof(dwc2_dsts_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t xfer_complete : 1; // 0 Transfer complete
- uint32_t disabled : 1; // 1 Endpoint disabled
- uint32_t ahb_err : 1; // 2 AHB error
- uint32_t timeout : 1; // 3 Timeout
- uint32_t in_rx_txfe : 1; // 4 IN token received when TxFIFO is empty
- uint32_t in_rx_ep_mismatch : 1; // 5 IN token received with EP mismatch
- uint32_t in_ep_nak_effective : 1; // 6 IN endpoint NAK effective
- uint32_t txfifo_empty : 1; // 7 TX FIFO empty
- uint32_t txfifo_underrun : 1; // 8 Tx FIFO under run
- uint32_t bna : 1; // 9 Buffer not available
- uint32_t rsv10 : 1; // 10 Reserved
- uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status
- uint32_t babble_err : 1; // 12 Babble error
- uint32_t nak : 1; // 13 NAK
- uint32_t nyet : 1; // 14 NYET
- uint32_t rsv14_31 :17; // 15..31 Reserved
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t xfer_complete : 1; // 0 Transfer complete
+ uint32_t disabled : 1; // 1 Endpoint disabled
+ uint32_t ahb_err : 1; // 2 AHB error
+ uint32_t timeout : 1; // 3 Timeout
+ uint32_t in_rx_txfe : 1; // 4 IN token received when TxFIFO is empty
+ uint32_t in_rx_ep_mismatch : 1; // 5 IN token received with EP mismatch
+ uint32_t in_ep_nak_effective : 1; // 6 IN endpoint NAK effective
+ uint32_t txfifo_empty : 1; // 7 TX FIFO empty
+ uint32_t txfifo_underrun : 1; // 8 Tx FIFO under run
+ uint32_t bna : 1; // 9 Buffer not available
+ uint32_t rsv10 : 1; // 10 Reserved
+ uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status
+ uint32_t babble_err : 1; // 12 Babble error
+ uint32_t nak : 1; // 13 NAK
+ uint32_t nyet : 1; // 14 NYET
+ uint32_t rsv14_31 :17; // 15..31 Reserved
+ };
} dwc2_diepint_t;
TU_VERIFY_STATIC(sizeof(dwc2_diepint_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t mps : 11; // 0..10 Maximum packet size, EP0 only use 2 bit
- uint32_t next_ep : 4; // 11..14 Next endpoint number
- uint32_t active : 1; // 15 Active
- const uint32_t dpid_iso_odd : 1; // 16 DATA0/DATA1 for bulk/interrupt, odd frame for isochronous
- const uint32_t nak_status : 1; // 17 NAK status
- uint32_t type : 2; // 18..19 Endpoint type
- uint32_t rsv20 : 1; // 20 Reserved
- uint32_t stall : 1; // 21 Stall
- uint32_t tx_fifo_num : 4; // 22..25 Tx FIFO number (IN)
- uint32_t clear_nak : 1; // 26 Clear NAK
- uint32_t set_nak : 1; // 27 Set NAK
- uint32_t set_data0_iso_even : 1; // 28 Set DATA0 if bulk/interrupt, even frame for isochronous
- uint32_t set_data1_iso_odd : 1; // 29 Set DATA1 if bulk/interrupt, odd frame for isochronous
- uint32_t disable : 1; // 30 Disable
- uint32_t enable : 1; // 31 Enable
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t mps : 11; // 0..10 Maximum packet size, EP0 only use 2 bits
+ uint32_t next_ep : 4; // 11..14 Next endpoint number
+ uint32_t active : 1; // 15 Active
+ uint32_t dpid_iso_odd : 1; // 16 DATA0/DATA1 for bulk/interrupt, odd frame for isochronous
+ uint32_t nak_status : 1; // 17 NAK status
+ uint32_t type : 2; // 18..19 Endpoint type
+ uint32_t rsv20 : 1; // 20 Reserved
+ uint32_t stall : 1; // 21 Stall
+ uint32_t tx_fifo_num : 4; // 22..25 Tx FIFO number (IN)
+ uint32_t clear_nak : 1; // 26 Clear NAK
+ uint32_t set_nak : 1; // 27 Set NAK
+ uint32_t set_data0_iso_even : 1; // 28 Set DATA0 if bulk/interrupt, even frame for isochronous
+ uint32_t set_data1_iso_odd : 1; // 29 Set DATA1 if bulk/interrupt, odd frame for isochronous
+ uint32_t disable : 1; // 30 Disable
+ uint32_t enable : 1; // 31 Enable
+ };
} dwc2_depctl_t;
TU_VERIFY_STATIC(sizeof(dwc2_depctl_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t xfer_complete : 1; // 0 Transfer complete
- uint32_t disabled : 1; // 1 Endpoint disabled
- uint32_t ahb_err : 1; // 2 AHB error
- uint32_t setup_phase_done : 1; // 3 Setup phase done
- uint32_t out_rx_ep_disabled : 1; // 4 OUT token received when endpoint disabled
- uint32_t status_phase_rx : 1; // 5 Status phase received
- uint32_t setup_b2b : 1; // 6 Setup packet back-to-back
- uint32_t rsv7 : 1; // 7 Reserved
- uint32_t out_packet_err : 1; // 8 OUT packet error
- uint32_t bna : 1; // 9 Buffer not available
- uint32_t rsv10 : 1; // 10 Reserved
- uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status
- uint32_t babble_err : 1; // 12 Babble error
- uint32_t nak : 1; // 13 NAK
- uint32_t nyet : 1; // 14 NYET
- uint32_t setup_packet_rx : 1; // 15 Setup packet received (Buffer DMA Mode only)
- uint32_t rsv16_31 :16; // 16..31 Reserved
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t xfer_complete : 1; // 0 Transfer complete
+ uint32_t disabled : 1; // 1 Endpoint disabled
+ uint32_t ahb_err : 1; // 2 AHB error
+ uint32_t setup_phase_done : 1; // 3 Setup phase done
+ uint32_t out_rx_ep_disabled : 1; // 4 OUT token received when endpoint disabled
+ uint32_t status_phase_rx : 1; // 5 Status phase received
+ uint32_t setup_b2b : 1; // 6 Setup packet back-to-back
+ uint32_t rsv7 : 1; // 7 Reserved
+ uint32_t out_packet_err : 1; // 8 OUT packet error
+ uint32_t bna : 1; // 9 Buffer not available
+ uint32_t rsv10 : 1; // 10 Reserved
+ uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status
+ uint32_t babble_err : 1; // 12 Babble error
+ uint32_t nak : 1; // 13 NAK
+ uint32_t nyet : 1; // 14 NYET
+ uint32_t setup_packet_rx : 1; // 15 Setup packet received (Buffer DMA Mode only)
+ uint32_t rsv16_31 :16; // 16..31 Reserved
+ };
} dwc2_doepint_t;
TU_VERIFY_STATIC(sizeof(dwc2_doepint_t) == 4, "incorrect size");
-typedef struct TU_ATTR_PACKED {
- uint32_t xfer_size : 19; // 0..18 Transfer size in bytes
- uint32_t packet_count : 10; // 19..28 Number of packets
- uint32_t mc_pid : 2; // 29..30 IN: Multi Count, OUT: PID
+typedef union {
+ uint32_t value;
+ struct TU_ATTR_PACKED {
+ uint32_t xfer_size : 19; // 0..18 Transfer size in bytes
+ uint32_t packet_count : 10; // 19..28 Number of packets
+ uint32_t mc_pid : 2; // 29..30 IN: Multi Count, OUT: PID
+ };
} dwc2_ep_tsize_t;
TU_VERIFY_STATIC(sizeof(dwc2_ep_tsize_t) == 4, "incorrect size");
@@ -601,26 +656,19 @@ typedef struct {
union {
volatile uint32_t diepctl;
volatile uint32_t doepctl;
-
volatile uint32_t ctl;
- volatile dwc2_depctl_t ctl_bm;
};
uint32_t rsv04;
union {
volatile uint32_t intr;
-
volatile uint32_t diepint;
- volatile dwc2_diepint_t diepint_bm;
-
volatile uint32_t doepint;
- volatile dwc2_doepint_t doepint_bm;
};
uint32_t rsv0c;
union {
volatile uint32_t dieptsiz;
volatile uint32_t doeptsiz;
volatile uint32_t tsiz;
- volatile dwc2_ep_tsize_t tsiz_bm;
};
union {
volatile uint32_t diepdma;
@@ -628,7 +676,7 @@ typedef struct {
};
volatile uint32_t dtxfsts;
uint32_t rsv1c;
-}dwc2_dep_t;
+} dwc2_dep_t;
TU_VERIFY_STATIC(sizeof(dwc2_dep_t) == 0x20, "incorrect size");
@@ -636,157 +684,108 @@ TU_VERIFY_STATIC(sizeof(dwc2_dep_t) == 0x20, "incorrect size");
// CSR Register Map
//--------------------------------------------------------------------
typedef struct {
- //------------- Core Global -------------//
- union {
- volatile uint32_t gotgctl; // 000 OTG Control and Status
- volatile dwc2_gotgctl_t gotgctl_bm;
- };
- union {
- volatile uint32_t gotgint; // 004 OTG Interrupt
- volatile dwc2_gotgint_t gotgint_bm;
- };
- union {
- volatile uint32_t gahbcfg; // 008 AHB Configuration
- volatile dwc2_gahbcfg_t gahbcfg_bm;
- };
- union {
- volatile uint32_t gusbcfg; // 00c USB Configuration
- volatile dwc2_gusbcfg_t gusbcfg_bm;
- };
- union {
- volatile uint32_t grstctl; // 010 Reset
- volatile dwc2_grstctl_t grstctl_bm;
- };
- volatile uint32_t gintsts; // 014 Interrupt
- volatile uint32_t gintmsk; // 018 Interrupt Mask
- volatile uint32_t grxstsr; // 01c Receive Status Debug Read
- union {
- volatile uint32_t grxstsp; // 020 Receive Status Read/Pop
- volatile dwc2_grxstsp_t grxstsp_bm;
- };
- volatile uint32_t grxfsiz; // 024 Receive FIFO Size
+ //------------- Core Global -------------
+ volatile uint32_t gotgctl; // 000 OTG Control and Status
+ volatile uint32_t gotgint; // 004 OTG Interrupt
+ volatile uint32_t gahbcfg; // 008 AHB Configuration
+ volatile uint32_t gusbcfg; // 00c USB Configuration
+ volatile uint32_t grstctl; // 010 Reset
+ volatile uint32_t gintsts; // 014 Interrupt
+ volatile uint32_t gintmsk; // 018 Interrupt Mask
+ volatile uint32_t grxstsr; // 01c Receive Status Debug Read
+ volatile uint32_t grxstsp; // 020 Receive Status Read/Pop
+ volatile uint32_t grxfsiz; // 024 Receive FIFO Size
union {
volatile uint32_t dieptxf0; // 028 EP0 Tx FIFO Size
volatile uint32_t gnptxfsiz; // 028 Non-periodic Transmit FIFO Size
};
union {
volatile uint32_t hnptxsts; // 02c Non-periodic Transmit FIFO/Queue Status
- volatile dwc2_hnptxsts_t hnptxsts_bm;
volatile uint32_t gnptxsts;
};
- volatile uint32_t gi2cctl; // 030 I2C Address
- volatile uint32_t gpvndctl; // 034 PHY Vendor Control
+ volatile uint32_t gi2cctl; // 030 I2C Address
+ volatile uint32_t gpvndctl; // 034 PHY Vendor Control
union {
volatile uint32_t ggpio; // 038 General Purpose IO
volatile uint32_t stm32_gccfg; // 038 STM32 General Core Configuration
};
- volatile uint32_t guid; // 03C User (Application programmable) ID
- volatile uint32_t gsnpsid; // 040 Synopsys ID + Release version
- volatile uint32_t ghwcfg1; // 044 User Hardware Configuration1: endpoint dir (2 bit per ep)
- union {
- volatile uint32_t ghwcfg2; // 048 User Hardware Configuration2
- volatile dwc2_ghwcfg2_t ghwcfg2_bm;
- };
- union {
- volatile uint32_t ghwcfg3; // 04C User Hardware Configuration3
- volatile dwc2_ghwcfg3_t ghwcfg3_bm;
- };
+ volatile uint32_t guid; // 03C User (Application programmable) ID
+ volatile uint32_t gsnpsid; // 040 Synopsys ID + Release version
+ volatile uint32_t ghwcfg1; // 044 User Hardware Configuration1: endpoint dir (2 bit per ep)
+ volatile uint32_t ghwcfg2; // 048 User Hardware Configuration2
+ volatile uint32_t ghwcfg3; // 04C User Hardware Configuration3
union {
volatile uint32_t ghwcfg4; // 050 User Hardware Configuration4
volatile dwc2_ghwcfg4_t ghwcfg4_bm;
};
- volatile uint32_t glpmcfg; // 054 Core LPM Configuration
- volatile uint32_t gpwrdn; // 058 Power Down
- volatile uint32_t gdfifocfg; // 05C DFIFO Software Configuration
- volatile uint32_t gadpctl; // 060 ADP Timer, Control and Status
- uint32_t reserved64[39]; // 064..0FF
- volatile uint32_t hptxfsiz; // 100 Host Periodic Tx FIFO Size
- volatile uint32_t dieptxf[15]; // 104..13C Device Periodic Transmit FIFO Size
- uint32_t reserved140[176]; // 140..3FF
+ volatile uint32_t glpmcfg; // 054 Core LPM Configuration
+ volatile uint32_t gpwrdn; // 058 Power Down
+ volatile uint32_t gdfifocfg; // 05C DFIFO Software Configuration
+ volatile uint32_t gadpctl; // 060 ADP Timer, Control and Status
+ uint32_t reserved64[39]; // 064..0FF
+ volatile uint32_t hptxfsiz; // 100 Host Periodic Tx FIFO Size
+ volatile uint32_t dieptxf[15]; // 104..13C Device Periodic Transmit FIFO Size
+ uint32_t reserved140[176]; // 140..3FF
- //------------ Host -------------//
- volatile uint32_t hcfg; // 400 Host Configuration
- volatile uint32_t hfir; // 404 Host Frame Interval
- union {
- volatile uint32_t hfnum; // 408 Host Frame Number / Frame Remaining
- volatile dwc2_hfnum_t hfnum_bm;
- };
- uint32_t reserved40c; // 40C
- union {
- volatile uint32_t hptxsts; // 410 Host Periodic TX FIFO / Queue Status
- volatile dwc2_hptxsts_t hptxsts_bm;
- };
- volatile uint32_t haint; // 414 Host All Channels Interrupt
- volatile uint32_t haintmsk; // 418 Host All Channels Interrupt Mask
- volatile uint32_t hflbaddr; // 41C Host Frame List Base Address
- uint32_t reserved420[8]; // 420..43F
- union {
- volatile uint32_t hprt; // 440 Host Port Control and Status
- volatile dwc2_hprt_t hprt_bm;
- };
- uint32_t reserved444[47]; // 444..4FF
+ //------------ Host -------------
+ volatile uint32_t hcfg; // 400 Host Configuration
+ volatile uint32_t hfir; // 404 Host Frame Interval
+ volatile uint32_t hfnum; // 408 Host Frame Number / Frame Remaining
+ uint32_t reserved40c; // 40C
+ volatile uint32_t hptxsts; // 410 Host Periodic TX FIFO / Queue Status
+ volatile uint32_t haint; // 414 Host All Channels Interrupt
+ volatile uint32_t haintmsk; // 418 Host All Channels Interrupt Mask
+ volatile uint32_t hflbaddr; // 41C Host Frame List Base Address
+ uint32_t reserved420[8]; // 420..43F
+ volatile uint32_t hprt; // 440 Host Port Control and Status
+ uint32_t reserved444[47]; // 444..4FF
- //------------- Host Channel -------------//
- dwc2_channel_t channel[16]; // 500..6FF Host Channels 0-15
- uint32_t reserved700[64]; // 700..7FF
+ //------------- Host Channel --------
+ dwc2_channel_t channel[16]; // 500..6FF Host Channels 0-15
+ uint32_t reserved700[64]; // 700..7FF
- //------------- Device -----------//
- union {
- volatile uint32_t dcfg; // 800 Device Configuration
- volatile dwc2_dcfg_t dcfg_bm;
- };
- union {
- volatile uint32_t dctl; // 804 Device Control
- volatile dwc2_dctl_t dctl_bm;
- };
- union {
- volatile uint32_t dsts; // 808 Device Status (RO)
- volatile dwc2_dsts_t dsts_bm;
- };
- uint32_t reserved80c; // 80C
- union {
- volatile uint32_t diepmsk; // 810 Device IN Endpoint Interrupt Mask
- volatile dwc2_diepint_t diepmsk_bm;
- };
- union {
- volatile uint32_t doepmsk; // 814 Device OUT Endpoint Interrupt Mask
- volatile dwc2_doepint_t doepmsk_bm;
- };
- volatile uint32_t daint; // 818 Device All Endpoints Interrupt
- volatile uint32_t daintmsk; // 81C Device All Endpoints Interrupt Mask
- volatile uint32_t dtknqr1; // 820 Device IN token sequence learning queue read1
- volatile uint32_t dtknqr2; // 824 Device IN token sequence learning queue read2
- volatile uint32_t dvbusdis; // 828 Device VBUS Discharge Time
- volatile uint32_t dvbuspulse; // 82C Device VBUS Pulsing Time
- volatile uint32_t dthrctl; // 830 Device threshold Control
- volatile uint32_t diepempmsk; // 834 Device IN Endpoint FIFO Empty Interrupt Mask
+ //------------- Device -----------
+ volatile uint32_t dcfg; // 800 Device Configuration
+ volatile uint32_t dctl; // 804 Device Control
+ volatile uint32_t dsts; // 808 Device Status (RO)
+ uint32_t reserved80c; // 80C
+ volatile uint32_t diepmsk; // 810 Device IN Endpoint Interrupt Mask
+ volatile uint32_t doepmsk; // 814 Device OUT Endpoint Interrupt Mask
+ volatile uint32_t daint; // 818 Device All Endpoints Interrupt
+ volatile uint32_t daintmsk; // 81C Device All Endpoints Interrupt Mask
+ volatile uint32_t dtknqr1; // 820 Device IN token sequence learning queue read1
+ volatile uint32_t dtknqr2; // 824 Device IN token sequence learning queue read2
+ volatile uint32_t dvbusdis; // 828 Device VBUS Discharge Time
+ volatile uint32_t dvbuspulse; // 82C Device VBUS Pulsing Time
+ volatile uint32_t dthrctl; // 830 Device threshold Control
+ volatile uint32_t diepempmsk; // 834 Device IN Endpoint FIFO Empty Interrupt Mask
- // Device Each Endpoint (IN/OUT) Interrupt/Mask for generating dedicated EP interrupt line
- // require OTG_MULTI_PROC_INTRPT=1
- volatile uint32_t deachint; // 838 Device Each Endpoint Interrupt
- volatile uint32_t deachmsk; // 83C Device Each Endpoint Interrupt mask
- volatile uint32_t diepeachmsk[16]; // 840..87C Device Each IN Endpoint mask
- volatile uint32_t doepeachmsk[16]; // 880..8BF Device Each OUT Endpoint mask
- uint32_t reserved8c0[16]; // 8C0..8FF
+ // Device Each Endpoint (IN/OUT) Interrupt/Mask for generating dedicated EP interrupt line require
+ // OTG_MULTI_PROC_INTRPT=1
+ volatile uint32_t deachint; // 838 Device Each Endpoint Interrupt
+ volatile uint32_t deachmsk; // 83C Device Each Endpoint Interrupt mask
+ volatile uint32_t diepeachmsk[16]; // 840..87C Device Each IN Endpoint mask
+ volatile uint32_t doepeachmsk[16]; // 880..8BF Device Each OUT Endpoint mask
+ uint32_t reserved8c0[16]; // 8C0..8FF
- //------------- Device Endpoint -------------//
- union {
- dwc2_dep_t ep[2][16]; // 0: IN, 1 OUT
- struct {
- dwc2_dep_t epin[16]; // 900..AFF IN Endpoints
- dwc2_dep_t epout[16]; // B00..CFF OUT Endpoints
- };
+ //------------- Device Endpoint -----
+ union {
+ dwc2_dep_t ep[2][16]; // 0: IN, 1 OUT
+ struct {
+ dwc2_dep_t epin[16]; // 900..AFF IN Endpoints
+ dwc2_dep_t epout[16]; // B00..CFF OUT Endpoints
};
- uint32_t reservedd00[64]; // D00..DFF
+ };
+ uint32_t reservedd00[64]; // D00..DFF
- //------------- Power Clock -------------//
- volatile uint32_t pcgcctl; // E00 Power and Clock Gating Characteristic Control
- volatile uint32_t pcgcctl1; // E04 Power and Clock Gating Characteristic Control 1
- uint32_t reservede08[126]; // E08..FFF
+ //------------- Power Clock ---------
+ volatile uint32_t pcgcctl; // E00 Power and Clock Gating Characteristic Control
+ volatile uint32_t pcgcctl1; // E04 Power and Clock Gating Characteristic Control 1
+ uint32_t reservede08[126]; // E08..FFF
- //------------- FIFOs -------------//
- // Word-accessed only using first pointer since it auto shift
- volatile uint32_t fifo[16][0x400]; // 1000..FFFF Endpoint FIFO
+ //------------- FIFOs -------------
+ // Word-accessed only using first pointer since it auto shift
+ volatile uint32_t fifo[16][0x400]; // 1000..FFFF Endpoint FIFO
} dwc2_regs_t;
TU_VERIFY_STATIC(offsetof(dwc2_regs_t, hcfg ) == 0x0400, "incorrect size");
diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c
index 65288e30c..4ab6446e1 100644
--- a/src/portable/synopsys/dwc2/hcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/hcd_dwc2.c
@@ -44,8 +44,6 @@
#endif
#define DWC2_CHANNEL_COUNT_MAX 16 // absolute max channel count
-#define DWC2_CHANNEL_COUNT(_dwc2) tu_min8((_dwc2)->ghwcfg2_bm.num_host_ch + 1, DWC2_CHANNEL_COUNT_MAX)
-
TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index");
enum {
@@ -97,7 +95,6 @@ typedef struct {
uint8_t err_count : 3;
uint8_t period_split_nyet_count : 3;
uint8_t halted_nyet : 1;
- uint8_t halted_sof_schedule : 1;
};
uint8_t result;
@@ -117,9 +114,15 @@ hcd_data_t _hcd_data;
//--------------------------------------------------------------------
//
//--------------------------------------------------------------------
+TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_channel_count(const dwc2_regs_t* dwc2) {
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ return tu_min8(ghwcfg2.num_host_ch + 1, DWC2_CHANNEL_COUNT_MAX);
+}
+
TU_ATTR_ALWAYS_INLINE static inline tusb_speed_t hprt_speed_get(dwc2_regs_t* dwc2) {
tusb_speed_t speed;
- switch(dwc2->hprt_bm.speed) {
+ const dwc2_hprt_t hprt = {.value = dwc2->hprt};
+ switch(hprt.speed) {
case HPRT_SPEED_HIGH: speed = TUSB_SPEED_HIGH; break;
case HPRT_SPEED_FULL: speed = TUSB_SPEED_FULL; break;
case HPRT_SPEED_LOW : speed = TUSB_SPEED_LOW ; break;
@@ -134,7 +137,8 @@ TU_ATTR_ALWAYS_INLINE static inline tusb_speed_t hprt_speed_get(dwc2_regs_t* dwc
TU_ATTR_ALWAYS_INLINE static inline bool dma_host_enabled(const dwc2_regs_t* dwc2) {
(void) dwc2;
// Internal DMA only
- return CFG_TUH_DWC2_DMA_ENABLE && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA;
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
+ return CFG_TUH_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA;
}
#if CFG_TUH_MEM_DCACHE_ENABLE
@@ -156,7 +160,7 @@ bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) {
// Allocate a channel for new transfer
TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_alloc(dwc2_regs_t* dwc2) {
- const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
+ const uint8_t max_channel = dwc2_channel_count(dwc2);
for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
if (!xfer->allocated) {
@@ -169,15 +173,18 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_alloc(dwc2_regs_t* dwc2) {
}
// Check if is periodic (interrupt/isochronous)
-TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_periodic(uint8_t ep_type) {
- return ep_type == HCCHAR_EPTYPE_INTERRUPT || ep_type == HCCHAR_EPTYPE_ISOCHRONOUS;
+TU_ATTR_ALWAYS_INLINE static inline bool channel_is_periodic(uint32_t hcchar) {
+ const dwc2_channel_char_t hcchar_bm = {.value = hcchar};
+ return hcchar_bm.ep_type == HCCHAR_EPTYPE_INTERRUPT || hcchar_bm.ep_type == HCCHAR_EPTYPE_ISOCHRONOUS;
}
TU_ATTR_ALWAYS_INLINE static inline uint8_t req_queue_avail(const dwc2_regs_t* dwc2, bool is_period) {
if (is_period) {
- return dwc2->hptxsts_bm.req_queue_available;
+ const dwc2_hptxsts_t hptxsts = {.value = dwc2->hptxsts};
+ return hptxsts.req_queue_available;
} else {
- return dwc2->hnptxsts_bm.req_queue_available;
+ const dwc2_hnptxsts_t hnptxsts = {.value = dwc2->hnptxsts};
+ return hnptxsts.req_queue_available;
}
}
@@ -189,7 +196,7 @@ 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, edpt_is_periodic(channel->hcchar_bm.ep_type)));
+ TU_ASSERT(req_queue_avail(dwc2, channel_is_periodic(channel->hcchar)));
channel->hcintmsk |= HCINT_HALTED;
channel->hcchar |= HCCHAR_CHDIS | HCCHAR_CHENA; // must set both CHDIS and CHENA
return true;
@@ -197,18 +204,18 @@ 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, edpt_is_periodic(channel->hcchar_bm.ep_type)));
+ TU_ASSERT(req_queue_avail(dwc2, channel_is_periodic(channel->hcchar)));
channel->hcchar |= HCCHAR_CHENA;
return true;
}
// Find currently enabled channel. Note: EP0 is bidirectional
TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_find_enabled(dwc2_regs_t* dwc2, uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir) {
- const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
+ const uint8_t max_channel = dwc2_channel_count(dwc2);
for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
if (_hcd_data.xfer[ch_id].allocated) {
- const dwc2_channel_char_t hcchar_bm = dwc2->channel[ch_id].hcchar_bm;
- if (hcchar_bm.dev_addr == dev_addr && hcchar_bm.ep_num == ep_num && (ep_num == 0 || hcchar_bm.ep_dir == ep_dir)) {
+ const dwc2_channel_char_t hcchar = {.value = dwc2->channel[ch_id].hcchar};
+ if (hcchar.dev_addr == dev_addr && hcchar.ep_num == ep_num && (ep_num == 0 || hcchar.ep_dir == ep_dir)) {
return ch_id;
}
}
@@ -305,12 +312,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t pa
static void dfifo_host_init(uint8_t rhport) {
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+ const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
// Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per channel
const bool is_dma = dma_host_enabled(dwc2);
uint16_t dfifo_top = dwc2_controller->ep_fifo_size/4;
if (is_dma) {
- dfifo_top -= dwc2->ghwcfg2_bm.num_host_ch;
+ dfifo_top -= ghwcfg2.num_host_ch;
}
// fixed allocation for now, improve later:
@@ -320,7 +328,7 @@ static void dfifo_host_init(uint8_t rhport) {
uint32_t ptx_largest = is_highspeed ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4;
uint16_t nptxfsiz = 2 * nptx_largest;
- uint16_t rxfsiz = 2 * (ptx_largest + 2) + dwc2->ghwcfg2_bm.num_host_ch;
+ uint16_t rxfsiz = 2 * (ptx_largest + 2) + ghwcfg2.num_host_ch;
TU_ASSERT(dfifo_top >= (nptxfsiz + rxfsiz),);
uint16_t ptxfsiz = dfifo_top - (nptxfsiz + rxfsiz);
@@ -382,7 +390,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
dwc2->hprt = HPRT_POWER; // turn on VBUS
// Enable required interrupts
- dwc2->gintmsk |= GINTSTS_OTGINT | GINTSTS_CONIDSTSCHNG | GINTSTS_HPRTINT | GINTSTS_HCINT;
+ dwc2->gintmsk |= GINTSTS_OTGINT | GINTSTS_CONIDSTSCHNG | GINTSTS_HPRTINT | GINTSTS_HCINT | GINTSTS_DISCINT;
// NPTX can hold at least 2 packet, change interrupt level to half-empty
uint32_t gahbcfg = dwc2->gahbcfg & ~GAHBCFG_TX_FIFO_EPMTY_LVL;
@@ -520,10 +528,11 @@ bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
// clean up channel after part of transfer is done but the whole urb is not complete
static void channel_xfer_out_wrapup(dwc2_regs_t* dwc2, uint8_t ch_id) {
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
- dwc2_channel_t* channel = &dwc2->channel[ch_id];
+ const dwc2_channel_t* channel = &dwc2->channel[ch_id];
hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id];
- edpt->next_pid = channel->hctsiz_bm.pid; // save PID
+ const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz};
+ edpt->next_pid = hctsiz.pid; // save PID
/* Since hctsiz.xfersize field reflects the number of bytes transferred via the AHB, not the USB)
* For IN: we can use hctsiz.xfersize as remaining bytes.
@@ -531,9 +540,10 @@ static void channel_xfer_out_wrapup(dwc2_regs_t* dwc2, uint8_t ch_id) {
* number of packets that have been transferred via the USB. This is always an integral number of packets if the
* transfer was halted before its normal completion.
*/
- const uint16_t remain_packets = channel->hctsiz_bm.packet_count;
- const uint16_t total_packets = cal_packet_count(edpt->buflen, channel->hcchar_bm.ep_size);
- const uint16_t actual_bytes = (total_packets - remain_packets) * channel->hcchar_bm.ep_size;
+ const uint16_t remain_packets = hctsiz.packet_count;
+ const dwc2_channel_char_t hcchar = {.value = channel->hcchar};
+ const uint16_t total_packets = cal_packet_count(edpt->buflen, hcchar.ep_size);
+ const uint16_t actual_bytes = (total_packets - remain_packets) * hcchar.ep_size;
xfer->fifo_bytes = 0;
xfer->xferred_bytes += actual_bytes;
@@ -546,7 +556,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) {
hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id];
dwc2_channel_char_t* hcchar_bm = &edpt->hcchar_bm;
dwc2_channel_t* channel = &dwc2->channel[ch_id];
- bool const is_period = edpt_is_periodic(hcchar_bm->ep_type);
+ bool const is_period = channel_is_periodic(edpt->hcchar);
// clear previous state
xfer->fifo_bytes = 0;
@@ -559,12 +569,15 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) {
// hctsiz: zero length packet still count as 1
const uint16_t packet_count = cal_packet_count(edpt->buflen, hcchar_bm->ep_size);
- uint32_t hctsiz = (edpt->next_pid << HCTSIZ_PID_Pos) | (packet_count << HCTSIZ_PKTCNT_Pos) | edpt->buflen;
+ dwc2_channel_tsize_t hctsiz = {.value = 0};
+ hctsiz.pid = edpt->next_pid; // next PID is set in transfer complete interrupt
+ hctsiz.packet_count = packet_count;
+ hctsiz.xfer_size = edpt->buflen;
if (edpt->do_ping && edpt->speed == TUSB_SPEED_HIGH &&
edpt->next_pid != HCTSIZ_PID_SETUP && hcchar_bm->ep_dir == TUSB_DIR_OUT) {
- hctsiz |= HCTSIZ_DOPING;
+ hctsiz.do_ping = 1;
}
- channel->hctsiz = hctsiz;
+ channel->hctsiz = hctsiz.value;
edpt->do_ping = 0;
// pre-calculate next PID based on packet count, adjusted in transfer complete interrupt if short packet
@@ -705,18 +718,23 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
//--------------------------------------------------------------------
// HCD Event Handler
//--------------------------------------------------------------------
+
+// retry an IN transfer, channel must be halted
static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) {
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];
+ dwc2_channel_t* channel = &dwc2->channel[ch_id];
+ dwc2_channel_char_t hcchar = {.value = channel->hcchar};
- if (edpt_is_periodic(channel->hcchar_bm.ep_type)){
+ if (channel_is_periodic(hcchar.value)){
+ const dwc2_channel_split_t hcsplt = {.value = channel->hcsplt};
// retry immediately for periodic split NYET if we haven't reach max retry
- if (channel->hcsplt_bm.split_en && channel->hcsplt_bm.split_compl && (hcint & HCINT_NYET || xfer->halted_nyet)) {
+ if (hcsplt.split_en && hcsplt.split_compl && (hcint & HCINT_NYET || xfer->halted_nyet)) {
xfer->period_split_nyet_count++;
xfer->halted_nyet = 0;
if (xfer->period_split_nyet_count < HCD_XFER_PERIOD_SPLIT_NYET_MAX) {
- channel->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame
+ hcchar.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame
+ channel->hcchar = hcchar.value;
channel_send_in_token(dwc2, channel);
return;
} else {
@@ -725,18 +743,20 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
}
}
- // for periodic, de-allocate channel, enable SOF set frame counter for later transfer
- edpt->next_pid = channel->hctsiz_bm.pid; // save PID
- edpt->uframe_countdown = edpt->uframe_interval;
- dwc2->gintmsk |= GINTSTS_SOF;
-
- if (hcint & HCINT_HALTED) {
+ const uint32_t ucount = (hprt_speed_get(dwc2) == TUSB_SPEED_HIGH ? 1 : 8);
+ if (edpt->uframe_interval == ucount) {
+ // retry on next frame if bInterval is 1
+ hcchar.odd_frame = 1 - (dwc2->hfnum & 1);
+ channel->hcchar = hcchar.value;
+ channel_send_in_token(dwc2, channel);
+ } else {
+ // otherwise, de-allocate channel, enable SOF set frame counter for later transfer
+ const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz};
+ edpt->next_pid = hctsiz.pid; // save PID
+ edpt->uframe_countdown = edpt->uframe_interval - ucount;
+ dwc2->gintmsk |= GINTSTS_SOF;
// already halted, de-allocate channel (called from DMA isr)
channel_dealloc(dwc2, ch_id);
- } else {
- // disable channel first if not halted (called slave isr)
- xfer->halted_sof_schedule = 1;
- channel_disable(dwc2, channel);
}
} else {
// for control/bulk: retry immediately
@@ -767,13 +787,13 @@ static void handle_rxflvl_irq(uint8_t rhport) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
// Pop control word off FIFO
- const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm;
- const uint8_t ch_id = grxstsp_bm.ep_ch_num;
+ const dwc2_grxstsp_t grxstsp = {.value= dwc2->grxstsp};
+ const uint8_t ch_id = grxstsp.ep_ch_num;
- switch (grxstsp_bm.packet_status) {
+ switch (grxstsp.packet_status) {
case GRXSTS_PKTSTS_RX_DATA: {
// In packet received, pop this entry --> ACK interrupt
- const uint16_t byte_count = grxstsp_bm.byte_count;
+ const uint16_t byte_count = grxstsp.byte_count;
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];
@@ -807,25 +827,26 @@ static void handle_rxflvl_irq(uint8_t rhport) {
// return true if there is still pending data and need more ISR
static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) {
// Use period txsts for both p/np to get request queue space available (1-bit difference, it is small enough)
- volatile dwc2_hptxsts_t* txsts_bm = (volatile dwc2_hptxsts_t*) (is_periodic ? &dwc2->hptxsts : &dwc2->hnptxsts);
+ const dwc2_hptxsts_t txsts = {.value = (is_periodic ? dwc2->hptxsts : dwc2->hnptxsts)};
- const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
+ const uint8_t max_channel = dwc2_channel_count(dwc2);
for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
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) && (channel->hcchar_bm.ep_dir == TUSB_DIR_OUT)) {
+ if (!(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 uint16_t remain_packets = channel->hctsiz_bm.packet_count;
+ const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz};
+ const uint16_t remain_packets = hctsiz.packet_count;
for (uint16_t i = 0; i < remain_packets; i++) {
const uint16_t remain_bytes = edpt->buflen - xfer->fifo_bytes;
- const uint16_t xact_bytes = tu_min16(remain_bytes, channel->hcchar_bm.ep_size);
+ const uint16_t xact_bytes = tu_min16(remain_bytes, hcchar.ep_size);
// skip if there is not enough space in FIFO and RequestQueue.
// Packet's last word written to FIFO will trigger a request queue
- if ((xact_bytes > (txsts_bm->fifo_available << 2)) || (txsts_bm->req_queue_available == 0)) {
+ if ((xact_bytes > (txsts.fifo_available << 2)) || (txsts.req_queue_available == 0)) {
return true;
}
@@ -842,23 +863,26 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h
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];
+ dwc2_channel_split_t hcsplt = {.value = channel->hcsplt};
+ const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz};
bool is_done = false;
- // if (channel->hcsplt_bm.split_en) {
+ // if (hcsplt.split_en) {
// if (edpt->hcchar_bm.ep_num == 1) {
- // TU_LOG1("Frame %u, ch %u: ep %u, hcint 0x%04lX ", dwc2->hfnum_bm.num, ch_id, channel->hcchar_bm.ep_num, hcint);
+ // TU_LOG1("Frame %u, ch %u: ep %u, hcint 0x%04lX ", dwc2->hfnum_bm.num, ch_id, hcsplt.ep_num, hcint);
// print_hcint(hcint);
// }
if (hcint & HCINT_XFER_COMPLETE) {
if (edpt->hcchar_bm.ep_num != 0) {
- edpt->next_pid = channel->hctsiz_bm.pid; // save pid (already toggled)
+ edpt->next_pid = hctsiz.pid; // save pid (already toggled)
}
- const uint16_t remain_packets = channel->hctsiz_bm.packet_count;
- if (channel->hcsplt_bm.split_en && remain_packets && xfer->fifo_bytes == edpt->hcchar_bm.ep_size) {
+ const uint16_t remain_packets = hctsiz.packet_count;
+ if (hcsplt.split_en && remain_packets && xfer->fifo_bytes == edpt->hcchar_bm.ep_size) {
// Split can only complete 1 transaction (up to 1 packet) at a time, schedule more
- channel->hcsplt_bm.split_compl = 0;
+ hcsplt.split_compl = 0;
+ channel->hcsplt = hcsplt.value;
} else {
xfer->result = XFER_RESULT_SUCCESS;
}
@@ -877,43 +901,44 @@ 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_NYET) {
// restart complete split
- channel->hcsplt_bm.split_compl = 1;
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
xfer->halted_nyet = 1;
channel_disable(dwc2, channel);
} else if (hcint & HCINT_NAK) {
- // NAK received, re-enable channel if request queue is available
- if (channel->hcsplt_bm.split_en) {
- channel->hcsplt_bm.split_compl = 0; // restart with start-split
+ // NAK received, disable channel to flush all posted request and try again
+ if (hcsplt.split_en) {
+ hcsplt.split_compl = 0; // restart with start-split
+ channel->hcsplt = hcsplt.value;
}
channel_disable(dwc2, channel);
} else if (hcint & HCINT_ACK) {
xfer->err_count = 0;
- if (channel->hcsplt_bm.split_en) {
- if (!channel->hcsplt_bm.split_compl) {
+ if (hcsplt.split_en) {
+ if (!hcsplt.split_compl) {
// start split is ACK --> do complete split
channel->hcintmsk |= HCINT_NYET;
- channel->hcsplt_bm.split_compl = 1;
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
channel_send_in_token(dwc2, channel);
} else {
// do nothing for complete split with DATA, this will trigger XferComplete and handled there
}
} else {
// ACK with data
- const uint16_t remain_packets = channel->hctsiz_bm.packet_count;
+ const uint16_t remain_packets = hctsiz.packet_count;
if (remain_packets) {
// still more packet to receive, also reset to start split
- channel->hcsplt_bm.split_compl = 0;
+ hcsplt.split_compl = 0;
+ channel->hcsplt = hcsplt.value;
channel_send_in_token(dwc2, channel);
}
}
} else if (hcint & HCINT_HALTED) {
channel->hcintmsk &= ~HCINT_HALTED;
- if (xfer->halted_sof_schedule) {
- // de-allocate channel but does not complete xfer, we schedule it in the SOF interrupt
- channel_dealloc(dwc2, ch_id);
- } else if (xfer->result != XFER_RESULT_INVALID) {
+ if (xfer->result != XFER_RESULT_INVALID) {
is_done = true;
} else if (xfer->err_count == HCD_XFER_ERROR_MAX) {
xfer->result = XFER_RESULT_FAILED;
@@ -933,6 +958,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
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];
+ dwc2_channel_split_t hcsplt = {.value = channel->hcsplt};
bool is_done = false;
if (hcint & HCINT_XFER_COMPLETE) {
@@ -944,9 +970,10 @@ 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 (channel->hcsplt_bm.split_en) {
+ if (hcsplt.split_en) {
// retry complete split
- channel->hcsplt_bm.split_compl = 1;
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
channel->hcchar |= HCCHAR_CHENA;
} else {
edpt->do_ping = 1;
@@ -979,9 +1006,10 @@ 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 (channel->hcsplt_bm.split_en && !channel->hcsplt_bm.split_compl) {
+ if (hcsplt.split_en && !hcsplt.split_compl) {
// start split is ACK --> do complete split
- channel->hcsplt_bm.split_compl = 1;
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
channel->hcchar |= HCCHAR_CHENA;
}
}
@@ -1000,6 +1028,9 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
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];
+ dwc2_channel_char_t hcchar = {.value = channel->hcchar};
+ dwc2_channel_split_t hcsplt = {.value = channel->hcsplt};
+ const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz};
bool is_done = false;
@@ -1007,8 +1038,8 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
if (hcint & HCINT_HALTED) {
if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL | HCINT_BABBLE_ERR)) {
- const uint16_t remain_bytes = (uint16_t) channel->hctsiz_bm.xfer_size;
- const uint16_t remain_packets = channel->hctsiz_bm.packet_count;
+ const uint16_t remain_bytes = (uint16_t) hctsiz.xfer_size;
+ const uint16_t remain_packets = hctsiz.packet_count;
const uint16_t actual_len = edpt->buflen - remain_bytes;
xfer->xferred_bytes += actual_len;
@@ -1018,13 +1049,14 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
xfer->result = XFER_RESULT_STALLED;
} else if (hcint & HCINT_BABBLE_ERR) {
xfer->result = XFER_RESULT_FAILED;
- } else if (channel->hcsplt_bm.split_en && remain_packets && actual_len == edpt->hcchar_bm.ep_size) {
+ } else if (hcsplt.split_en && remain_packets && actual_len == hcchar.ep_size) {
// Split can only complete 1 transaction (up to 1 packet) at a time, schedule more
is_done = false;
edpt->buffer += actual_len;
edpt->buflen -= actual_len;
- channel->hcsplt_bm.split_compl = 0;
+ hcsplt.split_compl = 0;
+ channel->hcsplt = hcsplt.value;
channel_xfer_in_retry(dwc2, ch_id, hcint);
} else {
xfer->result = XFER_RESULT_SUCCESS;
@@ -1039,33 +1071,38 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci
xfer->result = XFER_RESULT_FAILED;
} else {
channel->hcintmsk |= HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR;
- channel->hcsplt_bm.split_compl = 0;
+ hcsplt.split_compl = 0;
+ channel->hcsplt = hcsplt.value;
channel_xfer_in_retry(dwc2, ch_id, hcint);
}
} else if (hcint & HCINT_NYET) {
// Must handle nyet before nak or ack. Could get a nyet at the same time as either of those on a BULK/CONTROL
// OUT that started with a PING. The nyet takes precedence.
- if (channel->hcsplt_bm.split_en) {
+ if (hcsplt.split_en) {
// split not yet mean hub has no data, retry complete split
- channel->hcsplt_bm.split_compl = 1;
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
channel_xfer_in_retry(dwc2, ch_id, hcint);
}
} else if (hcint & HCINT_ACK) {
xfer->err_count = 0;
channel->hcintmsk &= ~HCINT_ACK;
- if (channel->hcsplt_bm.split_en) {
+ if (hcsplt.split_en) {
// start split is ACK --> do complete split
// TODO: for ISO must use xact_pos to plan complete split based on microframe (up to 187.5 bytes/uframe)
- channel->hcsplt_bm.split_compl = 1;
- if (edpt_is_periodic(channel->hcchar_bm.ep_type)) {
- channel->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
+ if (channel_is_periodic(channel->hcchar)) {
+ hcchar.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame
+ channel->hcchar = hcchar.value;
}
channel_send_in_token(dwc2, channel);
}
} else if (hcint & (HCINT_NAK | HCINT_DATATOGGLE_ERR)) {
xfer->err_count = 0;
channel->hcintmsk &= ~(HCINT_NAK | HCINT_DATATOGGLE_ERR);
- channel->hcsplt_bm.split_compl = 0; // restart with start-split
+ hcsplt.split_compl = 0; // restart with start-split
+ channel->hcsplt = hcsplt.value;
channel_xfer_in_retry(dwc2, ch_id, hcint);
} else if (hcint & HCINT_FARME_OVERRUN) {
// retry start-split in next binterval
@@ -1080,6 +1117,8 @@ 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;
@@ -1115,16 +1154,18 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc
}
}
} else if (hcint & HCINT_NYET) {
- if (channel->hcsplt_bm.split_en && channel->hcsplt_bm.split_compl) {
+ if (hcsplt.split_en && hcsplt.split_compl) {
// split not yet mean hub has no data, retry complete split
- channel->hcsplt_bm.split_compl = 1;
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
channel->hcchar |= HCCHAR_CHENA;
}
} else if (hcint & HCINT_ACK) {
xfer->err_count = 0;
- if (channel->hcsplt_bm.split_en && !channel->hcsplt_bm.split_compl) {
+ if (hcsplt.split_en && !hcsplt.split_compl) {
// start split is ACK --> do complete split
- channel->hcsplt_bm.split_compl = 1;
+ hcsplt.split_compl = 1;
+ channel->hcsplt = hcsplt.value;
channel->hcchar |= HCCHAR_CHENA;
}
}
@@ -1140,14 +1181,14 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc
static void handle_channel_irq(uint8_t rhport, bool in_isr) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
const bool is_dma = dma_host_enabled(dwc2);
- const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2);
+ const uint8_t max_channel = dwc2_channel_count(dwc2);
for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) {
if (tu_bit_test(dwc2->haint, ch_id)) {
dwc2_channel_t* channel = &dwc2->channel[ch_id];
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,);
- dwc2_channel_char_t hcchar_bm = channel->hcchar_bm;
+ dwc2_channel_char_t hcchar = {.value = channel->hcchar};
const uint32_t hcint = channel->hcint;
channel->hcint = hcint; // clear interrupt
@@ -1155,7 +1196,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) {
bool is_done = false;
if (is_dma) {
#if CFG_TUH_DWC2_DMA_ENABLE
- if (hcchar_bm.ep_dir == TUSB_DIR_OUT) {
+ if (hcchar.ep_dir == TUSB_DIR_OUT) {
is_done = handle_channel_out_dma(dwc2, ch_id, hcint);
} else {
is_done = handle_channel_in_dma(dwc2, ch_id, hcint);
@@ -1167,7 +1208,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) {
#endif
} else {
#if CFG_TUH_DWC2_SLAVE_ENABLE
- if (hcchar_bm.ep_dir == TUSB_DIR_OUT) {
+ if (hcchar.ep_dir == TUSB_DIR_OUT) {
is_done = handle_channel_out_slave(dwc2, ch_id, hcint);
} else {
is_done = handle_channel_in_slave(dwc2, ch_id, hcint);
@@ -1176,8 +1217,8 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) {
}
if (is_done) {
- const uint8_t ep_addr = tu_edpt_addr(hcchar_bm.ep_num, hcchar_bm.ep_dir);
- hcd_event_xfer_complete(hcchar_bm.dev_addr, ep_addr, xfer->xferred_bytes, xfer->result, in_isr);
+ 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);
}
}
@@ -1197,7 +1238,7 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) {
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 && edpt_is_periodic(edpt->hcchar_bm.ep_type) && edpt->uframe_countdown > 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)) {
@@ -1216,10 +1257,10 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) {
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_bm = dwc2->gusbcfg_bm;
+ const dwc2_gusbcfg_t gusbcfg = {.value = dwc2->gusbcfg};
uint32_t phy_clock;
- if (gusbcfg_bm.phy_sel) {
+ if (gusbcfg.phy_sel) {
phy_clock = 48; // dedicated FS is 48Mhz
if (speed == TUSB_SPEED_LOW) {
hcfg |= HCFG_FSLS_PHYCLK_SEL_6MHZ;
@@ -1227,11 +1268,11 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) {
hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ;
}
} else {
- if (gusbcfg_bm.ulpi_utmi_sel) {
+ if (gusbcfg.ulpi_utmi_sel) {
phy_clock = 60; // ULPI 8-bit is 60Mhz
} else {
// UTMI+ 16-bit is 30Mhz, 8-bit is 60Mhz
- phy_clock = gusbcfg_bm.phy_if16 ? 30 : 60;
+ phy_clock = gusbcfg.phy_if16 ? 30 : 60;
// Enable UTMI+ low power mode 48Mhz external clock if not highspeed
if (speed == TUSB_SPEED_HIGH) {
@@ -1248,9 +1289,9 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) {
uint32_t hfir = dwc2->hfir & ~HFIR_FRIVL_Msk;
if (speed == TUSB_SPEED_HIGH) {
- hfir |= 125*phy_clock;
+ hfir |= 125*phy_clock - 1; // The "- 1" is the correct value. The Synopsys databook was corrected in 3.30a
} else {
- hfir |= 1000*phy_clock;
+ hfir |= 1000*phy_clock - 1;
}
dwc2->hfir = hfir;
@@ -1263,10 +1304,10 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) {
*/
static void handle_hprt_irq(uint8_t rhport, bool in_isr) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
- uint32_t hprt = dwc2->hprt & ~HPRT_W1_MASK;
- const dwc2_hprt_t hprt_bm = dwc2->hprt_bm;
+ const dwc2_hprt_t hprt_bm = {.value = dwc2->hprt};
+ uint32_t hprt = hprt_bm.value & ~HPRT_W1_MASK;
- if (dwc2->hprt & HPRT_CONN_DETECT) {
+ if (hprt_bm.conn_detected) {
// Port Connect Detect
hprt |= HPRT_CONN_DETECT;
@@ -1278,7 +1319,7 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) {
}
}
- if (dwc2->hprt & HPRT_ENABLE_CHANGE) {
+ if (hprt_bm.enable_change) {
// Port enable change
hprt |= HPRT_ENABLE_CHANGE;
diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c
index 1202c4ef4..22ea22e63 100644
--- a/src/portable/template/hcd_template.c
+++ b/src/portable/template/hcd_template.c
@@ -106,6 +106,11 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
// Open an endpoint
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) {
(void) rhport; (void) dev_addr; (void) ep_desc;
+
+ // NOTE: ep_desc is allocated on the stack when called from usbh_edpt_control_open()
+ // You need to copy the data into a local variable who maintains the state of the endpoint and transfer.
+ // Check _hcd_data in hcd_dwc2.c for example.
+
return false;
}
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 29fdcb0d6..98f1a91b5 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -35,7 +35,7 @@
#define TUSB_VERSION_REVISION 0
#define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR * 10000 + TUSB_VERSION_MINOR * 100 + TUSB_VERSION_REVISION)
-#define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
+#define TUSB_VERSION_STRING TU_XSTRING(TUSB_VERSION_MAJOR) "." TU_XSTRING(TUSB_VERSION_MINOR) "." TU_XSTRING(TUSB_VERSION_REVISION)
//--------------------------------------------------------------------+
// Supported MCUs
diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py
index 8b89de66c..f292bca15 100755
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -514,6 +514,63 @@ host_test = [
]
+def test_example(board, f1, example):
+ """
+ Test example firmware
+ :param board: board dict
+ :param f1: flags on
+ :param example: example name
+ :return: 0 if success/skip, 1 if failed
+ """
+ name = board['name']
+ err_count = 0
+
+ f1_str = ""
+ if f1 != "":
+ f1_str = '-f1_' + f1.replace(' ', '_')
+
+ fw_dir = f'{TINYUSB_ROOT}/cmake-build/cmake-build-{name}{f1_str}/{example}'
+ if not os.path.exists(fw_dir):
+ fw_dir = f'{TINYUSB_ROOT}/examples/cmake-build-{name}{f1_str}/{example}'
+ fw_name = f'{fw_dir}/{os.path.basename(example)}'
+ print(f'{name+f1_str:40} {example:30} ... ', end='')
+
+ if not os.path.exists(fw_dir) or not (os.path.exists(f'{fw_name}.elf') or os.path.exists(f'{fw_name}.bin')):
+ print('Skip (no binary)')
+ return 0
+
+ if verbose:
+ print(f'Flashing {fw_name}.elf')
+
+ # flash firmware. It may fail randomly, retry a few times
+ max_rety = 3
+ for i in range(max_rety):
+ ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name)
+ if ret.returncode == 0:
+ try:
+ globals()[f'test_{example.replace("/", "_")}'](board)
+ print('OK')
+ break
+ except Exception as e:
+ if i == max_rety - 1:
+ err_count += 1
+ print(STATUS_FAILED)
+ print(f' {e}')
+ else:
+ print()
+ print(f' Test failed: {e}, retry {i+2}/{max_rety}')
+ time.sleep(1)
+ else:
+ print(f'Flashing failed, retry {i+2}/{max_rety}')
+ time.sleep(1)
+
+ if ret.returncode != 0:
+ err_count += 1
+ print(f'Flash {STATUS_FAILED}')
+
+ return err_count
+
+
def test_board(board):
name = board['name']
flasher = board['flasher']
@@ -537,57 +594,17 @@ def test_board(board):
test_list.remove(skip)
print(f'{name:25} {skip:30} ... Skip')
- # board_test is added last to disable board's usb
- test_list.append('device/board_test')
-
err_count = 0
flags_on_list = [""]
if 'build' in board and 'flags_on' in board['build']:
flags_on_list = board['build']['flags_on']
for f1 in flags_on_list:
- f1_str = ""
- if f1 != "":
- f1_str = '-f1_' + f1.replace(' ', '_')
for test in test_list:
- fw_dir = f'{TINYUSB_ROOT}/cmake-build/cmake-build-{name}{f1_str}/{test}'
- if not os.path.exists(fw_dir):
- fw_dir = f'{TINYUSB_ROOT}/examples/cmake-build-{name}{f1_str}/{test}'
- fw_name = f'{fw_dir}/{os.path.basename(test)}'
- print(f'{name+f1_str:40} {test:30} ... ', end='')
-
- if not os.path.exists(fw_dir) or not (os.path.exists(f'{fw_name}.elf') or os.path.exists(f'{fw_name}.bin')):
- print('Skip (no binary)')
- continue
-
- if verbose:
- print(f'Flashing {fw_name}.elf')
-
- # flash firmware. It may fail randomly, retry a few times
- max_rety = 2
- for i in range(max_rety):
- ret = globals()[f'flash_{flasher["name"].lower()}'](board, fw_name)
- if ret.returncode == 0:
- try:
- globals()[f'test_{test.replace("/", "_")}'](board)
- print('OK')
- break
- except Exception as e:
- if i == max_rety - 1:
- err_count += 1
- print(STATUS_FAILED)
- print(f' {e}')
- else:
- print()
- print(f' Test failed: {e}, retry {i+2}/{max_rety}')
- time.sleep(1)
- else:
- print(f'Flashing failed, retry {i+2}/{max_rety}')
- time.sleep(1)
+ err_count += test_example(board, f1, test)
- if ret.returncode != 0:
- err_count += 1
- print(f'Flash {STATUS_FAILED}')
+ # flash board_test last to disable board's usb
+ test_example(board, flags_on_list[0], 'device/board_test')
return err_count
diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json
index a9460bf9d..8a835e4c0 100644
--- a/test/hil/tinyusb.json
+++ b/test/hil/tinyusb.json
@@ -21,16 +21,18 @@
"name": "espressif_s3_devkitm",
"uid": "84F703C084E4",
"build" : {
- "flags_on": ["", "CFG_TUD_DWC2_DMA_ENABLE"]
+ "flags_on": ["", "CFG_TUD_DWC2_DMA_ENABLE CFG_TUH_DWC2_DMA_ENABLE"]
},
"tests": {
- "only": ["device/cdc_msc_freertos", "device/hid_composite_freertos"]
+ "only": ["device/cdc_msc_freertos", "device/hid_composite_freertos", "host/device_info"],
+ "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2005402"}]
},
"flasher": {
"name": "esptool",
"uid": "3ea619acd1cdeb11a0a0b806e93fd3f1",
"args": "-b 1500000"
- }
+ },
+ "comment": "Use TS3USB30 mux to test both device and host"
},
{
"name": "feather_nrf52840_express",
@@ -125,6 +127,20 @@
}
},
{
+ "name": "raspberry_pi_pico_w",
+ "uid": "E6614C311B764A37",
+ "tests": {
+ "device": false, "host": true, "dual": false,
+ "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2023934"}]
+ },
+ "flasher": {
+ "name": "openocd",
+ "uid": "E6633861A3819D38",
+ "args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\""
+ },
+ "comment": "Test native host"
+ },
+ {
"name": "raspberry_pi_pico2",
"uid": "560AE75E1C7152C9",
"build" : {
diff --git a/tools/build.py b/tools/build.py
index 633d2b582..d28ddd929 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -182,9 +182,14 @@ def build_boards_list(boards, toolchain, build_system, build_flags_on):
def build_family(family, toolchain, build_system, build_flags_on, one_per_family, boards):
+ skip_ci = ['pico_sdk']
+ if os.getenv('GITHUB_ACTIONS') or os.getenv('CIRCLECI'):
+ skip_ci_file = Path(f"hw/bsp/{family}/skip_ci.txt")
+ if skip_ci_file.exists():
+ skip_ci = skip_ci_file.read_text().split()
all_boards = []
for entry in os.scandir(f"hw/bsp/{family}/boards"):
- if entry.is_dir() and entry.name != 'pico_sdk':
+ if entry.is_dir() and not entry.name in skip_ci:
all_boards.append(entry.name)
all_boards.sort()