diff --git a/.github/actions/setup_toolchain/download/action.yml b/.github/actions/setup_toolchain/download/action.yml
index 2af456ef8..813197208 100644
--- a/.github/actions/setup_toolchain/download/action.yml
+++ b/.github/actions/setup_toolchain/download/action.yml
@@ -24,7 +24,13 @@ runs:
run: |
mkdir -p ~/cache/${{ inputs.toolchain }}
wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.tar.gz
- tar -C ~/cache/${{ inputs.toolchain }} -xaf toolchain.tar.gz
+ if [[ ${{ inputs.toolchain }} == rx-gcc ]]; then
+ mv toolchain.tar.gz toolchain.run
+ chmod +x toolchain.run
+ ./toolchain.run -p ~/cache/${{ inputs.toolchain }}/gnurx -y
+ else
+ tar -C ~/cache/${{ inputs.toolchain }} -xaf toolchain.tar.gz
+ fi
shell: bash
- name: Set Toolchain Path
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 78d95fbbc..712c7dd43 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -51,14 +51,15 @@ jobs:
# Build CMake
# ---------------------------------------
cmake:
+ # if: false
needs: set-matrix
uses: ./.github/workflows/build_util.yml
strategy:
fail-fast: false
matrix:
toolchain:
+ # - 'arm-clang' is built by circle-ci
- 'aarch64-gcc'
- # - 'arm-clang' # clang is built by circle-ci
- 'arm-gcc'
- 'msp430-gcc'
- 'riscv-gcc'
@@ -73,18 +74,19 @@ jobs:
# Build Make
# ---------------------------------------
make:
- #if: github.event_name == 'pull_request'
+ # if: false
needs: set-matrix
uses: ./.github/workflows/build_util.yml
strategy:
fail-fast: false
matrix:
toolchain:
+ # 'arm-clang' is built by circle-ci
- 'aarch64-gcc'
- # - 'arm-clang' # clang is built by circle-ci
- 'arm-gcc'
- 'msp430-gcc'
- 'riscv-gcc'
+ - 'rx-gcc'
with:
build-system: 'make'
toolchain: ${{ matrix.toolchain }}
@@ -112,6 +114,7 @@ jobs:
# Build Espressif
# ---------------------------------------
espressif:
+ # if: false
uses: ./.github/workflows/build_util.yml
strategy:
fail-fast: false
@@ -131,6 +134,7 @@ jobs:
# Build IAR on HFP self-hosted
# ---------------------------------------
arm-iar:
+ # if: false
if: github.repository_owner == 'hathach'
needs: set-matrix
runs-on: [self-hosted, Linux, X64, hifiphile]
diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml
deleted file mode 100644
index 3d2cbab28..000000000
--- a/.github/workflows/build_renesas.yml
+++ /dev/null
@@ -1,66 +0,0 @@
-name: Build Renesas
-
-on:
- workflow_dispatch:
- push:
- paths:
- - 'src/**'
- - 'examples/**'
- - 'lib/**'
- - 'hw/**'
- - 'tools/get_deps.py'
- - '.github/workflows/build_renesas.yml'
- pull_request:
- branches: [ master ]
- paths:
- - 'src/**'
- - 'examples/**'
- - 'lib/**'
- - 'hw/**'
- - 'tools/get_deps.py'
- - '.github/workflows/build_renesas.yml'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- build-rx:
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- family:
- # Alphabetical order
- - 'rx'
- steps:
- - name: Checkout TinyUSB
- uses: actions/checkout@v4
-
- - name: Set Toolchain URL
- run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run
-
- - name: Cache Toolchain
- uses: actions/cache@v4
- id: cache-toolchain
- with:
- path: ~/cache/
- key: ${{ runner.os }}-21-03-30-${{ env.TOOLCHAIN_URL }}
-
- - name: Install Toolchain
- if: steps.cache-toolchain.outputs.cache-hit != 'true'
- run: |
- mkdir -p ~/cache/toolchain/gnurx
- wget --progress=dot:mega $TOOLCHAIN_URL -O toolchain.run
- chmod +x toolchain.run
- ./toolchain.run -p ~/cache/toolchain/gnurx -y
-
- - name: Set Toolchain Path
- run: echo >> $GITHUB_PATH `echo ~/cache/toolchain/*/bin`
-
- - name: Get Dependencies
- run: |
- python3 tools/get_deps.py ${{ matrix.family }}
-
- - name: Build
- run: python3 tools/build.py -s make ${{ matrix.family }}
diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py
index c6f4e8fe2..2a00e5413 100644
--- a/.github/workflows/ci_set_matrix.py
+++ b/.github/workflows/ci_set_matrix.py
@@ -7,14 +7,16 @@ toolchain_list = {
"arm-iar": "",
"arm-gcc": "",
"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"
+ "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": "http://gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run",
}
# family: [supported toolchain]
family_list = {
"broadcom_32bit": ["arm-gcc"],
"broadcom_64bit": ["aarch64-gcc"],
- "ch32v20x ch32v307 fomu gd32vf103": ["riscv-gcc"],
+ "ch32v10x ch32v20x ch32v307 fomu gd32vf103": ["riscv-gcc"],
+ "da1469x": ["arm-gcc"],
"imxrt": ["arm-gcc", "arm-clang"],
"kinetis_k kinetis_kl kinetis_k32l2": ["arm-gcc", "arm-clang"],
"lpc11 lpc13 lpc15": ["arm-gcc", "arm-clang"],
@@ -27,6 +29,7 @@ family_list = {
"nrf": ["arm-gcc", "arm-clang"],
"ra": ["arm-gcc"],
"rp2040": ["arm-gcc"],
+ "rx": ["rx-gcc"],
"samd11 samd21 saml2x": ["arm-gcc", "arm-clang"],
"samd5x_e5x samg": ["arm-gcc", "arm-clang"],
"stm32f0 stm32f1 stm32f2 stm32f3": ["arm-gcc", "arm-clang", "arm-iar"],
@@ -34,7 +37,7 @@ family_list = {
"stm32f7": ["arm-gcc", "arm-clang", "arm-iar"],
"stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang", "arm-iar"],
"stm32h7": ["arm-gcc", "arm-clang", "arm-iar"],
- "stm32l4 stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"],
+ "stm32l0 stm32l4 stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"],
"xmc4000": ["arm-gcc"],
}
diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml
index 39a9060a2..51227d408 100644
--- a/.github/workflows/hil_test.yml
+++ b/.github/workflows/hil_test.yml
@@ -17,6 +17,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
+env:
+ HIL_JSON: test/hil/rpi.json
+
jobs:
# ---------------------------------------
# Build Non Espressif
@@ -36,7 +39,7 @@ jobs:
sudo apt install -y jq
# Non-Espresif boards
- BOARDS_LIST=$(jq -r '.boards[] | select(.flasher != "esptool") | "-b " + .name' test/hil/pi4.json | tr '\n' ' ')
+ BOARDS_LIST=$(jq -r '.boards[] | select(.flasher != "esptool") | "-b " + .name' ${{ env.HIL_JSON }} | tr '\n' ' ')
echo "BOARDS_LIST=$BOARDS_LIST"
echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_ENV
echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_OUTPUT
@@ -57,7 +60,7 @@ jobs:
- name: Upload Artifacts for Hardware Testing
uses: actions/upload-artifact@v4
with:
- name: hil_pi4
+ name: hil_rpi
path: |
cmake-build/cmake-build-*/*/*/*.elf
cmake-build/cmake-build-*/*/*/*.bin
@@ -78,7 +81,7 @@ jobs:
run: |
sudo apt install -y jq
# Espressif boards
- BOARDS_LIST=$(jq -r '.boards[] | select(.flasher == "esptool") | "-b " + .name' test/hil/pi4.json | tr '\n' ' ')
+ BOARDS_LIST=$(jq -r '.boards[] | select(.flasher == "esptool") | "-b " + .name' ${{ env.HIL_JSON }} | tr '\n' ' ')
echo "BOARDS_LIST=$BOARDS_LIST"
echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_ENV
echo "BOARDS_LIST=$BOARDS_LIST" >> $GITHUB_OUTPUT
@@ -102,7 +105,7 @@ jobs:
- name: Upload Artifacts for Hardware Testing
uses: actions/upload-artifact@v4
with:
- name: hil_pi4_esp
+ name: hil_rpi_esp
path: |
cmake-build/cmake-build-*/*/*/*.bin
cmake-build/cmake-build-*/*/*/bootloader/bootloader.bin
@@ -112,14 +115,14 @@ jobs:
# ---------------------------------------
# Hardware in the loop (HIL)
- # Current self-hosted instance is running on an RPI4. For attached hardware checkout test/hil/pi4.json
+ # self-hosted running on an RPI. For attached hardware checkout test/hil/rpi.json
# ---------------------------------------
- hil-pi4:
+ hil-rpi:
if: github.repository_owner == 'hathach'
needs:
- build
- build-esp
- runs-on: [self-hosted, rp2040, nrf52840, esp32s3, hardware-in-the-loop]
+ runs-on: [self-hosted, ARM64, rpi, hardware-in-the-loop]
env:
BOARDS_LIST: "${{ needs.build.outputs.BOARDS_LIST }} ${{ needs.build-esp.outputs.BOARDS_LIST }}"
steps:
@@ -129,12 +132,12 @@ jobs:
rm -rf "${{ github.workspace }}"
mkdir -p "${{ github.workspace }}"
- # USB bus on rpi4 is not stable, reset it before testing
- - name: Reset USB bus
- run: |
- # lsusb -t
- # reset VIA Labs 2.0 hub
- sudo usbreset 001/002
+ # USB bus on rpi is not stable, reset it before testing
+# - name: Reset USB bus
+# run: |
+# # reset VIA Labs 2.0 hub
+# sudo usbreset 001/002
+# lsusb -t
- name: Checkout TinyUSB
uses: actions/checkout@v4
@@ -144,13 +147,13 @@ jobs:
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
- name: hil_pi4
+ name: hil_rpi
path: cmake-build
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
- name: hil_pi4_esp
+ name: hil_rpi_esp
path: cmake-build
- name: Test on actual hardware
@@ -159,4 +162,4 @@ jobs:
echo "::group::{cmake-build contents}"
tree cmake-build
echo "::endgroup::"
- python3 test/hil/hil_test.py $BOARDS_LIST pi4.json
+ python3 test/hil/hil_test.py $BOARDS_LIST ${{ env.HIL_JSON }}
diff --git a/.gitignore b/.gitignore
index 7a37d65dc..f2150a26f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,62 +31,4 @@ cov-int
__pycache__
cmake-build-*
sdkconfig
-
-# submodules
-hw/mcu/allwinner
-hw/mcu/bridgetek/ft9xx/ft90x-sdk
-hw/mcu/broadcom
-hw/mcu/gd/nuclei-sdk
-hw/mcu/infineon/mtb-xmclib-cat3
-hw/mcu/microchip
-hw/mcu/mindmotion/mm32sdk
-hw/mcu/nordic/nrfx
-hw/mcu/nuvoton
-hw/mcu/nxp/lpcopen
-hw/mcu/nxp/mcux-sdk
-hw/mcu/nxp/nxp_sdk
-hw/mcu/raspberry_pi/Pico-PIO-USB
-hw/mcu/renesas/rx
-hw/mcu/silabs/cmsis-dfp-efm32gg12b
-hw/mcu/sony/cxd56/spresense-exported-sdk
-hw/mcu/st/cmsis_device_f0
-hw/mcu/st/cmsis_device_f1
-hw/mcu/st/cmsis_device_f2
-hw/mcu/st/cmsis_device_f3
-hw/mcu/st/cmsis_device_f4
-hw/mcu/st/cmsis_device_f7
-hw/mcu/st/cmsis_device_g0
-hw/mcu/st/cmsis_device_g4
-hw/mcu/st/cmsis_device_h5
-hw/mcu/st/cmsis_device_h7
-hw/mcu/st/cmsis_device_l0
-hw/mcu/st/cmsis_device_l1
-hw/mcu/st/cmsis_device_l4
-hw/mcu/st/cmsis_device_l5
-hw/mcu/st/cmsis_device_u5
-hw/mcu/st/cmsis_device_wb
-hw/mcu/st/stm32f0xx_hal_driver
-hw/mcu/st/stm32f1xx_hal_driver
-hw/mcu/st/stm32f2xx_hal_driver
-hw/mcu/st/stm32f3xx_hal_driver
-hw/mcu/st/stm32f4xx_hal_driver
-hw/mcu/st/stm32f7xx_hal_driver
-hw/mcu/st/stm32g0xx_hal_driver
-hw/mcu/st/stm32g4xx_hal_driver
-hw/mcu/st/stm32h5xx_hal_driver
-hw/mcu/st/stm32h7xx_hal_driver
-hw/mcu/st/stm32l0xx_hal_driver
-hw/mcu/st/stm32l1xx_hal_driver
-hw/mcu/st/stm32l4xx_hal_driver
-hw/mcu/st/stm32l5xx_hal_driver
-hw/mcu/st/stm32u5xx_hal_driver
-hw/mcu/st/stm32wbxx_hal_driver
-hw/mcu/ti
-hw/mcu/wch/ch32v20x
-hw/mcu/wch/ch32v307
-hw/mcu/wch/ch32f20x
-lib/CMSIS_5
-lib/FreeRTOS-Kernel
-lib/lwip
-lib/sct_neopixel
-tools/uf2
+.PVS-Studio
diff --git a/.idea/cmake.xml b/.idea/cmake.xml
index 24d4eafe9..67e793016 100644
--- a/.idea/cmake.xml
+++ b/.idea/cmake.xml
@@ -3,6 +3,7 @@
+
@@ -65,14 +66,14 @@
-
-
+
+
-
+
-
+
@@ -105,17 +106,18 @@
-
-
-
-
-
+
+
+
+
+
+
@@ -131,10 +133,12 @@
-
-
+
+
+
+
\ No newline at end of file
diff --git a/README.rst b/README.rst
index b5f9fc149..1ae8c5375 100644
--- a/README.rst
+++ b/README.rst
@@ -151,8 +151,9 @@ Following CPUs are supported, check out `Supported Devices`_ for comprehensive l
+--------------+------------------------------------------------------------+
| Sony | CXD56 |
+--------------+------------------------------------------------------------+
-| ST STM32 | F0, F1, F2, F3, F4, F7, H5, H7, G0, G4, L0, L1, L4, L4+, |
-| | U5, WB |
+| ST STM32 | F0, F1, F2, F3, F4, F7, G0, G4, H5, H7, |
+| | |
+| | L0, L1, L4, L4+, L5, U5, WB |
+--------------+------------------------------------------------------------+
| TI | MSP430, MSP432E4, TM4C123 |
+--------------+------------------------------------------------------------+
diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst
index 3ca203e88..edb6b69ca 100644
--- a/docs/reference/supported.rst
+++ b/docs/reference/supported.rst
@@ -104,21 +104,33 @@ Supported MCUs
| +-----------------------+--------+------+-----------+-------------------+--------------+
| | F7 | ✔ | | ✔ | dwc2 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | H7 | ✔ | | ✔ | dwc2 | |
+| | G0 | ✔ | | ✖ | stm32_fsdev | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | L0, L1 | ✔ | ✖ | ✖ | stm32_fsdev | |
+| | H5 | ✔ | | ✖ | stm32_fsdev | |
+| +-----------------------+--------+------+-----------+-------------------+--------------+
+| | H7 | ✔ | | ✔ | dwc2 | |
+| +-----------------------+--------+------+-----------+-------------------+--------------+
+| | L0 | ✔ | ✖ | ✖ | stm32_fsdev | |
+| +-----------------------+--------+------+-----------+-------------------+--------------+
+| | L1 | ✔ | ✖ | ✖ | stm32_fsdev | |
| +----+------------------+--------+------+-----------+-------------------+--------------+
| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | |
| | +------------------+--------+------+-----------+-------------------+--------------+
-| | | 4x5, 4x6 | ✔ | | | dwc2 | |
+| | | 4x5, 4x6 | ✔ | | ✖ | dwc2 | |
| +----+------------------+--------+------+-----------+-------------------+--------------+
-| | L4+ | ✔ | | | dwc2 | |
+| | L4+ | ✔ | | ✖ | dwc2 | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | U5 | ✔ | | ✔ | dwc2 | |
-| +-----------------------+--------+------+-----------+-------------------+--------------+
-| | WBx5 | ✔ | | | stm32_fsdev | |
+| | L5 | ✔ | ✖ | ✖ | stm32_fsdev | |
+| +----+------------------+--------+------+-----------+-------------------+--------------+
+| | U5 | 535, 545 | ✔ | | ✖ | stm32_fsdev | |
+| | +------------------+--------+------+-----------+-------------------+--------------+
+| | | 575, 585 | ✔ | | ✖ | dwc2 | |
+| | +------------------+--------+------+-----------+-------------------+--------------+
+| | | 59x,5Ax,5Fx,5Gx | ✔ | | ✔ | dwc2 | |
+| +----+------------------+--------+------+-----------+-------------------+--------------+
+| | WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | |
| +-----------------------+--------+------+-----------+-------------------+--------------+
@@ -129,7 +141,9 @@ Supported MCUs
| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
| WCH | CH32F20x | ✔ | | ✔ | ch32f205 | |
+| +-----------------------+--------+------+-----------+-------------------+--------------+
| | CH32V20x | ✔ | | ✖ | ch32v20x | |
+| +-----------------------+--------+------+-----------+-------------------+--------------+
| | CH32V307 | ✔ | | ✔ | ch32v307 | |
+--------------+-----------------------+--------+------+-----------+-------------------+--------------+
@@ -137,11 +151,12 @@ Supported MCUs
Table Legend
------------
-= ===================
-✔ Supported
-⚠ WIP/partial support
-✖ Not supported
-= ===================
+========= =========================
+✔ Supported
+⚠ Partial support
+✖ Not supported by hardware
+\[empty\] Unknown
+========= =========================
Supported Boards
================
diff --git a/examples/build_system/cmake/cpu/cortex-m33-nodsp.cmake b/examples/build_system/cmake/cpu/cortex-m33-nodsp.cmake
new file mode 100644
index 000000000..b3cd743fd
--- /dev/null
+++ b/examples/build_system/cmake/cpu/cortex-m33-nodsp.cmake
@@ -0,0 +1,25 @@
+if (TOOLCHAIN STREQUAL "gcc")
+ set(TOOLCHAIN_COMMON_FLAGS
+ -mthumb
+ -mcpu=cortex-m33+nodsp
+ -mfloat-abi=hard
+ -mfpu=fpv5-sp-d16
+ )
+ set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "clang")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --target=arm-none-eabi
+ -mcpu=cortex-m33+nodsp
+ -mfpu=fpv5-sp-d16
+ )
+ set(FREERTOS_PORT GCC_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+elseif (TOOLCHAIN STREQUAL "iar")
+ set(TOOLCHAIN_COMMON_FLAGS
+ --cpu cortex-m33+nodsp
+ --fpu VFPv5-SP
+ )
+ set(FREERTOS_PORT IAR_ARM_CM33_NTZ_NONSECURE CACHE INTERNAL "")
+
+endif ()
diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk
index a78f4130d..1500a51e0 100644
--- a/examples/build_system/make/make.mk
+++ b/examples/build_system/make/make.mk
@@ -109,6 +109,10 @@ INC += \
BOARD_UPPER = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$(subst -,_,$(BOARD))))))))))))))))))))))))))))
CFLAGS += -DBOARD_$(BOARD_UPPER)
+ifdef CFLAGS_CLI
+ CFLAGS += $(CFLAGS_CLI)
+endif
+
# use max3421 as host controller
ifeq (${MAX3421_HOST},1)
SRC_C += src/portable/analog/max3421/hcd_max3421.c
diff --git a/examples/build_system/make/rules.mk b/examples/build_system/make/rules.mk
index 102c6db0c..f322dbae6 100644
--- a/examples/build_system/make/rules.mk
+++ b/examples/build_system/make/rules.mk
@@ -145,6 +145,12 @@ OPENOCD_WCH_OPTION ?=
flash-openocd-wch: $(BUILD)/$(PROJECT).elf
$(OPENOCD_WCH) $(OPENOCD_WCH_OPTION) -c init -c halt -c "flash write_image $<" -c reset -c exit
+# --------------- wlink-rs -----------------
+# flash with https://github.com/ch32-rs/wlink
+WLINK_RS ?= wlink
+flash-wlink-rs: $(BUILD)/$(PROJECT).elf
+ $(WLINK_RS) flash $<
+
# --------------- dfu-util -----------------
DFU_UTIL_OPTION ?= -a 0
flash-dfu-util: $(BUILD)/$(PROJECT).bin
diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt
index 4769af009..012ca4e74 100644
--- a/examples/device/audio_4_channel_mic_freertos/skip.txt
+++ b/examples/device/audio_4_channel_mic_freertos/skip.txt
@@ -1,3 +1,4 @@
+mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56
diff --git a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
index 6cc7a6577..869500ad2 100644
--- a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
@@ -67,6 +67,7 @@
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
+#define configRUN_FREERTOS_SECURE_ONLY 1
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt
index 6aaa27661..c13667f56 100644
--- a/examples/device/audio_test_freertos/skip.txt
+++ b/examples/device/audio_test_freertos/skip.txt
@@ -1,3 +1,4 @@
+mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56
diff --git a/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
index 6cc7a6577..869500ad2 100644
--- a/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
@@ -67,6 +67,7 @@
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
+#define configRUN_FREERTOS_SECURE_ONLY 1
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c
index 1167a5d50..ef12186f2 100644
--- a/examples/device/cdc_dual_ports/src/main.c
+++ b/examples/device/cdc_dual_ports/src/main.c
@@ -119,6 +119,26 @@ static void cdc_task(void) {
}
}
+// Invoked when cdc when line state changed e.g connected/disconnected
+// Use to reset to DFU when disconnect with 1200 bps
+void tud_cdc_line_state_cb(uint8_t instance, bool dtr, bool rts) {
+ (void)rts;
+
+ // DTR = false is counted as disconnected
+ if (!dtr) {
+ // touch1200 only with first CDC instance (Serial)
+ if (instance == 0) {
+ cdc_line_coding_t coding;
+ tud_cdc_get_line_coding(&coding);
+ if (coding.bit_rate == 1200) {
+ if (board_reset_to_bootloader) {
+ board_reset_to_bootloader();
+ }
+ }
+ }
+ }
+}
+
//--------------------------------------------------------------------+
// BLINKING TASK
//--------------------------------------------------------------------+
diff --git a/examples/device/cdc_msc/skip.txt b/examples/device/cdc_msc/skip.txt
index 833fd072c..b6252e405 100644
--- a/examples/device/cdc_msc/skip.txt
+++ b/examples/device/cdc_msc/skip.txt
@@ -1,2 +1,3 @@
mcu:SAMD11
family:espressif
+board:ch32v203g_r0_1v0
diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt
index 457ddb760..75a79aff4 100644
--- a/examples/device/cdc_msc_freertos/skip.txt
+++ b/examples/device/cdc_msc_freertos/skip.txt
@@ -1,3 +1,4 @@
+mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56
diff --git a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
index 6cc7a6577..869500ad2 100644
--- a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
@@ -67,6 +67,7 @@
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
+#define configRUN_FREERTOS_SECURE_ONLY 1
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c
index c8a04bb74..d2f8628f1 100644
--- a/examples/device/cdc_msc_freertos/src/msc_disk.c
+++ b/examples/device/cdc_msc_freertos/src/msc_disk.c
@@ -28,6 +28,9 @@
#if CFG_TUD_MSC
+// whether host does safe-eject
+static bool ejected = false;
+
// Some MCU doesn't have enough 8KB SRAM to store the whole disk
// We will use Flash as read-only disk with board that has
// CFG_EXAMPLE_MSC_READONLY defined
@@ -137,7 +140,14 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun)
{
(void) lun;
- return true; // RAM disk is always ready
+ // RAM disk is ready until ejected
+ if (ejected) {
+ // Additional Sense 3A-00 is NOT_FOUND
+ tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
+ return false;
+ }
+
+ return true;
}
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
@@ -166,6 +176,7 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo
}else
{
// unload disk storage
+ ejected = true;
}
}
@@ -187,6 +198,17 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff
return (int32_t) bufsize;
}
+bool tud_msc_is_writable_cb (uint8_t lun)
+{
+ (void) lun;
+
+#ifdef CFG_EXAMPLE_MSC_READONLY
+ return false;
+#else
+ return true;
+#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)
diff --git a/examples/device/dynamic_configuration/skip.txt b/examples/device/dynamic_configuration/skip.txt
index 833fd072c..b6252e405 100644
--- a/examples/device/dynamic_configuration/skip.txt
+++ b/examples/device/dynamic_configuration/skip.txt
@@ -1,2 +1,3 @@
mcu:SAMD11
family:espressif
+board:ch32v203g_r0_1v0
diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt
index 6aaa27661..c13667f56 100644
--- a/examples/device/hid_composite_freertos/skip.txt
+++ b/examples/device/hid_composite_freertos/skip.txt
@@ -1,3 +1,4 @@
+mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56
diff --git a/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
index 6cc7a6577..869500ad2 100644
--- a/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
@@ -67,6 +67,7 @@
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
+#define configRUN_FREERTOS_SECURE_ONLY 1
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
diff --git a/examples/device/net_lwip_webserver/CMakeLists.txt b/examples/device/net_lwip_webserver/CMakeLists.txt
index c39fd32c5..13923b583 100644
--- a/examples/device/net_lwip_webserver/CMakeLists.txt
+++ b/examples/device/net_lwip_webserver/CMakeLists.txt
@@ -5,7 +5,14 @@ include(${CMAKE_CURRENT_LIST_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. -)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+# Prefer the tinyusb lwip
set(LWIP ${TOP}/lib/lwip)
+
+# If we can't find one from tinyusb then check cmake var before giving up
+if (NOT EXISTS ${LWIP}/src)
+ set(LWIP ${TINYUSB_LWIP_PATH})
+endif()
+
if (NOT EXISTS ${LWIP}/src)
family_example_missing_dependency(${PROJECT} "lib/lwip")
return()
diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt
index 51af58667..85c450e82 100644
--- a/examples/device/net_lwip_webserver/skip.txt
+++ b/examples/device/net_lwip_webserver/skip.txt
@@ -1,3 +1,4 @@
+mcu:CH32V103
mcu:CH32V20X
mcu:LPC11UXX
mcu:LPC13XX
diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt
index 714cabeec..cb0c7d2e6 100644
--- a/examples/device/video_capture/skip.txt
+++ b/examples/device/video_capture/skip.txt
@@ -1,3 +1,4 @@
+mcu:CH32V103
mcu:CH32V20X
mcu:MSP430x5xx
mcu:NUC121
diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt
index 1786297f9..af3b0de04 100644
--- a/examples/device/video_capture_2ch/skip.txt
+++ b/examples/device/video_capture_2ch/skip.txt
@@ -2,6 +2,7 @@ mcu:MSP430x5xx
mcu:NUC121
mcu:SAMD11
mcu:GD32VF103
+mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:STM32L0
diff --git a/examples/dual/CMakeLists.txt b/examples/dual/CMakeLists.txt
index 15081cf26..f11074e93 100644
--- a/examples/dual/CMakeLists.txt
+++ b/examples/dual/CMakeLists.txt
@@ -10,4 +10,5 @@ if (FAMILY STREQUAL "rp2040" AND NOT TARGET tinyusb_pico_pio_usb)
else ()
# family_add_subdirectory will filter what to actually add based on selected FAMILY
family_add_subdirectory(host_hid_to_device_cdc)
+ family_add_subdirectory(host_info_to_device_cdc)
endif ()
diff --git a/examples/dual/host_hid_to_device_cdc/src/main.c b/examples/dual/host_hid_to_device_cdc/src/main.c
index 96a2beff5..0b4165e38 100644
--- a/examples/dual/host_hid_to_device_cdc/src/main.c
+++ b/examples/dual/host_hid_to_device_cdc/src/main.c
@@ -55,14 +55,14 @@ const uint8_t colemak[128] = {
};
#endif
-static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
+static uint8_t const keycode2ascii[128][2] = {HID_KEYCODE_TO_ASCII};
/* Blink pattern
* - 250 ms : device not mounted
* - 1000 ms : device mounted
* - 2500 ms : device is suspended
*/
-enum {
+enum {
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
@@ -73,8 +73,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
void led_blinking_task(void);
/*------------- MAIN -------------*/
-int main(void)
-{
+int main(void) {
board_init();
printf("TinyUSB Host HID <-> Device CDC Example\r\n");
@@ -87,8 +86,7 @@ int main(void)
board_init_after_tusb();
}
- while (1)
- {
+ while (1) {
tud_task(); // tinyusb device task
tuh_task(); // tinyusb host task
led_blinking_task();
@@ -102,35 +100,30 @@ int main(void)
//--------------------------------------------------------------------+
// Invoked when device is mounted
-void tud_mount_cb(void)
-{
+void tud_mount_cb(void) {
blink_interval_ms = BLINK_MOUNTED;
}
// Invoked when device is unmounted
-void tud_umount_cb(void)
-{
+void tud_umount_cb(void) {
blink_interval_ms = BLINK_NOT_MOUNTED;
}
// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
-void tud_suspend_cb(bool remote_wakeup_en)
-{
+void tud_suspend_cb(bool remote_wakeup_en) {
(void) remote_wakeup_en;
blink_interval_ms = BLINK_SUSPENDED;
}
// Invoked when usb bus is resumed
-void tud_resume_cb(void)
-{
+void tud_resume_cb(void) {
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
// Invoked when CDC interface received data from host
-void tud_cdc_rx_cb(uint8_t itf)
-{
+void tud_cdc_rx_cb(uint8_t itf) {
(void) itf;
char buf[64];
@@ -149,38 +142,36 @@ void tud_cdc_rx_cb(uint8_t itf)
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
-void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
-{
- (void)desc_report;
- (void)desc_len;
+void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) {
+ (void) desc_report;
+ (void) desc_len;
// Interface protocol (hid_interface_protocol_enum_t)
- const char* protocol_str[] = { "None", "Keyboard", "Mouse" };
+ const char* protocol_str[] = {"None", "Keyboard", "Mouse"};
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
char tempbuf[256];
- int count = sprintf(tempbuf, "[%04x:%04x][%u] HID Interface%u, Protocol = %s\r\n", vid, pid, dev_addr, instance, protocol_str[itf_protocol]);
+ int count = sprintf(
+ tempbuf, "[%04x:%04x][%u] HID Interface%u, Protocol = %s\r\n", vid, pid, dev_addr, instance,
+ protocol_str[itf_protocol]);
tud_cdc_write(tempbuf, (uint32_t) count);
tud_cdc_write_flush();
// Receive report from boot keyboard & mouse only
// tuh_hid_report_received_cb() will be invoked when report is available
- if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD || itf_protocol == HID_ITF_PROTOCOL_MOUSE)
- {
- if ( !tuh_hid_receive_report(dev_addr, instance) )
- {
+ if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD || itf_protocol == HID_ITF_PROTOCOL_MOUSE) {
+ if (!tuh_hid_receive_report(dev_addr, instance)) {
tud_cdc_write_str("Error: cannot request report\r\n");
}
}
}
// Invoked when device with hid interface is un-mounted
-void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
-{
+void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
char tempbuf[256];
int count = sprintf(tempbuf, "[%u] HID Interface%u is unmounted\r\n", dev_addr, instance);
tud_cdc_write(tempbuf, (uint32_t) count);
@@ -188,11 +179,9 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
}
// look up new key in previous keys
-static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode)
-{
- for(uint8_t i=0; i<6; i++)
- {
- if (report->keycode[i] == keycode) return true;
+static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) {
+ for (uint8_t i = 0; i < 6; i++) {
+ if (report->keycode[i] == keycode) return true;
}
return false;
@@ -200,22 +189,17 @@ static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8
// convert hid keycode to ascii and print via usb device CDC (ignore non-printable)
-static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *report)
-{
+static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const* report) {
(void) dev_addr;
- static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released
+ static hid_keyboard_report_t prev_report = {0, 0, {0}}; // previous report to check key released
bool flush = false;
- for(uint8_t i=0; i<6; i++)
- {
+ for (uint8_t i = 0; i < 6; i++) {
uint8_t keycode = report->keycode[i];
- if ( keycode )
- {
- if ( find_key_in_report(&prev_report, keycode) )
- {
+ if (keycode) {
+ if (find_key_in_report(&prev_report, keycode)) {
// exist in previous report means the current key is holding
- }else
- {
+ } else {
// not existed in previous report means the current key is pressed
// remap the key code for Colemak layout
@@ -227,8 +211,7 @@ static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *re
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
uint8_t ch = keycode2ascii[keycode][is_shift ? 1 : 0];
- if (ch)
- {
+ if (ch) {
if (ch == '\n') tud_cdc_write("\r", 1);
tud_cdc_write(&ch, 1);
flush = true;
@@ -244,13 +227,12 @@ static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const *re
}
// send mouse report to usb device CDC
-static void process_mouse_report(uint8_t dev_addr, hid_mouse_report_t const * report)
-{
+static void process_mouse_report(uint8_t dev_addr, hid_mouse_report_t const* report) {
//------------- button state -------------//
//uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
- char l = report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-';
+ char l = report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-';
char m = report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-';
- char r = report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-';
+ char r = report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-';
char tempbuf[32];
int count = sprintf(tempbuf, "[%u] %c%c%c %d %d %d\r\n", dev_addr, l, m, r, report->x, report->y, report->wheel);
@@ -260,27 +242,25 @@ static void process_mouse_report(uint8_t dev_addr, hid_mouse_report_t const * re
}
// Invoked when received report from device via interrupt endpoint
-void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
-{
+void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
(void) len;
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
- switch(itf_protocol)
- {
+ switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
- process_kbd_report(dev_addr, (hid_keyboard_report_t const*) report );
- break;
+ process_kbd_report(dev_addr, (hid_keyboard_report_t const*) report);
+ break;
case HID_ITF_PROTOCOL_MOUSE:
- process_mouse_report(dev_addr, (hid_mouse_report_t const*) report );
- break;
+ process_mouse_report(dev_addr, (hid_mouse_report_t const*) report);
+ break;
- default: break;
+ default:
+ break;
}
// continue to request to receive report
- if ( !tuh_hid_receive_report(dev_addr, instance) )
- {
+ if (!tuh_hid_receive_report(dev_addr, instance)) {
tud_cdc_write_str("Error: cannot request report\r\n");
}
}
@@ -288,13 +268,12 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
//--------------------------------------------------------------------+
// Blinking Task
//--------------------------------------------------------------------+
-void led_blinking_task(void)
-{
+void led_blinking_task(void) {
static uint32_t start_ms = 0;
static bool led_state = false;
// Blink every interval ms
- if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
+ if (board_millis() - start_ms < blink_interval_ms) return; // not enough time
start_ms += blink_interval_ms;
board_led_write(led_state);
diff --git a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
index 8133ed418..2843e0b83 100644
--- a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
+++ b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
@@ -23,8 +23,8 @@
*
*/
-#ifndef _TUSB_CONFIG_H_
-#define _TUSB_CONFIG_H_
+#ifndef TUSB_CONFIG_H_
+#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
@@ -144,4 +144,4 @@
}
#endif
-#endif /* _TUSB_CONFIG_H_ */
+#endif
diff --git a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
index 293620042..9d57737fb 100644
--- a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
+++ b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
@@ -42,44 +42,41 @@
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
-tusb_desc_device_t const desc_device =
-{
- .bLength = sizeof(tusb_desc_device_t),
- .bDescriptorType = TUSB_DESC_DEVICE,
- .bcdUSB = USB_BCD,
+tusb_desc_device_t const desc_device = {
+ .bLength = sizeof(tusb_desc_device_t),
+ .bDescriptorType = TUSB_DESC_DEVICE,
+ .bcdUSB = USB_BCD,
- // Use Interface Association Descriptor (IAD) for CDC
- // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
- .bDeviceClass = TUSB_CLASS_MISC,
- .bDeviceSubClass = MISC_SUBCLASS_COMMON,
- .bDeviceProtocol = MISC_PROTOCOL_IAD,
+ // Use Interface Association Descriptor (IAD) for CDC
+ // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
- .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
- .idVendor = USB_VID,
- .idProduct = USB_PID,
- .bcdDevice = 0x0100,
+ .idVendor = USB_VID,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
- .iManufacturer = 0x01,
- .iProduct = 0x02,
- .iSerialNumber = 0x03,
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
- .bNumConfigurations = 0x01
+ .bNumConfigurations = 0x01
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
-uint8_t const * tud_descriptor_device_cb(void)
-{
- return (uint8_t const *) &desc_device;
+uint8_t const* tud_descriptor_device_cb(void) {
+ return (uint8_t const*) &desc_device;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
-enum
-{
+enum {
ITF_NUM_CDC = 0,
ITF_NUM_CDC_DATA,
ITF_NUM_TOTAL
@@ -92,7 +89,7 @@ enum
#define EPNUM_CDC_OUT 0x02
#define EPNUM_CDC_IN 0x82
-#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
+#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
// SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_NOTIF 0x81
@@ -109,7 +106,7 @@ enum
#define EPNUM_CDC_IN 0x81
#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
- // FT9XX doesn't support a same endpoint number with different direction IN and OUT
+// FT9XX doesn't support a same endpoint number with different direction IN and OUT
// e.g EP1 OUT & EP1 IN cannot exist together
#define EPNUM_CDC_NOTIF 0x81
#define EPNUM_CDC_OUT 0x02
@@ -125,21 +122,19 @@ enum
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
// full speed configuration
-uint8_t const desc_fs_configuration[] =
-{
- // Config number, interface count, string index, total length, attribute, power in mA
- TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+uint8_t const desc_fs_configuration[] = {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
- // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
- TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
};
#if TUD_OPT_HIGH_SPEED
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
// high speed configuration
-uint8_t const desc_hs_configuration[] =
-{
+uint8_t const desc_hs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
@@ -151,8 +146,7 @@ uint8_t const desc_hs_configuration[] =
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
-tusb_desc_device_qualifier_t const desc_device_qualifier =
-{
+tusb_desc_device_qualifier_t const desc_device_qualifier = {
.bLength = sizeof(tusb_desc_device_qualifier_t),
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
.bcdUSB = USB_BCD,
@@ -170,16 +164,14 @@ tusb_desc_device_qualifier_t const desc_device_qualifier =
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
// device_qualifier descriptor describes information about a high-speed capable device that would
// change if the device were operating at the other speed. If not highspeed capable stall this request.
-uint8_t const* tud_descriptor_device_qualifier_cb(void)
-{
+uint8_t const* tud_descriptor_device_qualifier_cb(void) {
return (uint8_t const*) &desc_device_qualifier;
}
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
-uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
-{
+uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
// if link speed is high return fullspeed config, and vice versa
@@ -199,8 +191,7 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
-uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
-{
+uint8_t const* tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
#if TUD_OPT_HIGH_SPEED
@@ -224,24 +215,23 @@ enum {
};
// array of pointer to string descriptors
-char const *string_desc_arr[] =
-{
- (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
- "TinyUSB", // 1: Manufacturer
- "TinyUSB Device", // 2: Product
- NULL, // 3: Serials will use unique ID if possible
- "TinyUSB CDC", // 4: CDC Interface
+char const* string_desc_arr[] = {
+ (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409)
+ "TinyUSB", // 1: Manufacturer
+ "TinyUSB Device", // 2: Product
+ NULL, // 3: Serials will use unique ID if possible
+ "TinyUSB CDC", // 4: CDC Interface
};
static uint16_t _desc_str[32 + 1];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
-uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
+uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
(void) langid;
size_t chr_count;
- switch ( index ) {
+ switch (index) {
case STRID_LANGID:
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
@@ -255,17 +245,17 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
- if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL;
+ if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) return NULL;
- const char *str = string_desc_arr[index];
+ const char* str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
- if ( chr_count > max_count ) chr_count = max_count;
+ if (chr_count > max_count) chr_count = max_count;
// Convert ASCII string into UTF-16
- for ( size_t i = 0; i < chr_count; i++ ) {
+ for (size_t i = 0; i < chr_count; i++) {
_desc_str[1 + i] = str[i];
}
break;
diff --git a/examples/dual/host_info_to_device_cdc/CMakeLists.txt b/examples/dual/host_info_to_device_cdc/CMakeLists.txt
new file mode 100644
index 000000000..a6557c2d0
--- /dev/null
+++ b/examples/dual/host_info_to_device_cdc/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. -)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
+project(${PROJECT} C CXX ASM)
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+add_executable(${PROJECT})
+
+# Example source
+target_sources(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+ )
+
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
+
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_dual_usb_example(${PROJECT} noos)
+
+# due to warnings from Pico-PIO-USB
+target_compile_options(${PROJECT} PUBLIC
+ -Wno-error=shadow
+ -Wno-error=cast-align
+ -Wno-error=cast-qual
+ -Wno-error=redundant-decls
+ -Wno-error=sign-conversion
+ -Wno-error=conversion
+ -Wno-error=sign-compare
+ -Wno-error=unused-function
+ )
diff --git a/examples/dual/host_info_to_device_cdc/Makefile b/examples/dual/host_info_to_device_cdc/Makefile
new file mode 100644
index 000000000..0ede79c17
--- /dev/null
+++ b/examples/dual/host_info_to_device_cdc/Makefile
@@ -0,0 +1,17 @@
+include ../../build_system/make/make.mk
+
+INC += \
+ src \
+ $(TOP)/hw \
+
+# Example source
+EXAMPLE_SOURCE += $(wildcard src/*.c)
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference
+
+SRC_C += \
+ src/host/hub.c \
+ src/host/usbh.c
+
+include ../../build_system/make/rules.mk
diff --git a/examples/dual/host_info_to_device_cdc/only.txt b/examples/dual/host_info_to_device_cdc/only.txt
new file mode 100644
index 000000000..cfc87eb4e
--- /dev/null
+++ b/examples/dual/host_info_to_device_cdc/only.txt
@@ -0,0 +1,6 @@
+board:mimxrt1060_evk
+board:mimxrt1064_evk
+board:mcb1800
+mcu:RP2040
+mcu:ra6m5
+mcu:MAX3421
diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c
new file mode 100644
index 000000000..5be531098
--- /dev/null
+++ b/examples/dual/host_info_to_device_cdc/src/main.c
@@ -0,0 +1,285 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+/* Host example will get device descriptors of attached devices and print it out via device cdc as follows:
+ * Device 1: ID 046d:c52f
+ Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 0200
+ bDeviceClass 0
+ bDeviceSubClass 0
+ bDeviceProtocol 0
+ bMaxPacketSize0 8
+ idVendor 0x046d
+ idProduct 0xc52f
+ bcdDevice 2200
+ iManufacturer 1 Logitech
+ iProduct 2 USB Receiver
+ iSerialNumber 0
+ bNumConfigurations 1
+ *
+ */
+
+#include
+#include
+#include
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTYPES
+//--------------------------------------------------------------------+
+// Language ID: English
+#define LANGUAGE_ID 0x0409
+
+/* Blink pattern
+ * - 250 ms : device not mounted
+ * - 1000 ms : device mounted
+ * - 2500 ms : device is suspended
+ */
+enum {
+ BLINK_NOT_MOUNTED = 250,
+ BLINK_MOUNTED = 1000,
+ BLINK_SUSPENDED = 2500,
+};
+
+static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
+
+static bool is_print[CFG_TUH_DEVICE_MAX+1] = { 0 };
+
+static void print_utf16(uint16_t *temp_buf, size_t buf_len);
+void led_blinking_task(void);
+void cdc_task(void);
+
+/*------------- MAIN -------------*/
+int main(void) {
+ board_init();
+
+ printf("TinyUSB Host Information -> Device CDC Example\r\n");
+
+ // init device and host stack on configured roothub port
+ tud_init(BOARD_TUD_RHPORT);
+ tuh_init(BOARD_TUH_RHPORT);
+
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+ while (1) {
+ tud_task(); // tinyusb device task
+ tuh_task(); // tinyusb host task
+ cdc_task();
+ led_blinking_task();
+ }
+
+ return 0;
+}
+
+//--------------------------------------------------------------------+
+// Device CDC
+//--------------------------------------------------------------------+
+
+// Invoked when device is mounted
+void tud_mount_cb(void) {
+ blink_interval_ms = BLINK_MOUNTED;
+}
+
+// Invoked when device is unmounted
+void tud_umount_cb(void) {
+ blink_interval_ms = BLINK_NOT_MOUNTED;
+}
+
+// Invoked when usb bus is suspended
+// remote_wakeup_en : if host allow us to perform remote wakeup
+// Within 7ms, device must draw an average of current less than 2.5 mA from bus
+void tud_suspend_cb(bool remote_wakeup_en) {
+ (void) remote_wakeup_en;
+ blink_interval_ms = BLINK_SUSPENDED;
+}
+
+// Invoked when usb bus is resumed
+void tud_resume_cb(void) {
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
+}
+
+#if 1
+#define cdc_printf(...) \
+ do { \
+ char _tempbuf[256]; \
+ int count = sprintf(_tempbuf, __VA_ARGS__); \
+ tud_cdc_write(_tempbuf, (uint32_t) count); \
+ tud_cdc_write_flush(); \
+ tud_task(); \
+ } while(0)
+#endif
+
+//#define cdc_printf printf
+
+void print_device_info(uint8_t daddr) {
+ tusb_desc_device_t desc_device;
+ uint8_t xfer_result = tuh_descriptor_get_device_sync(daddr, &desc_device, 18);
+ if (XFER_RESULT_SUCCESS != xfer_result) {
+ tud_cdc_write_str("Failed to get device descriptor\r\n");
+ return;
+ }
+
+ cdc_printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct);
+ cdc_printf("Device Descriptor:\r\n");
+ cdc_printf(" bLength %u\r\n" , desc_device.bLength);
+ cdc_printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType);
+ cdc_printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB);
+ cdc_printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass);
+ cdc_printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass);
+ cdc_printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol);
+ cdc_printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0);
+ cdc_printf(" idVendor 0x%04x\r\n" , desc_device.idVendor);
+ cdc_printf(" idProduct 0x%04x\r\n" , desc_device.idProduct);
+ cdc_printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice);
+
+ // Get String descriptor using Sync API
+ uint16_t buf[128];
+
+ cdc_printf(" iManufacturer %u " , desc_device.iManufacturer);
+ xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result ) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ tud_cdc_write_str("\r\n");
+
+ cdc_printf(" iProduct %u " , desc_device.iProduct);
+ xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ tud_cdc_write_str("\r\n");
+
+ cdc_printf(" iSerialNumber %u " , desc_device.iSerialNumber);
+ xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ tud_cdc_write_str("\r\n");
+
+ cdc_printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations);
+}
+
+void cdc_task(void) {
+ if (tud_cdc_connected()) {
+ for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) {
+ if (tuh_mounted(daddr)) {
+ if (is_print[daddr]) {
+ is_print[daddr] = false;
+ print_device_info(daddr);
+ tud_cdc_write_flush();
+ }
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------+
+// Host Get device information
+//--------------------------------------------------------------------+
+void tuh_mount_cb(uint8_t daddr) {
+ printf("mounted device %u\r\n", daddr);
+ is_print[daddr] = true;
+}
+
+void tuh_umount_cb(uint8_t daddr) {
+ printf("unmounted device %u\r\n", daddr);
+ is_print[daddr] = false;
+}
+
+//--------------------------------------------------------------------+
+// Blinking Task
+//--------------------------------------------------------------------+
+void led_blinking_task(void) {
+ static uint32_t start_ms = 0;
+ static bool led_state = false;
+
+ // Blink every interval ms
+ if (board_millis() - start_ms < blink_interval_ms) return; // not enough time
+ start_ms += blink_interval_ms;
+
+ board_led_write(led_state);
+ led_state = 1 - led_state; // toggle
+}
+
+//--------------------------------------------------------------------+
+// String Descriptor Helper
+//--------------------------------------------------------------------+
+
+static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
+ // TODO: Check for runover.
+ (void)utf8_len;
+ // Get the UTF-16 length out of the data itself.
+
+ for (size_t i = 0; i < utf16_len; i++) {
+ uint16_t chr = utf16[i];
+ if (chr < 0x80) {
+ *utf8++ = chr & 0xffu;
+ } else if (chr < 0x800) {
+ *utf8++ = (uint8_t)(0xC0 | (chr >> 6 & 0x1F));
+ *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
+ } else {
+ // TODO: Verify surrogate.
+ *utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F));
+ *utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
+ *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
+ }
+ // TODO: Handle UTF-16 code points that take two entries.
+ }
+}
+
+// Count how many bytes a utf-16-le encoded string will take in utf-8.
+static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
+ size_t total_bytes = 0;
+ for (size_t i = 0; i < len; i++) {
+ uint16_t chr = buf[i];
+ if (chr < 0x80) {
+ total_bytes += 1;
+ } else if (chr < 0x800) {
+ total_bytes += 2;
+ } else {
+ total_bytes += 3;
+ }
+ // TODO: Handle UTF-16 code points that take two entries.
+ }
+ return (int) total_bytes;
+}
+
+static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
+ if ((temp_buf[0] & 0xff) == 0) return; // empty
+ size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
+ size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
+ _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
+ ((uint8_t*) temp_buf)[utf8_len] = '\0';
+
+ tud_cdc_write(temp_buf, utf8_len);
+ tud_cdc_write_flush();
+ tud_task();
+}
diff --git a/examples/dual/host_info_to_device_cdc/src/tusb_config.h b/examples/dual/host_info_to_device_cdc/src/tusb_config.h
new file mode 100644
index 000000000..bb47fbf4a
--- /dev/null
+++ b/examples/dual/host_info_to_device_cdc/src/tusb_config.h
@@ -0,0 +1,143 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef TUSB_CONFIG_H_
+#define TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// Board Specific Configuration
+//--------------------------------------------------------------------+
+
+// RHPort number used for device can be defined by board.mk, default to port 0
+#ifndef BOARD_TUD_RHPORT
+#define BOARD_TUD_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUD_MAX_SPEED
+#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+// RHPort number used for host can be defined by board.mk, default to port 1
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 1
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+#error CFG_TUSB_MCU must be defined
+#endif
+
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS OPT_OS_NONE
+#endif
+
+#ifndef CFG_TUSB_DEBUG
+#define CFG_TUSB_DEBUG 0
+#endif
+
+// Enable Device stack, Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUD_ENABLED 1
+#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED
+
+// Enable Host stack, Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_ENABLED 1
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+// Use pico-pio-usb as host controller for raspberry rp2040
+#define CFG_TUH_RPI_PIO_USB 1
+#endif
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUD_MEM_SECTION
+#define CFG_TUD_MEM_SECTION
+#endif
+
+#ifndef CFG_TUD_MEM_ALIGN
+#define CFG_TUD_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------
+
+#ifndef CFG_TUD_ENDPOINT0_SIZE
+#define CFG_TUD_ENDPOINT0_SIZE 64
+#endif
+
+//------------- CLASS -------------//
+#define CFG_TUD_CDC 1
+
+// CDC FIFO size of TX and RX
+#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+// CDC Endpoint transfer buffer size, more is faster
+#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+//--------------------------------------------------------------------
+// HOST CONFIGURATION
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
+#endif
+
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+#define CFG_TUH_HUB 1
+// max device support (excluding hub device)
+#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c
new file mode 100644
index 000000000..9d57737fb
--- /dev/null
+++ b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c
@@ -0,0 +1,268 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
+ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
+ *
+ * Auto ProductID layout's Bitmap:
+ * [MSB] HID | MSC | CDC [LSB]
+ */
+#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
+#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
+ _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
+
+#define USB_VID 0xCafe
+#define USB_BCD 0x0200
+
+//--------------------------------------------------------------------+
+// Device Descriptors
+//--------------------------------------------------------------------+
+tusb_desc_device_t const desc_device = {
+ .bLength = sizeof(tusb_desc_device_t),
+ .bDescriptorType = TUSB_DESC_DEVICE,
+ .bcdUSB = USB_BCD,
+
+ // Use Interface Association Descriptor (IAD) for CDC
+ // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
+
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+
+ .idVendor = USB_VID,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01
+};
+
+// Invoked when received GET DEVICE DESCRIPTOR
+// Application return pointer to descriptor
+uint8_t const* tud_descriptor_device_cb(void) {
+ return (uint8_t const*) &desc_device;
+}
+
+//--------------------------------------------------------------------+
+// Configuration Descriptor
+//--------------------------------------------------------------------+
+
+enum {
+ ITF_NUM_CDC = 0,
+ ITF_NUM_CDC_DATA,
+ ITF_NUM_TOTAL
+};
+
+#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
+ // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
+ // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x82
+
+#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X
+ // SAMG & SAME70 don't support a same endpoint number with different direction IN and OUT
+ // e.g EP1 OUT & EP1 IN cannot exist together
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x83
+
+#elif CFG_TUSB_MCU == OPT_MCU_CXD56
+ // CXD56 doesn't support a same endpoint number with different direction IN and OUT
+ // e.g EP1 OUT & EP1 IN cannot exist together
+ // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number
+ // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN)
+ #define EPNUM_CDC_NOTIF 0x83
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x81
+
+#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X
+// FT9XX doesn't support a same endpoint number with different direction IN and OUT
+ // e.g EP1 OUT & EP1 IN cannot exist together
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x83
+
+#else
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x82
+
+#endif
+
+#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
+
+// full speed configuration
+uint8_t const desc_fs_configuration[] = {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
+};
+
+#if TUD_OPT_HIGH_SPEED
+// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
+
+// high speed configuration
+uint8_t const desc_hs_configuration[] = {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
+
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
+};
+
+// other speed configuration
+uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
+
+// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
+tusb_desc_device_qualifier_t const desc_device_qualifier = {
+ .bLength = sizeof(tusb_desc_device_qualifier_t),
+ .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
+ .bcdUSB = USB_BCD,
+
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
+
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+ .bNumConfigurations = 0x01,
+ .bReserved = 0x00
+};
+
+// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
+// device_qualifier descriptor describes information about a high-speed capable device that would
+// change if the device were operating at the other speed. If not highspeed capable stall this request.
+uint8_t const* tud_descriptor_device_qualifier_cb(void) {
+ return (uint8_t const*) &desc_device_qualifier;
+}
+
+// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
+uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
+ (void) index; // for multiple configurations
+
+ // if link speed is high return fullspeed config, and vice versa
+ // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
+ memcpy(desc_other_speed_config,
+ (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
+ CONFIG_TOTAL_LEN);
+
+ desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
+
+ return desc_other_speed_config;
+}
+
+#endif // highspeed
+
+
+// Invoked when received GET CONFIGURATION DESCRIPTOR
+// Application return pointer to descriptor
+// Descriptor contents must exist long enough for transfer to complete
+uint8_t const* tud_descriptor_configuration_cb(uint8_t index) {
+ (void) index; // for multiple configurations
+
+#if TUD_OPT_HIGH_SPEED
+ // Although we are highspeed, host may be fullspeed.
+ return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
+#else
+ return desc_fs_configuration;
+#endif
+}
+
+//--------------------------------------------------------------------+
+// String Descriptors
+//--------------------------------------------------------------------+
+
+// String Descriptor Index
+enum {
+ STRID_LANGID = 0,
+ STRID_MANUFACTURER,
+ STRID_PRODUCT,
+ STRID_SERIAL,
+};
+
+// array of pointer to string descriptors
+char const* string_desc_arr[] = {
+ (const char[]) {0x09, 0x04}, // 0: is supported language is English (0x0409)
+ "TinyUSB", // 1: Manufacturer
+ "TinyUSB Device", // 2: Product
+ NULL, // 3: Serials will use unique ID if possible
+ "TinyUSB CDC", // 4: CDC Interface
+};
+
+static uint16_t _desc_str[32 + 1];
+
+// Invoked when received GET STRING DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
+ (void) langid;
+ size_t chr_count;
+
+ switch (index) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
+
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
+
+ default:
+ // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
+
+ if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) return NULL;
+
+ const char* str = string_desc_arr[index];
+
+ // Cap at max char
+ chr_count = strlen(str);
+ size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
+ if (chr_count > max_count) chr_count = max_count;
+
+ // Convert ASCII string into UTF-16
+ for (size_t i = 0; i < chr_count; i++) {
+ _desc_str[1 + i] = str[i];
+ }
+ break;
+ }
+
+ // first byte is length (including header), second byte is string type
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
+
+ return _desc_str;
+}
diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt
index e6a2ece14..793f6ab08 100644
--- a/examples/host/CMakeLists.txt
+++ b/examples/host/CMakeLists.txt
@@ -9,5 +9,6 @@ family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})
family_add_subdirectory(bare_api)
family_add_subdirectory(cdc_msc_hid)
family_add_subdirectory(cdc_msc_hid_freertos)
+family_add_subdirectory(device_info)
family_add_subdirectory(hid_controller)
family_add_subdirectory(msc_file_explorer)
diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c
index 670e58498..ae574c078 100644
--- a/examples/host/bare_api/src/main.c
+++ b/examples/host/bare_api/src/main.c
@@ -23,10 +23,6 @@
*
*/
-/* This example current worked and tested with following controller
- * - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc
- */
-
#include
#include
diff --git a/examples/host/bare_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h
index 432446e94..fab233be0 100644
--- a/examples/host/bare_api/src/tusb_config.h
+++ b/examples/host/bare_api/src/tusb_config.h
@@ -23,8 +23,8 @@
*
*/
-#ifndef _TUSB_CONFIG_H_
-#define _TUSB_CONFIG_H_
+#ifndef TUSB_CONFIG_H_
+#define TUSB_CONFIG_H_
#ifdef __cplusplus
extern "C" {
@@ -118,4 +118,4 @@
}
#endif
-#endif /* _TUSB_CONFIG_H_ */
+#endif
diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c
index f0d42a08f..6bb3a2072 100644
--- a/examples/host/cdc_msc_hid/src/hid_app.c
+++ b/examples/host/cdc_msc_hid/src/hid_app.c
@@ -235,6 +235,7 @@ static void process_mouse_report(hid_mouse_report_t const * report)
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{
(void) dev_addr;
+ (void) len;
uint8_t const rpt_count = hid_info[instance].report_count;
tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info;
diff --git a/examples/host/device_info/CMakeLists.txt b/examples/host/device_info/CMakeLists.txt
new file mode 100644
index 000000000..76182d6fa
--- /dev/null
+++ b/examples/host/device_info/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.17)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
+project(${PROJECT} C CXX ASM)
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+# Espressif has its own cmake build system
+if(FAMILY STREQUAL "espressif")
+ return()
+endif()
+
+add_executable(${PROJECT})
+
+# Example source
+target_sources(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ )
+
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
+
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT} noos)
diff --git a/examples/host/device_info/Makefile b/examples/host/device_info/Makefile
new file mode 100644
index 000000000..0235e08c3
--- /dev/null
+++ b/examples/host/device_info/Makefile
@@ -0,0 +1,13 @@
+include ../../build_system/make/make.mk
+
+INC += \
+ src \
+ $(TOP)/hw \
+
+# Example source
+EXAMPLE_SOURCE += \
+ src/main.c
+
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+include ../../build_system/make/rules.mk
diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt
new file mode 100644
index 000000000..fee10f9e2
--- /dev/null
+++ b/examples/host/device_info/only.txt
@@ -0,0 +1,14 @@
+mcu:KINETIS_KL
+mcu:LPC175X_6X
+mcu:LPC177X_8X
+mcu:LPC18XX
+mcu:LPC40XX
+mcu:LPC43XX
+mcu:MIMXRT1XXX
+mcu:MIMXRT10XX
+mcu:MIMXRT11XX
+mcu:RP2040
+mcu:MSP432E4
+mcu:RX65X
+mcu:RAXXX
+mcu:MAX3421
diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c
new file mode 100644
index 000000000..18beea663
--- /dev/null
+++ b/examples/host/device_info/src/main.c
@@ -0,0 +1,210 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+/* Host example will get device descriptors of attached devices and print it out via uart/rtt (logger) as follows:
+ * Device 1: ID 046d:c52f
+ Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 0200
+ bDeviceClass 0
+ bDeviceSubClass 0
+ bDeviceProtocol 0
+ bMaxPacketSize0 8
+ idVendor 0x046d
+ idProduct 0xc52f
+ bcdDevice 2200
+ iManufacturer 1 Logitech
+ iProduct 2 USB Receiver
+ iSerialNumber 0
+ bNumConfigurations 1
+ *
+ */
+
+#include
+#include
+#include
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+// English
+#define LANGUAGE_ID 0x0409
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTYPES
+//--------------------------------------------------------------------+
+void led_blinking_task(void);
+static void print_utf16(uint16_t* temp_buf, size_t buf_len);
+
+/*------------- MAIN -------------*/
+int main(void) {
+ board_init();
+
+ printf("TinyUSB Device Info Example\r\n");
+
+ // init host stack on configured roothub port
+ tuh_init(BOARD_TUH_RHPORT);
+
+ if (board_init_after_tusb) {
+ board_init_after_tusb();
+ }
+
+ while (1) {
+ // tinyusb host task
+ tuh_task();
+ led_blinking_task();
+ }
+
+ return 0;
+}
+
+/*------------- TinyUSB Callbacks -------------*/
+
+// Invoked when device is mounted (configured)
+void tuh_mount_cb(uint8_t daddr) {
+ // Get Device Descriptor
+ tusb_desc_device_t desc_device;
+ uint8_t xfer_result = tuh_descriptor_get_device_sync(daddr, &desc_device, 18);
+ if (XFER_RESULT_SUCCESS != xfer_result) {
+ printf("Failed to get device descriptor\r\n");
+ return;
+ }
+
+ uint16_t buf[256];
+
+ printf("Device %u: ID %04x:%04x\r\n", daddr, desc_device.idVendor, desc_device.idProduct);
+ printf("Device Descriptor:\r\n");
+ printf(" bLength %u\r\n", desc_device.bLength);
+ printf(" bDescriptorType %u\r\n", desc_device.bDescriptorType);
+ printf(" bcdUSB %04x\r\n", desc_device.bcdUSB);
+ printf(" bDeviceClass %u\r\n", desc_device.bDeviceClass);
+ printf(" bDeviceSubClass %u\r\n", desc_device.bDeviceSubClass);
+ printf(" bDeviceProtocol %u\r\n", desc_device.bDeviceProtocol);
+ printf(" bMaxPacketSize0 %u\r\n", desc_device.bMaxPacketSize0);
+ printf(" idVendor 0x%04x\r\n", desc_device.idVendor);
+ printf(" idProduct 0x%04x\r\n", desc_device.idProduct);
+ printf(" bcdDevice %04x\r\n", desc_device.bcdDevice);
+
+ // Get String descriptor using Sync API
+
+ printf(" iManufacturer %u ", desc_device.iManufacturer);
+ xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ printf("\r\n");
+
+ printf(" iProduct %u ", desc_device.iProduct);
+ xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ printf("\r\n");
+
+ printf(" iSerialNumber %u ", desc_device.iSerialNumber);
+ xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ printf("\r\n");
+
+ printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations);
+}
+
+/// Invoked when device is unmounted (bus reset/unplugged)
+void tuh_umount_cb(uint8_t daddr) {
+ printf("Device removed, address = %d\r\n", daddr);
+}
+
+//--------------------------------------------------------------------+
+// Blinking Task
+//--------------------------------------------------------------------+
+void led_blinking_task(void) {
+ const uint32_t interval_ms = 1000;
+ static uint32_t start_ms = 0;
+
+ static bool led_state = false;
+
+ // Blink every interval ms
+ if (board_millis() - start_ms < interval_ms) return; // not enough time
+ start_ms += interval_ms;
+
+ board_led_write(led_state);
+ led_state = 1 - led_state; // toggle
+}
+
+//--------------------------------------------------------------------+
+// String Descriptor Helper
+//--------------------------------------------------------------------+
+
+static void _convert_utf16le_to_utf8(const uint16_t* utf16, size_t utf16_len, uint8_t* utf8, size_t utf8_len) {
+ // TODO: Check for runover.
+ (void) utf8_len;
+ // Get the UTF-16 length out of the data itself.
+
+ for (size_t i = 0; i < utf16_len; i++) {
+ uint16_t chr = utf16[i];
+ if (chr < 0x80) {
+ *utf8++ = chr & 0xffu;
+ } else if (chr < 0x800) {
+ *utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
+ *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
+ } else {
+ // TODO: Verify surrogate.
+ *utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
+ *utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
+ *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
+ }
+ // TODO: Handle UTF-16 code points that take two entries.
+ }
+}
+
+// Count how many bytes a utf-16-le encoded string will take in utf-8.
+static int _count_utf8_bytes(const uint16_t* buf, size_t len) {
+ size_t total_bytes = 0;
+ for (size_t i = 0; i < len; i++) {
+ uint16_t chr = buf[i];
+ if (chr < 0x80) {
+ total_bytes += 1;
+ } else if (chr < 0x800) {
+ total_bytes += 2;
+ } else {
+ total_bytes += 3;
+ }
+ // TODO: Handle UTF-16 code points that take two entries.
+ }
+ return (int) total_bytes;
+}
+
+static void print_utf16(uint16_t* temp_buf, size_t buf_len) {
+ if ((temp_buf[0] & 0xff) == 0) return; // empty
+ size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
+ size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
+ _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t*) temp_buf, sizeof(uint16_t) * buf_len);
+ ((uint8_t*) temp_buf)[utf8_len] = '\0';
+
+ printf("%s", (char*) temp_buf);
+}
diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h
new file mode 100644
index 000000000..2e9731eaf
--- /dev/null
+++ b/examples/host/device_info/src/tusb_config.h
@@ -0,0 +1,115 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef TUSB_CONFIG_H_
+#define TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------
+// Common Configuration
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+#error CFG_TUSB_MCU must be defined
+#endif
+
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS OPT_OS_NONE
+#endif
+
+#ifndef CFG_TUSB_DEBUG
+#define CFG_TUSB_DEBUG 0
+#endif
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
+#endif
+
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+// only hub class is enabled
+#define CFG_TUH_HUB 1
+
+// max device support (excluding hub device)
+// 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c
index bff830ca2..6ffe0b6d4 100644
--- a/examples/host/hid_controller/src/hid_app.c
+++ b/examples/host/hid_controller/src/hid_app.c
@@ -253,6 +253,7 @@ bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
void process_sony_ds4(uint8_t const* report, uint16_t len)
{
+ (void)len;
const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" };
// previous report used to compare for changes
diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h
index eee9ed9c5..a458a3fdc 100644
--- a/hw/bsp/board_api.h
+++ b/hw/bsp/board_api.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _BOARD_API_H_
-#define _BOARD_API_H_
+#ifndef BOARD_API_H_
+#define BOARD_API_H_
#ifdef __cplusplus
extern "C" {
@@ -72,6 +72,9 @@ void board_init(void);
// Init board after tinyusb is initialized
void board_init_after_tusb(void) TU_ATTR_WEAK;
+// Jump to bootloader
+void board_reset_to_bootloader(void) TU_ATTR_WEAK;
+
// Turn LED on or off
void board_led_write(bool state);
diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.cmake b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake
similarity index 89%
rename from hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.cmake
rename to hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake
index 8d3e0326e..f6e47ba30 100644
--- a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.cmake
+++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake
@@ -1,5 +1,3 @@
-set(MCU_VARIANT D6)
-
set(LD_FLASH_SIZE 64K)
set(LD_RAM_SIZE 20K)
diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h
similarity index 53%
rename from hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h
rename to hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h
index 3ed2aef04..3b1187c3a 100644
--- a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.h
+++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h
@@ -6,9 +6,13 @@ extern "C" {
#endif
#define LED_PORT GPIOA
-#define LED_PIN GPIO_Pin_15
+#define LED_PIN GPIO_Pin_10
#define LED_STATE_ON 0
+#define BUTTON_PORT GPIOA
+#define BUTTON_PIN GPIO_Pin_1
+#define BUTTON_STATE_ACTIVE 0
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk
new file mode 100644
index 000000000..e594f42a7
--- /dev/null
+++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk
@@ -0,0 +1,5 @@
+CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY
+
+LDFLAGS += \
+ -Wl,--defsym=__FLASH_SIZE=64K \
+ -Wl,--defsym=__RAM_SIZE=20K \
diff --git a/hw/bsp/ch32v10x/ch32v10x_conf.h b/hw/bsp/ch32v10x/ch32v10x_conf.h
new file mode 100644
index 000000000..939c0fbde
--- /dev/null
+++ b/hw/bsp/ch32v10x/ch32v10x_conf.h
@@ -0,0 +1,37 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : ch32v10x_conf.h
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2020/04/30
+ * Description : Library configuration file.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#ifndef __CH32V10x_CONF_H
+#define __CH32V10x_CONF_H
+
+#include "ch32v10x_adc.h"
+#include "ch32v10x_bkp.h"
+#include "ch32v10x_crc.h"
+#include "ch32v10x_dbgmcu.h"
+#include "ch32v10x_dma.h"
+#include "ch32v10x_exti.h"
+#include "ch32v10x_flash.h"
+#include "ch32v10x_gpio.h"
+#include "ch32v10x_i2c.h"
+#include "ch32v10x_iwdg.h"
+#include "ch32v10x_pwr.h"
+#include "ch32v10x_rcc.h"
+#include "ch32v10x_rtc.h"
+#include "ch32v10x_spi.h"
+#include "ch32v10x_tim.h"
+#include "ch32v10x_usart.h"
+#include "ch32v10x_wwdg.h"
+#include "ch32v10x_usb.h"
+#include "ch32v10x_usb_host.h"
+#include "ch32v10x_it.h"
+#include "ch32v10x_misc.h"
+
+#endif /* __CH32V10x_CONF_H */
diff --git a/hw/bsp/ch32v10x/ch32v10x_it.h b/hw/bsp/ch32v10x/ch32v10x_it.h
new file mode 100644
index 000000000..13afc2412
--- /dev/null
+++ b/hw/bsp/ch32v10x/ch32v10x_it.h
@@ -0,0 +1,15 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : ch32v10x_it.h
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2022/08/20
+ * Description : This file contains the headers of the interrupt handlers.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#ifndef __CH32V10x_IT_H
+#define __CH32V10x_IT_H
+
+#endif /* __CH32V10x_IT_H */
diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c
new file mode 100644
index 000000000..15f754e11
--- /dev/null
+++ b/hw/bsp/ch32v10x/family.c
@@ -0,0 +1,148 @@
+#include
+
+// https://github.com/openwch/ch32v307/pull/90
+// https://github.com/openwch/ch32v20x/pull/12
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+
+#include "ch32v10x.h"
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#include "bsp/board_api.h"
+#include "board.h"
+
+__attribute__((interrupt)) __attribute__((used))
+void USBHD_IRQHandler(void) {
+ #if CFG_TUD_WCH_USBIP_USBFS
+ tud_int_handler(0);
+ #endif
+}
+
+__attribute__((interrupt)) __attribute__((used))
+void USBWakeUp_IRQHandler(void) {
+ #if CFG_TUD_WCH_USBIP_USBFS
+ tud_int_handler(0);
+ #endif
+}
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+volatile uint32_t system_ticks = 0;
+
+__attribute__((interrupt)) __attribute__((used))
+void SysTick_Handler(void) {
+ SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0;
+ SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0;
+ system_ticks++;
+}
+
+uint32_t SysTick_Config(uint32_t ticks) {
+ NVIC_EnableIRQ(SysTicK_IRQn);
+ SysTick->CTLR = 0;
+ SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0;
+ SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0;
+
+ SysTick->CMPLR0 = (u8)(ticks & 0xFF);
+ SysTick->CMPLR1 = (u8)(ticks >> 8);
+ SysTick->CMPLR2 = (u8)(ticks >> 16);
+ SysTick->CMPLR3 = (u8)(ticks >> 24);
+
+ SysTick->CMPHR0 = SysTick->CMPHR1 = SysTick->CMPHR2 = SysTick->CMPHR3 = 0;
+ SysTick->CTLR = 1;
+ return 0;
+}
+
+uint32_t board_millis(void) {
+ return system_ticks;
+}
+#endif
+
+void board_init(void) {
+ __disable_irq();
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+ SysTick_Config(SystemCoreClock / 1000);
+#endif
+
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
+
+ EXTEN->EXTEN_CTR |= EXTEN_USBFS_IO_EN;
+ uint8_t usb_div;
+ switch (SystemCoreClock) {
+ case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break;
+ case 72000000: usb_div = RCC_USBCLKSource_PLLCLK_1Div5; break;
+ default: TU_ASSERT(0,); break;
+ }
+ RCC_USBCLKConfig(usb_div);
+ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE);
+
+ #ifdef LED_PIN
+ GPIO_InitTypeDef led_init = {
+ .GPIO_Pin = LED_PIN,
+ .GPIO_Mode = GPIO_Mode_Out_OD,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ };
+ GPIO_Init(LED_PORT, &led_init);
+ #endif
+
+ #ifdef BUTTON_PIN
+ GPIO_InitTypeDef button_init = {
+ .GPIO_Pin = BUTTON_PIN,
+ .GPIO_Mode = GPIO_Mode_IPU,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ };
+ GPIO_Init(BUTTON_PORT, &button_init);
+ #endif
+
+ // UART TX is PA9
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
+ GPIO_InitTypeDef usart_init = {
+ .GPIO_Pin = GPIO_Pin_9,
+ .GPIO_Speed = GPIO_Speed_50MHz,
+ .GPIO_Mode = GPIO_Mode_AF_PP,
+ };
+ GPIO_Init(GPIOA, &usart_init);
+
+ USART_InitTypeDef usart = {
+ .USART_BaudRate = 115200,
+ .USART_WordLength = USART_WordLength_8b,
+ .USART_StopBits = USART_StopBits_1,
+ .USART_Parity = USART_Parity_No,
+ .USART_Mode = USART_Mode_Tx,
+ .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
+ };
+ USART_Init(USART1, &usart);
+ USART_Cmd(USART1, ENABLE);
+
+ __enable_irq();
+
+ board_led_write(true);
+}
+
+void board_led_write(bool state) {
+ GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
+}
+
+uint32_t board_button_read(void) {
+ return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN);
+}
+
+int board_uart_read(uint8_t *buf, int len) {
+ (void) buf;
+ (void) len;
+ return 0;
+}
+
+int board_uart_write(void const *buf, int len) {
+ const char *bufc = (const char *) buf;
+ for (int i = 0; i < len; i++) {
+ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
+ USART_SendData(USART1, *bufc++);
+ }
+
+ return len;
+}
diff --git a/hw/bsp/ch32v10x/family.cmake b/hw/bsp/ch32v10x/family.cmake
new file mode 100644
index 000000000..c0af0ef44
--- /dev/null
+++ b/hw/bsp/ch32v10x/family.cmake
@@ -0,0 +1,117 @@
+include_guard()
+
+#set(UF2_FAMILY_ID 0x699b62ec)
+set(CH32_FAMILY ch32v10x)
+set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v103)
+set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
+
+# include board specific
+include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
+
+# toolchain set up
+set(CMAKE_SYSTEM_PROCESSOR rv32imac-ilp32 CACHE INTERNAL "System Processor")
+set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake)
+
+set(FAMILY_MCUS CH32V103 CACHE INTERNAL "")
+set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg")
+
+#------------------------------------
+# BOARD_TARGET
+#------------------------------------
+# only need to be built ONCE for all examples
+function(add_board_target BOARD_TARGET)
+ if (TARGET ${BOARD_TARGET})
+ return()
+ endif()
+
+ if (NOT DEFINED LD_FILE_GNU)
+ set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${CH32_FAMILY}.ld)
+ endif ()
+ set(LD_FILE_Clang ${LD_FILE_GNU})
+
+ if (NOT DEFINED STARTUP_FILE_GNU)
+ set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}.S)
+ endif ()
+ set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
+
+ add_library(${BOARD_TARGET} STATIC
+ ${SDK_SRC_DIR}/Core/core_riscv.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c
+ ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
+ )
+ target_include_directories(${BOARD_TARGET} PUBLIC
+ ${SDK_SRC_DIR}/Core
+ ${SDK_SRC_DIR}/Peripheral/inc
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ )
+ target_compile_definitions(${BOARD_TARGET} PUBLIC
+ )
+
+ update_board(${BOARD_TARGET})
+
+ if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ target_compile_options(${BOARD_TARGET} PUBLIC
+ -mcmodel=medany
+ )
+ target_link_options(${BOARD_TARGET} PUBLIC
+ "LINKER:--script=${LD_FILE_GNU}"
+ -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE}
+ -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE}
+ -nostartfiles
+ --specs=nosys.specs --specs=nano.specs
+ )
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ message(FATAL_ERROR "Clang is not supported for MSP432E4")
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+ target_link_options(${BOARD_TARGET} PUBLIC
+ "LINKER:--config=${LD_FILE_IAR}"
+ )
+ endif ()
+endfunction()
+
+
+#------------------------------------
+# Functions
+#------------------------------------
+function(family_configure_example TARGET RTOS)
+ family_configure_common(${TARGET} ${RTOS})
+
+ # Board target
+ add_board_target(board_${BOARD})
+
+ #---------- Port Specific ----------
+ # These files are built for each example since it depends on example's tusb_config.h
+ target_sources(${TARGET} PUBLIC
+ # BSP
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
+ )
+ target_include_directories(${TARGET} PUBLIC
+ # family, hw, board
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
+ )
+
+ # Add TinyUSB target and port source
+ family_add_tinyusb(${TARGET} OPT_MCU_CH32V103 ${RTOS})
+
+ target_sources(${TARGET}-tinyusb PUBLIC
+ ${TOP}/src/portable/wch/dcd_ch32_usbfs.c
+ )
+ target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD})
+
+ # Link dependencies
+ target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb)
+
+ # Flashing
+ family_add_bin_hex(${TARGET})
+ family_flash_openocd_wch(${TARGET})
+
+ #family_add_uf2(${TARGET} ${UF2_FAMILY_ID})
+ #family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
+endfunction()
diff --git a/hw/bsp/ch32v10x/family.mk b/hw/bsp/ch32v10x/family.mk
new file mode 100644
index 000000000..d96d5012e
--- /dev/null
+++ b/hw/bsp/ch32v10x/family.mk
@@ -0,0 +1,53 @@
+# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable
+#CROSS_COMPILE ?= riscv32-unknown-elf-
+
+# Toolchain from https://nucleisys.com/download.php
+#CROSS_COMPILE ?= riscv-nuclei-elf-
+
+# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
+CROSS_COMPILE ?= riscv-none-elf-
+
+CH32_FAMILY = ch32v10x
+SDK_DIR = hw/mcu/wch/ch32v103
+SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC
+
+include $(TOP)/$(BOARD_PATH)/board.mk
+CPU_CORE ?= rv32imac-ilp32
+
+# Port0 use FSDev, Port1 use USBFS
+PORT ?= 0
+
+CFLAGS += \
+ -mcmodel=medany \
+ -ffat-lto-objects \
+ -flto \
+ -DCFG_TUSB_MCU=OPT_MCU_CH32V103
+
+# https://github.com/openwch/ch32v20x/pull/12
+CFLAGS += -Wno-error=strict-prototypes
+
+LDFLAGS_GCC += \
+ -nostdlib -nostartfiles \
+ --specs=nosys.specs --specs=nano.specs \
+
+LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld
+
+SRC_C += \
+ src/portable/wch/dcd_ch32_usbfs.c \
+ $(SDK_SRC_DIR)/Core/core_riscv.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \
+
+SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}.S
+
+INC += \
+ $(TOP)/$(BOARD_PATH) \
+ $(TOP)/$(SDK_SRC_DIR)/Core \
+ $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \
+
+FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
+
+OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
+flash: flash-openocd-wch
diff --git a/hw/bsp/ch32v10x/linker/ch32v10x.ld b/hw/bsp/ch32v10x/linker/ch32v10x.ld
new file mode 100644
index 000000000..cd5c8dc17
--- /dev/null
+++ b/hw/bsp/ch32v10x/linker/ch32v10x.ld
@@ -0,0 +1,165 @@
+/* Define default values if not already defined */
+__FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K;
+__RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K;
+
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE
+}
+
+ENTRY( _start )
+
+__stack_size = 2048;
+
+PROVIDE( _stack_size = __stack_size );
+
+SECTIONS
+{
+ .init :
+ {
+ _sinit = .;
+ . = ALIGN(4);
+ KEEP(*(SORT_NONE(.init)))
+ . = ALIGN(4);
+ _einit = .;
+ } >FLASH AT>FLASH
+
+ .vector :
+ {
+ *(.vector);
+ . = ALIGN(64);
+ } >FLASH AT>FLASH
+
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text)
+ *(.text.*)
+ *(.rodata)
+ *(.rodata*)
+ *(.gnu.linkonce.t.*)
+ . = ALIGN(4);
+ } >FLASH AT>FLASH
+
+ .fini :
+ {
+ KEEP(*(SORT_NONE(.fini)))
+ . = ALIGN(4);
+ } >FLASH AT>FLASH
+
+ PROVIDE( _etext = . );
+ PROVIDE( _eitcm = . );
+
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ } >FLASH AT>FLASH
+
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ } >FLASH AT>FLASH
+
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ } >FLASH AT>FLASH
+
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ } >FLASH AT>FLASH
+
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ } >FLASH AT>FLASH
+
+ .dalign :
+ {
+ . = ALIGN(4);
+ PROVIDE(_data_vma = .);
+ } >RAM AT>FLASH
+
+ .dlalign :
+ {
+ . = ALIGN(4);
+ PROVIDE(_data_lma = .);
+ } >FLASH AT>FLASH
+
+ .data :
+ {
+ *(.gnu.linkonce.r.*)
+ *(.data .data.*)
+ *(.gnu.linkonce.d.*)
+ . = ALIGN(8);
+ PROVIDE( __global_pointer$ = . + 0x800 );
+ *(.sdata .sdata.*)
+ *(.sdata2.*)
+ *(.gnu.linkonce.s.*)
+ . = ALIGN(8);
+ *(.srodata.cst16)
+ *(.srodata.cst8)
+ *(.srodata.cst4)
+ *(.srodata.cst2)
+ *(.srodata .srodata.*)
+ . = ALIGN(4);
+ PROVIDE( _edata = .);
+ } >RAM AT>FLASH
+
+ .bss :
+ {
+ . = ALIGN(4);
+ PROVIDE( _sbss = .);
+ *(.sbss*)
+ *(.gnu.linkonce.sb.*)
+ *(.bss*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON*)
+ . = ALIGN(4);
+ PROVIDE( _ebss = .);
+ } >RAM AT>FLASH
+
+ PROVIDE( _end = _ebss);
+ PROVIDE( end = . );
+
+ .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :
+ {
+ PROVIDE( _heap_end = . );
+ . = ALIGN(4);
+ PROVIDE(_susrstack = . );
+ . = . + __stack_size;
+ PROVIDE( _eusrstack = .);
+ } >RAM
+
+}
diff --git a/hw/bsp/ch32v10x/system_ch32v10x.c b/hw/bsp/ch32v10x/system_ch32v10x.c
new file mode 100644
index 000000000..b083b83b4
--- /dev/null
+++ b/hw/bsp/ch32v10x/system_ch32v10x.c
@@ -0,0 +1,600 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : system_ch32v10x.c
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2020/04/30
+ * Description : CH32V10x Device Peripheral Access Layer System Source File.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#include "ch32v10x.h"
+
+/*
+ * Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
+ * reset the HSI is used as SYSCLK source).
+ * If none of the define below is enabled, the HSI is used as System clock source.
+ */
+//#define SYSCLK_FREQ_HSE HSE_VALUE
+//#define SYSCLK_FREQ_48MHz_HSE 48000000
+//#define SYSCLK_FREQ_56MHz_HSE 56000000
+#define SYSCLK_FREQ_72MHz_HSE 72000000
+//#define SYSCLK_FREQ_HSI HSI_VALUE
+//#define SYSCLK_FREQ_48MHz_HSI 48000000
+//#define SYSCLK_FREQ_56MHz_HSI 56000000
+//#define SYSCLK_FREQ_72MHz_HSI 72000000
+
+/* Clock Definitions */
+#ifdef SYSCLK_FREQ_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_48MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_56MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_72MHz_HSE
+uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_48MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_56MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
+#elif defined SYSCLK_FREQ_72MHz_HSI
+uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
+#else
+uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
+
+#endif
+
+__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/* ch32v10x_system_private_function_proto_types */
+static void SetSysClock(void);
+
+#ifdef SYSCLK_FREQ_HSE
+static void SetSysClockToHSE( void );
+#elif defined SYSCLK_FREQ_48MHz_HSE
+static void SetSysClockTo48_HSE( void );
+#elif defined SYSCLK_FREQ_56MHz_HSE
+static void SetSysClockTo56_HSE( void );
+#elif defined SYSCLK_FREQ_72MHz_HSE
+static void SetSysClockTo72_HSE( void );
+#elif defined SYSCLK_FREQ_48MHz_HSI
+static void SetSysClockTo48_HSI( void );
+#elif defined SYSCLK_FREQ_56MHz_HSI
+static void SetSysClockTo56_HSI( void );
+#elif defined SYSCLK_FREQ_72MHz_HSI
+static void SetSysClockTo72_HSI( void );
+
+#endif
+
+/*********************************************************************
+ * @fn SystemInit
+ *
+ * @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
+ * the PLL and update the SystemCoreClock variable.
+ *
+ * @return none
+ */
+void SystemInit(void)
+{
+ RCC->CTLR |= (uint32_t)0x00000001;
+ RCC->CFGR0 &= (uint32_t)0xF8FF0000;
+ RCC->CTLR &= (uint32_t)0xFEF6FFFF;
+ RCC->CTLR &= (uint32_t)0xFFFBFFFF;
+ RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
+ RCC->INTR = 0x009F0000;
+ SetSysClock();
+}
+
+/*********************************************************************
+ * @fn SystemCoreClockUpdate
+ *
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
+ *
+ * @return none
+ */
+void SystemCoreClockUpdate(void)
+{
+ uint32_t tmp = 0, pllmull = 0, pllsource = 0;
+
+ tmp = RCC->CFGR0 & RCC_SWS;
+
+ switch(tmp)
+ {
+ case 0x00:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ case 0x04:
+ SystemCoreClock = HSE_VALUE;
+ break;
+ case 0x08:
+ pllmull = RCC->CFGR0 & RCC_PLLMULL;
+ pllsource = RCC->CFGR0 & RCC_PLLSRC;
+ pllmull = (pllmull >> 18) + 2;
+ if(pllsource == 0x00)
+ {
+ if( EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE )
+ {
+ SystemCoreClock = ( HSI_VALUE ) * pllmull;
+ }
+ else
+ {
+ SystemCoreClock = ( HSI_VALUE >> 1 ) * pllmull;
+ }
+ }
+ else
+ {
+ if((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
+ {
+ SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
+ }
+ else
+ {
+ SystemCoreClock = HSE_VALUE * pllmull;
+ }
+ }
+ break;
+ default:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ }
+
+ tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
+ SystemCoreClock >>= tmp;
+}
+
+/*********************************************************************
+ * @fn SetSysClock
+ *
+ * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClock(void)
+{
+ //GPIO_IPD_Unused();
+#ifdef SYSCLK_FREQ_HSE
+ SetSysClockToHSE();
+#elif defined SYSCLK_FREQ_48MHz_HSE
+ SetSysClockTo48_HSE();
+#elif defined SYSCLK_FREQ_56MHz_HSE
+ SetSysClockTo56_HSE();
+#elif defined SYSCLK_FREQ_72MHz_HSE
+ SetSysClockTo72_HSE();
+#elif defined SYSCLK_FREQ_48MHz_HSI
+ SetSysClockTo48_HSI();
+#elif defined SYSCLK_FREQ_56MHz_HSI
+ SetSysClockTo56_HSI();
+#elif defined SYSCLK_FREQ_72MHz_HSI
+ SetSysClockTo72_HSI();
+
+#endif
+
+ /* If none of the define above is enabled, the HSI is used as System clock
+ * source (default after reset)
+ */
+}
+
+#ifdef SYSCLK_FREQ_HSE
+
+/*********************************************************************
+ * @fn SetSysClockToHSE
+ *
+ * @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockToHSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+ /* Flash 0 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
+
+ /* Select HSE as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
+
+ /* Wait till HSE is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
+ {
+ }
+ }
+ else
+ {
+ /* If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+
+#elif defined SYSCLK_FREQ_48MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo48_HSE
+ *
+ * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo48_HSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL6);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_56MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo56_HSE
+ *
+ * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo56_HSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 2 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL7);
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_72MHz_HSE
+
+/*********************************************************************
+ * @fn SetSysClockTo72_HSE
+ *
+ * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo72_HSE(void)
+{
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
+
+ RCC->CTLR |= ((uint32_t)RCC_HSEON);
+
+ /* Wait till HSE is ready and if Time out is reached exit */
+ do
+ {
+ HSEStatus = RCC->CTLR & RCC_HSERDY;
+ StartUpCounter++;
+ } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
+
+ if((RCC->CTLR & RCC_HSERDY) != RESET)
+ {
+ HSEStatus = (uint32_t)0x01;
+ }
+ else
+ {
+ HSEStatus = (uint32_t)0x00;
+ }
+
+ if(HSEStatus == (uint32_t)0x01)
+ {
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 2 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
+ RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL9);
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+ }
+ else
+ {
+ /*
+ * If HSE fails to start-up, the application will have wrong clock
+ * configuration. User can add here some code to deal with this error
+ */
+ }
+}
+
+#elif defined SYSCLK_FREQ_48MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo48_HSI
+ *
+ * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo48_HSI(void)
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+}
+
+#elif defined SYSCLK_FREQ_56MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo56_HSI
+ *
+ * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo56_HSI(void)
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 7 = 56 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+}
+
+#elif defined SYSCLK_FREQ_72MHz_HSI
+
+/*********************************************************************
+ * @fn SetSysClockTo72_HSI
+ *
+ * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
+ *
+ * @return none
+ */
+static void SetSysClockTo72_HSI(void)
+{
+ EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
+
+ /* Enable Prefetch Buffer */
+ FLASH->ACTLR |= FLASH_ACTLR_PRFTBE;
+
+ /* Flash 1 wait state */
+ FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY);
+ FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1;
+
+ /* HCLK = SYSCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
+ /* PCLK2 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
+ /* PCLK1 = HCLK */
+ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
+
+ /* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
+ RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9);
+
+ /* Enable PLL */
+ RCC->CTLR |= RCC_PLLON;
+ /* Wait till PLL is ready */
+ while((RCC->CTLR & RCC_PLLRDY) == 0)
+ {
+ }
+ /* Select PLL as system clock source */
+ RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
+ RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
+ /* Wait till PLL is used as system clock source */
+ while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
+ {
+ }
+}
+
+#endif
diff --git a/hw/bsp/ch32v10x/system_ch32v10x.h b/hw/bsp/ch32v10x/system_ch32v10x.h
new file mode 100644
index 000000000..d15624520
--- /dev/null
+++ b/hw/bsp/ch32v10x/system_ch32v10x.h
@@ -0,0 +1,29 @@
+/********************************** (C) COPYRIGHT *******************************
+ * File Name : system_ch32v10x.h
+ * Author : WCH
+ * Version : V1.0.0
+ * Date : 2020/04/30
+ * Description : CH32V10x Device Peripheral Access Layer System Header File.
+*********************************************************************************
+* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
+* Attention: This software (modified or not) and binary are used for
+* microcontroller manufactured by Nanjing Qinheng Microelectronics.
+*******************************************************************************/
+#ifndef __SYSTEM_CH32V10x_H
+#define __SYSTEM_CH32V10x_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
+
+/* System_Exported_Functions */
+extern void SystemInit(void);
+extern void SystemCoreClockUpdate(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__CH32V10x_SYSTEM_H */
diff --git a/hw/bsp/ch32v10x/wch-riscv.cfg b/hw/bsp/ch32v10x/wch-riscv.cfg
new file mode 100644
index 000000000..aa35aa9c5
--- /dev/null
+++ b/hw/bsp/ch32v10x/wch-riscv.cfg
@@ -0,0 +1,17 @@
+adapter driver wlinke
+adapter speed 6000
+transport select sdi
+
+wlink_set_address 0x00000000
+set _CHIPNAME wch_riscv
+sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001
+
+set _TARGETNAME $_CHIPNAME.cpu
+
+target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME
+$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1
+set _FLASHNAME $_CHIPNAME.flash
+
+flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0
+
+echo "Ready for Remote Connections"
diff --git a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.mk b/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.mk
deleted file mode 100644
index 7d7462312..000000000
--- a/hw/bsp/ch32v20x/boards/ch32v203_r0_1v0/board.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-MCU_VARIANT = D6
-
-CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY
-
-LDFLAGS += \
- -Wl,--defsym=__flash_size=64K \
- -Wl,--defsym=__ram_size=20K \
diff --git a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake
new file mode 100644
index 000000000..4aae6bdc2
--- /dev/null
+++ b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake
@@ -0,0 +1,15 @@
+set(MCU_VARIANT D6)
+
+# 64KB zero-wait, 224KB total flash
+#set(LD_FLASH_SIZE 64K)
+set(LD_FLASH_SIZE 224K)
+set(LD_RAM_SIZE 20K)
+
+# set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/${CH32_FAMILY}_tinyuf2.ld)
+
+function(update_board TARGET)
+ target_compile_definitions(${TARGET} PUBLIC
+ SYSCLK_FREQ_144MHz_HSE=144000000
+ CFG_EXAMPLE_MSC_DUAL_READONLY
+ )
+endfunction()
diff --git a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h
new file mode 100644
index 000000000..692cf11bf
--- /dev/null
+++ b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h
@@ -0,0 +1,21 @@
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LED_PORT GPIOA
+#define LED_PIN GPIO_Pin_0
+#define LED_STATE_ON 0
+
+#define UART_DEV USART1
+#define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
+#define UART_TX_PIN GPIO_Pin_9
+#define UART_RX_PIN GPIO_Pin_10
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.mk b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.mk
new file mode 100644
index 000000000..bdd15f737
--- /dev/null
+++ b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.mk
@@ -0,0 +1,11 @@
+MCU_VARIANT = D6
+
+CFLAGS += \
+ -DSYSCLK_FREQ_144MHz_HSE=144000000 \
+ -DCH32_FLASH_ENHANCE_READ_MODE=1 \
+ -DCFG_EXAMPLE_MSC_DUAL_READONLY \
+
+# 64KB zero-wait, 224KB total flash
+LDFLAGS += \
+ -Wl,--defsym=__FLASH_SIZE=224K \
+ -Wl,--defsym=__RAM_SIZE=20K \
diff --git a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake
new file mode 100644
index 000000000..ecb8b378f
--- /dev/null
+++ b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake
@@ -0,0 +1,13 @@
+set(MCU_VARIANT D6)
+
+# 32KB zero-wait, 224KB total flash
+#set(LD_FLASH_SIZE 32K)
+set(LD_FLASH_SIZE 224K)
+set(LD_RAM_SIZE 10K)
+
+function(update_board TARGET)
+ target_compile_definitions(${TARGET} PUBLIC
+ SYSCLK_FREQ_144MHz_HSI=144000000
+ CFG_EXAMPLE_MSC_DUAL_READONLY
+ )
+endfunction()
diff --git a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h
new file mode 100644
index 000000000..783831edd
--- /dev/null
+++ b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h
@@ -0,0 +1,21 @@
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LED_PORT GPIOA
+#define LED_PIN GPIO_Pin_0
+#define LED_STATE_ON 0
+
+#define UART_DEV USART2
+#define UART_CLOCK_EN() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE)
+#define UART_TX_PIN GPIO_Pin_2
+#define UART_RX_PIN GPIO_Pin_3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.mk b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.mk
new file mode 100644
index 000000000..f71f53478
--- /dev/null
+++ b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.mk
@@ -0,0 +1,11 @@
+MCU_VARIANT = D6
+
+CFLAGS += \
+ -DSYSCLK_FREQ_144MHz_HSI=144000000 \
+ -DCH32_FLASH_ENHANCE_READ_MODE=1 \
+ -DCFG_EXAMPLE_MSC_DUAL_READONLY \
+
+# 32KB zero-wait, 224KB total flash
+LDFLAGS += \
+ -Wl,--defsym=__FLASH_SIZE=224K \
+ -Wl,--defsym=__RAM_SIZE=10K \
diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake
index 8d3e0326e..a0bf12b5c 100644
--- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake
+++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake
@@ -1,10 +1,13 @@
set(MCU_VARIANT D6)
-set(LD_FLASH_SIZE 64K)
+# 64KB zero-wait, 224KB total flash
+#set(LD_FLASH_SIZE 64K)
+set(LD_FLASH_SIZE 224K)
set(LD_RAM_SIZE 20K)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
+ SYSCLK_FREQ_144MHz_HSE=144000000
CFG_EXAMPLE_MSC_DUAL_READONLY
)
endfunction()
diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.h b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h
index c8d28d90f..64eaf931e 100644
--- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.h
+++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h
@@ -8,7 +8,11 @@ extern "C" {
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_15
#define LED_STATE_ON 0
-#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
+
+#define UART_DEV USART1
+#define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
+#define UART_TX_PIN GPIO_Pin_9
+#define UART_RX_PIN GPIO_Pin_10
#ifdef __cplusplus
}
diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk b/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk
index 7d7462312..362aace47 100644
--- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk
+++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.mk
@@ -1,7 +1,11 @@
MCU_VARIANT = D6
-CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY
+CFLAGS += \
+ -DSYSCLK_FREQ_144MHz_HSE=144000000 \
+ -DCH32_FLASH_ENHANCE_READ_MODE=1 \
+ -DCFG_EXAMPLE_MSC_DUAL_READONLY \
+# 64KB zero-wait , 224KB total flash
LDFLAGS += \
- -Wl,--defsym=__flash_size=64K \
- -Wl,--defsym=__ram_size=20K \
+ -Wl,--defsym=__FLASH_SIZE=224K \
+ -Wl,--defsym=__RAM_SIZE=20K \
diff --git a/hw/bsp/ch32v20x/core_riscv.h b/hw/bsp/ch32v20x/core_riscv.h
deleted file mode 100644
index be1b52a6c..000000000
--- a/hw/bsp/ch32v20x/core_riscv.h
+++ /dev/null
@@ -1,572 +0,0 @@
-/********************************** (C) COPYRIGHT *******************************
- * File Name : core_riscv.h
- * Author : WCH
- * Version : V1.0.0
- * Date : 2021/06/06
- * Description : RISC-V Core Peripheral Access Layer Header File for CH32V20x
-*********************************************************************************
-* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
-* Attention: This software (modified or not) and binary are used for
-* microcontroller manufactured by Nanjing Qinheng Microelectronics.
-*******************************************************************************/
-#ifndef __CORE_RISCV_H__
-#define __CORE_RISCV_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* IO definitions */
-#ifdef __cplusplus
- #define __I volatile /* defines 'read only' permissions */
-#else
- #define __I volatile const /* defines 'read only' permissions */
-#endif
-#define __O volatile /* defines 'write only' permissions */
-#define __IO volatile /* defines 'read / write' permissions */
-
-/* Standard Peripheral Library old types (maintained for legacy purpose) */
-typedef __I uint64_t vuc64; /* Read Only */
-typedef __I uint32_t vuc32; /* Read Only */
-typedef __I uint16_t vuc16; /* Read Only */
-typedef __I uint8_t vuc8; /* Read Only */
-
-typedef const uint64_t uc64; /* Read Only */
-typedef const uint32_t uc32; /* Read Only */
-typedef const uint16_t uc16; /* Read Only */
-typedef const uint8_t uc8; /* Read Only */
-
-typedef __I int64_t vsc64; /* Read Only */
-typedef __I int32_t vsc32; /* Read Only */
-typedef __I int16_t vsc16; /* Read Only */
-typedef __I int8_t vsc8; /* Read Only */
-
-typedef const int64_t sc64; /* Read Only */
-typedef const int32_t sc32; /* Read Only */
-typedef const int16_t sc16; /* Read Only */
-typedef const int8_t sc8; /* Read Only */
-
-typedef __IO uint64_t vu64;
-typedef __IO uint32_t vu32;
-typedef __IO uint16_t vu16;
-typedef __IO uint8_t vu8;
-
-typedef uint64_t u64;
-typedef uint32_t u32;
-typedef uint16_t u16;
-typedef uint8_t u8;
-
-typedef __IO int64_t vs64;
-typedef __IO int32_t vs32;
-typedef __IO int16_t vs16;
-typedef __IO int8_t vs8;
-
-typedef int64_t s64;
-typedef int32_t s32;
-typedef int16_t s16;
-typedef int8_t s8;
-
-typedef enum {NoREADY = 0, READY = !NoREADY} ErrorStatus;
-
-typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
-
-typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
-
-#define RV_STATIC_INLINE static inline
-
-/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */
-typedef struct{
- __I uint32_t ISR[8];
- __I uint32_t IPR[8];
- __IO uint32_t ITHRESDR;
- __IO uint32_t RESERVED;
- __IO uint32_t CFGR;
- __I uint32_t GISR;
- __IO uint8_t VTFIDR[4];
- uint8_t RESERVED0[12];
- __IO uint32_t VTFADDR[4];
- uint8_t RESERVED1[0x90];
- __O uint32_t IENR[8];
- uint8_t RESERVED2[0x60];
- __O uint32_t IRER[8];
- uint8_t RESERVED3[0x60];
- __O uint32_t IPSR[8];
- uint8_t RESERVED4[0x60];
- __O uint32_t IPRR[8];
- uint8_t RESERVED5[0x60];
- __IO uint32_t IACTR[8];
- uint8_t RESERVED6[0xE0];
- __IO uint8_t IPRIOR[256];
- uint8_t RESERVED7[0x810];
- __IO uint32_t SCTLR;
-}PFIC_Type;
-
-/* memory mapped structure for SysTick */
-typedef struct
-{
- __IO uint32_t CTLR;
- __IO uint32_t SR;
- __IO uint64_t CNT;
- __IO uint64_t CMP;
-}SysTick_Type;
-
-#define PFIC ((PFIC_Type *) 0xE000E000 )
-#define NVIC PFIC
-#define NVIC_KEY1 ((uint32_t)0xFA050000)
-#define NVIC_KEY2 ((uint32_t)0xBCAF0000)
-#define NVIC_KEY3 ((uint32_t)0xBEEF0000)
-
-#define SysTick ((SysTick_Type *) 0xE000F000)
-
-/*********************************************************************
- * @fn __enable_irq
- *
- * @brief Enable Global Interrupt
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __enable_irq(void)
-{
- __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) );
-}
-
-/*********************************************************************
- * @fn __disable_irq
- *
- * @brief Disable Global Interrupt
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __disable_irq(void)
-{
- __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) );
-}
-
-/*********************************************************************
- * @fn __NOP
- *
- * @brief nop
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __NOP(void)
-{
- __asm volatile ("nop");
-}
-
-/*********************************************************************
- * @fn NVIC_EnableIRQ
- *
- * @brief Disable Interrupt
- *
- * @param IRQn - Interrupt Numbers
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
-{
- NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_DisableIRQ
- *
- * @brief Disable Interrupt
- *
- * @param IRQn - Interrupt Numbers
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
-{
- NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_GetStatusIRQ
- *
- * @brief Get Interrupt Enable State
- *
- * @param IRQn - Interrupt Numbers
- *
- * @return 1 - Interrupt Pending Enable
- * 0 - Interrupt Pending Disable
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn)
-{
- return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
-}
-
-/*********************************************************************
- * @fn NVIC_GetPendingIRQ
- *
- * @brief Get Interrupt Pending State
- *
- * @param IRQn - Interrupt Numbers
- *
- * @return 1 - Interrupt Pending Enable
- * 0 - Interrupt Pending Disable
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
-{
- return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
-}
-
-/*********************************************************************
- * @fn NVIC_SetPendingIRQ
- *
- * @brief Set Interrupt Pending
- *
- * @param IRQn - Interrupt Numbers
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
-{
- NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_ClearPendingIRQ
- *
- * @brief Clear Interrupt Pending
- *
- * @param IRQn - Interrupt Numbers
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
-{
- NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_GetActive
- *
- * @brief Get Interrupt Active State
- *
- * @param IRQn - Interrupt Numbers
- *
- * @return 1 - Interrupt Active
- * 0 - Interrupt No Active
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
-{
- return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
-}
-
-/*********************************************************************
- * @fn NVIC_SetPriority
- *
- * @brief Set Interrupt Priority
- *
- * @param IRQn - Interrupt Numbers
- * priority - bit7 - Pre-emption Priority
- * bit[6:5] - Subpriority
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority)
-{
- NVIC->IPRIOR[(uint32_t)(IRQn)] = priority;
-}
-
-/*********************************************************************
- * @fn __WFI
- *
- * @brief Wait for Interrupt
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void)
-{
- NVIC->SCTLR &= ~(1<<3); // wfi
- asm volatile ("wfi");
-}
-
-/*********************************************************************
- * @fn _SEV
- *
- * @brief Set Event
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _SEV(void)
-{
- uint32_t t;
-
- t = NVIC->SCTLR;
- NVIC->SCTLR |= (1<<3)|(1<<5);
- NVIC->SCTLR = (NVIC->SCTLR & ~(1<<5)) | ( t & (1<<5));
-}
-
-/*********************************************************************
- * @fn _WFE
- *
- * @brief Wait for Events
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _WFE(void)
-{
- NVIC->SCTLR |= (1<<3);
- asm volatile ("wfi");
-}
-
-/*********************************************************************
- * @fn __WFE
- *
- * @brief Wait for Events
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void)
-{
- _SEV();
- _WFE();
- _WFE();
-}
-
-/*********************************************************************
- * @fn SetVTFIRQ
- *
- * @brief Set VTF Interrupt
- *
- * @param addr - VTF interrupt service function base address.
- * IRQn - Interrupt Numbers
- * num - VTF Interrupt Numbers
- * NewState - DISABLE or ENABLE
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){
- if(num > 3) return ;
-
- if (NewState != DISABLE)
- {
- NVIC->VTFIDR[num] = IRQn;
- NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1);
- }
- else{
- NVIC->VTFIDR[num] = IRQn;
- NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1));
- }
-}
-
-/*********************************************************************
- * @fn NVIC_SystemReset
- *
- * @brief Initiate a system reset request
- *
- * @return none
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SystemReset(void)
-{
- NVIC->CFGR = NVIC_KEY3|(1<<7);
-}
-
-/*********************************************************************
- * @fn __AMOADD_W
- *
- * @brief Atomic Add with 32bit value
- * Atomically ADD 32bit value with value in memory using amoadd.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be ADDed
- *
- * @return return memory value + add value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOADD_W(volatile int32_t *addr, int32_t value)
-{
- int32_t result;
-
- __asm volatile ("amoadd.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/*********************************************************************
- * @fn __AMOAND_W
- *
- * @brief Atomic And with 32bit value
- * Atomically AND 32bit value with value in memory using amoand.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be ANDed
- *
- * @return return memory value & and value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOAND_W(volatile int32_t *addr, int32_t value)
-{
- int32_t result;
-
- __asm volatile ("amoand.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/*********************************************************************
- * @fn __AMOMAX_W
- *
- * @brief Atomic signed MAX with 32bit value
- * Atomically signed max compare 32bit value with value in memory using amomax.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be compared
- *
- * @return the bigger value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMAX_W(volatile int32_t *addr, int32_t value)
-{
- int32_t result;
-
- __asm volatile ("amomax.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/*********************************************************************
- * @fn __AMOMAXU_W
- *
- * @brief Atomic unsigned MAX with 32bit value
- * Atomically unsigned max compare 32bit value with value in memory using amomaxu.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be compared
- *
- * @return return the bigger value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMAXU_W(volatile uint32_t *addr, uint32_t value)
-{
- uint32_t result;
-
- __asm volatile ("amomaxu.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/*********************************************************************
- * @fn __AMOMIN_W
- *
- * @brief Atomic signed MIN with 32bit value
- * Atomically signed min compare 32bit value with value in memory using amomin.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be compared
- *
- * @return the smaller value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMIN_W(volatile int32_t *addr, int32_t value)
-{
- int32_t result;
-
- __asm volatile ("amomin.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/*********************************************************************
- * @fn __AMOMINU_W
- *
- * @brief Atomic unsigned MIN with 32bit value
- * Atomically unsigned min compare 32bit value with value in memory using amominu.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be compared
- *
- * @return the smaller value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMINU_W(volatile uint32_t *addr, uint32_t value)
-{
- uint32_t result;
-
- __asm volatile ("amominu.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/*********************************************************************
- * @fn __AMOOR_W
- *
- * @brief Atomic OR with 32bit value
- * Atomically OR 32bit value with value in memory using amoor.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be ORed
- *
- * @return return memory value | and value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOOR_W(volatile int32_t *addr, int32_t value)
-{
- int32_t result;
-
- __asm volatile ("amoor.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/*********************************************************************
- * @fn __AMOSWAP_W
- *
- * @brief Atomically swap new 32bit value into memory using amoswap.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * newval - New value to be stored into the address
- *
- * @return return the original value in memory
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOSWAP_W(volatile uint32_t *addr, uint32_t newval)
-{
- uint32_t result;
-
- __asm volatile ("amoswap.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(newval) : "memory");
- return result;
-}
-
-/*********************************************************************
- * @fn __AMOXOR_W
- *
- * @brief Atomic XOR with 32bit value
- * Atomically XOR 32bit value with value in memory using amoxor.d.
- *
- * @param addr - Address pointer to data, address need to be 4byte aligned
- * value - value to be XORed
- *
- * @return return memory value ^ and value
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOXOR_W(volatile int32_t *addr, int32_t value)
-{
- int32_t result;
-
- __asm volatile ("amoxor.w %0, %2, %1" : \
- "=r"(result), "+A"(*addr) : "r"(value) : "memory");
- return *addr;
-}
-
-/* Core_Exported_Functions */
-extern uint32_t __get_MSTATUS(void);
-extern void __set_MSTATUS(uint32_t value);
-extern uint32_t __get_MISA(void);
-extern void __set_MISA(uint32_t value);
-extern uint32_t __get_MTVEC(void);
-extern void __set_MTVEC(uint32_t value);
-extern uint32_t __get_MSCRATCH(void);
-extern void __set_MSCRATCH(uint32_t value);
-extern uint32_t __get_MEPC(void);
-extern void __set_MEPC(uint32_t value);
-extern uint32_t __get_MCAUSE(void);
-extern void __set_MCAUSE(uint32_t value);
-extern uint32_t __get_MTVAL(void);
-extern void __set_MTVAL(uint32_t value);
-extern uint32_t __get_MVENDORID(void);
-extern uint32_t __get_MARCHID(void);
-extern uint32_t __get_MIMPID(void);
-extern uint32_t __get_MHARTID(void);
-extern uint32_t __get_SP(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c
index be654e543..542d4b5db 100644
--- a/hw/bsp/ch32v20x/family.c
+++ b/hw/bsp/ch32v20x/family.c
@@ -1,6 +1,18 @@
#include
+
+// https://github.com/openwch/ch32v307/pull/90
+// https://github.com/openwch/ch32v20x/pull/12
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+
#include "ch32v20x.h"
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#include "bsp/board_api.h"
#include "board.h"
@@ -50,7 +62,6 @@ void USBWakeUp_IRQHandler(void) {
#if CFG_TUSB_OS == OPT_OS_NONE
-
volatile uint32_t system_ticks = 0;
__attribute__((interrupt))
@@ -72,7 +83,6 @@ uint32_t SysTick_Config(uint32_t ticks) {
uint32_t board_millis(void) {
return system_ticks;
}
-
#endif
void board_init(void) {
@@ -84,28 +94,17 @@ void board_init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- uint8_t usb_div;
- switch (SystemCoreClock) {
- case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break;
- case 96000000: usb_div = RCC_USBCLKSource_PLLCLK_Div2; break;
- case 144000000: usb_div = RCC_USBCLKSource_PLLCLK_Div3; break;
- default: TU_ASSERT(0,); break;
- }
- RCC_USBCLKConfig(usb_div);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); // FSDEV
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); // USB FS
-
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = LED_PIN,
.GPIO_Mode = GPIO_Mode_Out_OD,
- .GPIO_Speed = GPIO_Speed_50MHz,
+ .GPIO_Speed = GPIO_Speed_10MHz,
};
GPIO_Init(LED_PORT, &GPIO_InitStructure);
- // UART TX is PA9
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
+#ifdef UART_DEV
+ UART_CLOCK_EN();
GPIO_InitTypeDef usart_init = {
- .GPIO_Pin = GPIO_Pin_9,
+ .GPIO_Pin = UART_TX_PIN,
.GPIO_Speed = GPIO_Speed_50MHz,
.GPIO_Mode = GPIO_Mode_AF_PP,
};
@@ -119,15 +118,55 @@ void board_init(void) {
.USART_Mode = USART_Mode_Tx,
.USART_HardwareFlowControl = USART_HardwareFlowControl_None,
};
- USART_Init(USART1, &usart);
- USART_Cmd(USART1, ENABLE);
+ USART_Init(UART_DEV, &usart);
+ USART_Cmd(UART_DEV, ENABLE);
+#endif
+
+ // USB init
+ uint8_t usb_div;
+ switch (SystemCoreClock) {
+ case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break;
+ case 96000000: usb_div = RCC_USBCLKSource_PLLCLK_Div2; break;
+ case 144000000: usb_div = RCC_USBCLKSource_PLLCLK_Div3; break;
+ default: TU_ASSERT(0,); break;
+ }
+ RCC_USBCLKConfig(usb_div);
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); // FSDEV
+ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); // USB FS
__enable_irq();
- board_delay(2);
+}
+
+void board_reset_to_bootloader(void) {
+// board_led_write(true);
+//
+// __disable_irq();
+//
+// #if CFG_TUD_ENABLED
+// tud_deinit(0);
+// RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB, ENABLE);
+// RCC_APB1PeriphResetCmd(RCC_APB1Periph_USB, DISABLE);
+// #endif
+//
+// SysTick->CTLR = 0;
+// for (int i = WWDG_IRQn; i< DMA1_Channel8_IRQn; i++) {
+// NVIC_DisableIRQ(i);
+// }
+//
+// __enable_irq();
+//
+// // define function pointer to BOOT ROM address
+// void (*bootloader_entry)(void) = (void (*)(void))0x1FFF8000;
+//
+// bootloader_entry();
+//
+// board_led_write(false);
+
+ // while(1) { }
}
void board_led_write(bool state) {
- GPIO_WriteBit(LED_PORT, LED_PIN, state);
+ GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
}
uint32_t board_button_read(void) {
@@ -141,11 +180,19 @@ int board_uart_read(uint8_t *buf, int len) {
}
int board_uart_write(void const *buf, int len) {
+#ifdef UART_DEV
const char *bufc = (const char *) buf;
for (int i = 0; i < len; i++) {
- while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
- USART_SendData(USART1, *bufc++);
+ while (USART_GetFlagStatus(UART_DEV, USART_FLAG_TC) == RESET);
+ USART_SendData(UART_DEV, *bufc++);
}
+#else
+ (void) buf; (void) len;
+#endif
return len;
}
+
+//--------------------------------------------------------------------
+// Neopixel
+//--------------------------------------------------------------------
diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake
index 3fb1c0e79..380ef190d 100644
--- a/hw/bsp/ch32v20x/family.cmake
+++ b/hw/bsp/ch32v20x/family.cmake
@@ -1,5 +1,6 @@
include_guard()
+set(UF2_FAMILY_ID 0x699b62ec)
set(CH32_FAMILY ch32v20x)
set(SDK_DIR ${TOP}/hw/mcu/wch/${CH32_FAMILY})
set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC)
@@ -40,6 +41,7 @@ function(add_board_target BOARD_TARGET)
add_library(${BOARD_TARGET} STATIC
${SDK_SRC_DIR}/Core/core_riscv.c
+ ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_flash.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c
${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c
@@ -48,6 +50,7 @@ function(add_board_target BOARD_TARGET)
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${BOARD_TARGET} PUBLIC
+ ${SDK_SRC_DIR}/Core
${SDK_SRC_DIR}/Peripheral/inc
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
)
@@ -69,19 +72,25 @@ function(add_board_target BOARD_TARGET)
update_board(${BOARD_TARGET})
+ if (LD_FLASH_SIZE STREQUAL 224K)
+ target_compile_definitions(${BOARD_TARGET} PUBLIC
+ CH32_FLASH_ENHANCE_READ_MODE=1
+ )
+ endif()
+
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(${BOARD_TARGET} PUBLIC
-mcmodel=medany
)
target_link_options(${BOARD_TARGET} PUBLIC
- "LINKER:--script=${LD_FILE_GNU}"
- -Wl,--defsym=__flash_size=${LD_FLASH_SIZE}
- -Wl,--defsym=__ram_size=${LD_RAM_SIZE}
-nostartfiles
--specs=nosys.specs --specs=nano.specs
+ -Wl,--defsym=__FLASH_SIZE=${LD_FLASH_SIZE}
+ -Wl,--defsym=__RAM_SIZE=${LD_RAM_SIZE}
+ "LINKER:--script=${LD_FILE_GNU}"
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
- message(FATAL_ERROR "Clang is not supported for MSP432E4")
+ message(FATAL_ERROR "Clang is not supported for CH32v")
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
target_link_options(${BOARD_TARGET} PUBLIC
"LINKER:--config=${LD_FILE_IAR}"
@@ -128,4 +137,8 @@ function(family_configure_example TARGET RTOS)
# Flashing
family_add_bin_hex(${TARGET})
family_flash_openocd_wch(${TARGET})
+ family_flash_wlink_rs(${TARGET})
+
+ #family_add_uf2(${TARGET} ${UF2_FAMILY_ID})
+ #family_flash_uf2(${TARGET} ${UF2_FAMILY_ID})
endfunction()
diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk
index 49d4d2feb..08761dc0d 100644
--- a/hw/bsp/ch32v20x/family.mk
+++ b/hw/bsp/ch32v20x/family.mk
@@ -24,6 +24,9 @@ CFLAGS += \
-DCH32V20x_${MCU_VARIANT} \
-DCFG_TUSB_MCU=OPT_MCU_CH32V20X
+# https://github.com/openwch/ch32v20x/pull/12
+CFLAGS += -Wno-error=strict-prototypes
+
ifeq ($(PORT),0)
$(info "Using FSDEV driver")
CFLAGS += -DCFG_TUD_WCH_USBIP_FSDEV=1
@@ -42,18 +45,20 @@ SRC_C += \
src/portable/wch/dcd_ch32_usbfs.c \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_gpio.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_misc.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_rcc.c \
- $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_usart.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \
+ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \
-SRC_S += $(SDK_SRC_DIR)/Startup/startup_ch32v20x_${MCU_VARIANT}.S
+SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S
INC += \
$(TOP)/$(BOARD_PATH) \
+ $(TOP)/$(SDK_SRC_DIR)/Core \
$(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V
OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg
-flash: flash-openocd-wch
+flash: flash-wlink-rs
+#flash: flash-openocd-wch
diff --git a/hw/bsp/ch32v20x/linker/ch32v20x.ld b/hw/bsp/ch32v20x/linker/ch32v20x.ld
index cd5c8dc17..f84808b0d 100644
--- a/hw/bsp/ch32v20x/linker/ch32v20x.ld
+++ b/hw/bsp/ch32v20x/linker/ch32v20x.ld
@@ -1,17 +1,16 @@
/* Define default values if not already defined */
-__FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K;
-__RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K;
+__flash_size = DEFINED(__FLASH_SIZE) ? __FLASH_SIZE : 64K;
+__ram_size = DEFINED(__RAM_SIZE) ? __RAM_SIZE : 20K;
+__stack_size = DEFINED(__STACK_SIZE) ? __STACK_SIZE : 2048;
MEMORY
{
- FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE
- RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __flash_size
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __ram_size
}
ENTRY( _start )
-__stack_size = 2048;
-
PROVIDE( _stack_size = __stack_size );
SECTIONS
diff --git a/hw/bsp/ch32v20x/system_ch32v20x.c b/hw/bsp/ch32v20x/system_ch32v20x.c
index bdc0d498f..d32ee8d17 100644
--- a/hw/bsp/ch32v20x/system_ch32v20x.c
+++ b/hw/bsp/ch32v20x/system_ch32v20x.c
@@ -19,12 +19,12 @@
* If none of the define below is enabled, the HSI is used as System clock source.
*/
//#define SYSCLK_FREQ_HSE HSE_VALUE
-//#define SYSCLK_FREQ_48MHz_HSE 48000000
+// #define SYSCLK_FREQ_48MHz_HSE 48000000
//#define SYSCLK_FREQ_56MHz_HSE 56000000
-//#define SYSCLK_FREQ_72MHz_HSE 72000000
+// #define SYSCLK_FREQ_72MHz_HSE 72000000
// #define SYSCLK_FREQ_96MHz_HSE 96000000
//#define SYSCLK_FREQ_120MHz_HSE 120000000
-#define SYSCLK_FREQ_144MHz_HSE 144000000
+//#define SYSCLK_FREQ_144MHz_HSE 144000000
//#define SYSCLK_FREQ_HSI HSI_VALUE
//#define SYSCLK_FREQ_48MHz_HSI 48000000
//#define SYSCLK_FREQ_56MHz_HSI 56000000
@@ -109,6 +109,16 @@ static void SetSysClockTo144_HSI( void );
*/
void SystemInit (void)
{
+ // Enable Flash enhance read mode for full 224KB
+#if defined(CH32_FLASH_ENHANCE_READ_MODE) && CH32_FLASH_ENHANCE_READ_MODE == 1
+ FLASH->KEYR = 0x45670123; // FLASH_Unlock_Fast();
+ FLASH->KEYR = 0xCDEF89AB;
+
+ FLASH->CTLR |= (1 << 24); // Enhanced Read Mode
+
+ FLASH->CTLR |= (1 << 15); // FLASH_Lock_Fast();
+#endif
+
RCC->CTLR |= (uint32_t)0x00000001;
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
diff --git a/hw/bsp/ch32v307/core_riscv.h b/hw/bsp/ch32v307/core_riscv.h
deleted file mode 100644
index a7ce10a00..000000000
--- a/hw/bsp/ch32v307/core_riscv.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/********************************** (C) COPYRIGHT *******************************
-* File Name : core_riscv.h
-* Author : WCH
-* Version : V1.0.0
-* Date : 2021/06/06
-* Description : RISC-V Core Peripheral Access Layer Header File for CH32V30x
-* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
-* SPDX-License-Identifier: Apache-2.0
-*******************************************************************************/
-#ifndef __CORE_RISCV_H__
-#define __CORE_RISCV_H__
-
-/* IO definitions */
-#ifdef __cplusplus
- #define __I volatile /* defines 'read only' permissions */
-#else
- #define __I volatile const /* defines 'read only' permissions */
-#endif
-#define __O volatile /* defines 'write only' permissions */
-#define __IO volatile /* defines 'read / write' permissions */
-
-/* Standard Peripheral Library old types (maintained for legacy purpose) */
-typedef __I uint64_t vuc64; /* Read Only */
-typedef __I uint32_t vuc32; /* Read Only */
-typedef __I uint16_t vuc16; /* Read Only */
-typedef __I uint8_t vuc8; /* Read Only */
-
-typedef const uint64_t uc64; /* Read Only */
-typedef const uint32_t uc32; /* Read Only */
-typedef const uint16_t uc16; /* Read Only */
-typedef const uint8_t uc8; /* Read Only */
-
-typedef __I int64_t vsc64; /* Read Only */
-typedef __I int32_t vsc32; /* Read Only */
-typedef __I int16_t vsc16; /* Read Only */
-typedef __I int8_t vsc8; /* Read Only */
-
-typedef const int64_t sc64; /* Read Only */
-typedef const int32_t sc32; /* Read Only */
-typedef const int16_t sc16; /* Read Only */
-typedef const int8_t sc8; /* Read Only */
-
-typedef __IO uint64_t vu64;
-typedef __IO uint32_t vu32;
-typedef __IO uint16_t vu16;
-typedef __IO uint8_t vu8;
-
-typedef uint64_t u64;
-typedef uint32_t u32;
-typedef uint16_t u16;
-typedef uint8_t u8;
-
-typedef __IO int64_t vs64;
-typedef __IO int32_t vs32;
-typedef __IO int16_t vs16;
-typedef __IO int8_t vs8;
-
-typedef int64_t s64;
-typedef int32_t s32;
-typedef int16_t s16;
-typedef int8_t s8;
-
-typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;
-
-typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
-
-typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
-
-#define RV_STATIC_INLINE static inline
-
-/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */
-typedef struct{
- __I uint32_t ISR[8];
- __I uint32_t IPR[8];
- __IO uint32_t ITHRESDR;
- __IO uint32_t RESERVED;
- __IO uint32_t CFGR;
- __I uint32_t GISR;
- uint8_t VTFIDR[4];
- uint8_t RESERVED0[12];
- __IO uint32_t VTFADDR[4];
- uint8_t RESERVED1[0x90];
- __O uint32_t IENR[8];
- uint8_t RESERVED2[0x60];
- __O uint32_t IRER[8];
- uint8_t RESERVED3[0x60];
- __O uint32_t IPSR[8];
- uint8_t RESERVED4[0x60];
- __O uint32_t IPRR[8];
- uint8_t RESERVED5[0x60];
- __IO uint32_t IACTR[8];
- uint8_t RESERVED6[0xE0];
- __IO uint8_t IPRIOR[256];
- uint8_t RESERVED7[0x810];
- __IO uint32_t SCTLR;
-}PFIC_Type;
-
-/* memory mapped structure for SysTick */
-typedef struct
-{
- __IO u32 CTLR;
- __IO u32 SR;
- __IO u64 CNT;
- __IO u64 CMP;
-}SysTick_Type;
-
-
-#define PFIC ((PFIC_Type *) 0xE000E000 )
-#define NVIC PFIC
-#define NVIC_KEY1 ((uint32_t)0xFA050000)
-#define NVIC_KEY2 ((uint32_t)0xBCAF0000)
-#define NVIC_KEY3 ((uint32_t)0xBEEF0000)
-
-#define SysTick ((SysTick_Type *) 0xE000F000)
-
-
-/*********************************************************************
- * @fn __enable_irq
- *
- * @brief Enable Global Interrupt
- *
- * @return none
- */
-RV_STATIC_INLINE void __enable_irq(void)
-{
- __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) );
-}
-
-/*********************************************************************
- * @fn __disable_irq
- *
- * @brief Disable Global Interrupt
- *
- * @return none
- */
-RV_STATIC_INLINE void __disable_irq(void)
-{
- __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) );
-}
-
-/*********************************************************************
- * @fn __NOP
- *
- * @brief nop
- *
- * @return none
- */
-RV_STATIC_INLINE void __NOP(void)
-{
- __asm volatile ("nop");
-}
-
-/*********************************************************************
- * @fn NVIC_EnableIRQ
- *
- * @brief Enable Interrupt
- *
- * @param IRQn: Interrupt Numbers
- *
- * @return none
- */
-RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
-{
- NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_DisableIRQ
- *
- * @brief Disable Interrupt
- *
- * @param IRQn: Interrupt Numbers
- *
- * @return none
- */
-RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
-{
- NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_GetStatusIRQ
- *
- * @brief Get Interrupt Enable State
- *
- * @param IRQn: Interrupt Numbers
- *
- * @return 1 - Interrupt Enable
- * 0 - Interrupt Disable
- */
-RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn)
-{
- return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
-}
-
-/*********************************************************************
- * @fn NVIC_GetPendingIRQ
- *
- * @brief Get Interrupt Pending State
- *
- * @param IRQn: Interrupt Numbers
- *
- * @return 1 - Interrupt Pending Enable
- * 0 - Interrupt Pending Disable
- */
-RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
-{
- return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
-}
-
-/*********************************************************************
- * @fn NVIC_SetPendingIRQ
- *
- * @brief Set Interrupt Pending
- *
- * @param IRQn: Interrupt Numbers
- *
- * @return None
- */
-RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
-{
- NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_ClearPendingIRQ
- *
- * @brief Clear Interrupt Pending
- *
- * @param IRQn: Interrupt Numbers
- *
- * @return None
- */
-RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
-{
- NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));
-}
-
-/*********************************************************************
- * @fn NVIC_GetActive
- *
- * @brief Get Interrupt Active State
- *
- * @param IRQn: Interrupt Numbers
- *
- * @return 1 - Interrupt Active
- * 0 - Interrupt No Active
- */
-RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
-{
- return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0));
-}
-
-/*********************************************************************
- * @fn NVIC_SetPriority
- *
- * @brief Set Interrupt Priority
- *
- * @param IRQn - Interrupt Numbers
- * priority -
- * bit7 - pre-emption priority
- * bit6~bit4 - subpriority
- * @return None
- */
-RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority)
-{
- NVIC->IPRIOR[(uint32_t)(IRQn)] = priority;
-}
-
-/*********************************************************************
- * @fn __WFI
- *
- * @brief Wait for Interrupt
- *
- * @return None
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void)
-{
- NVIC->SCTLR &= ~(1<<3); // wfi
- asm volatile ("wfi");
-}
-
-/*********************************************************************
- * @fn __WFE
- *
- * @brief Wait for Events
- *
- * @return None
- */
-__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void)
-{
- uint32_t t;
-
- t = NVIC->SCTLR;
- NVIC->SCTLR |= (1<<3)|(1<<5); // (wfi->wfe)+(__sev)
- NVIC->SCTLR = (NVIC->SCTLR & ~(1<<5)) | ( t & (1<<5));
- asm volatile ("wfi");
- asm volatile ("wfi");
-}
-
-/*********************************************************************
- * @fn SetVTFIRQ
- *
- * @brief Set VTF Interrupt
- *
- * @param add - VTF interrupt service function base address.
- * IRQn -Interrupt Numbers
- * num - VTF Interrupt Numbers
- * NewState - DISABLE or ENABLE
- * @return None
- */
-RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){
- if(num > 3) return ;
-
- if (NewState != DISABLE)
- {
- NVIC->VTFIDR[num] = IRQn;
- NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1);
- }
- else{
- NVIC->VTFIDR[num] = IRQn;
- NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1));
- }
-}
-
-/*********************************************************************
- * @fn NVIC_SystemReset
- *
- * @brief Initiate a system reset request
- *
- * @return None
- */
-RV_STATIC_INLINE void NVIC_SystemReset(void)
-{
- NVIC->CFGR = NVIC_KEY3|(1<<7);
-}
-
-
-/* Core_Exported_Functions */
-extern uint32_t __get_FFLAGS(void);
-extern void __set_FFLAGS(uint32_t value);
-extern uint32_t __get_FRM(void);
-extern void __set_FRM(uint32_t value);
-extern uint32_t __get_FCSR(void);
-extern void __set_FCSR(uint32_t value);
-extern uint32_t __get_MSTATUS(void);
-extern void __set_MSTATUS(uint32_t value);
-extern uint32_t __get_MISA(void);
-extern void __set_MISA(uint32_t value);
-extern uint32_t __get_MIE(void);
-extern void __set_MIE(uint32_t value);
-extern uint32_t __get_MTVEC(void);
-extern void __set_MTVEC(uint32_t value);
-extern uint32_t __get_MSCRATCH(void);
-extern void __set_MSCRATCH(uint32_t value);
-extern uint32_t __get_MEPC(void);
-extern void __set_MEPC(uint32_t value);
-extern uint32_t __get_MCAUSE(void);
-extern void __set_MCAUSE(uint32_t value);
-extern uint32_t __get_MTVAL(void);
-extern void __set_MTVAL(uint32_t value);
-extern uint32_t __get_MIP(void);
-extern void __set_MIP(uint32_t value);
-extern uint32_t __get_MCYCLE(void);
-extern void __set_MCYCLE(uint32_t value);
-extern uint32_t __get_MCYCLEH(void);
-extern void __set_MCYCLEH(uint32_t value);
-extern uint32_t __get_MINSTRET(void);
-extern void __set_MINSTRET(uint32_t value);
-extern uint32_t __get_MINSTRETH(void);
-extern void __set_MINSTRETH(uint32_t value);
-extern uint32_t __get_MVENDORID(void);
-extern uint32_t __get_MARCHID(void);
-extern uint32_t __get_MIMPID(void);
-extern uint32_t __get_MHARTID(void);
-extern uint32_t __get_SP(void);
-
-
-#endif
diff --git a/hw/bsp/ch32v307/debug_uart.c b/hw/bsp/ch32v307/debug_uart.c
index fbabeeadc..2fd3a9d64 100644
--- a/hw/bsp/ch32v307/debug_uart.c
+++ b/hw/bsp/ch32v307/debug_uart.c
@@ -25,8 +25,17 @@
*/
#include "debug_uart.h"
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+
#include
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
#define UART_RINGBUFFER_SIZE_TX 128
#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)
diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c
index 0846b10a9..adf2dbea5 100644
--- a/hw/bsp/ch32v307/family.c
+++ b/hw/bsp/ch32v307/family.c
@@ -25,9 +25,22 @@
*/
#include "stdio.h"
+
+// https://github.com/openwch/ch32v307/pull/90
+// https://github.com/openwch/ch32v20x/pull/12
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+
#include "debug_uart.h"
#include "ch32v30x.h"
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#include "bsp/board_api.h"
#include "board.h"
diff --git a/hw/bsp/ch32v307/family.cmake b/hw/bsp/ch32v307/family.cmake
index af26bfc31..d603af62d 100644
--- a/hw/bsp/ch32v307/family.cmake
+++ b/hw/bsp/ch32v307/family.cmake
@@ -49,6 +49,7 @@ function(add_board_target BOARD_TARGET)
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${BOARD_TARGET} PUBLIC
+ ${SDK_SRC_DIR}/Core
${SDK_SRC_DIR}/Peripheral/inc
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
)
diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk
index 30a070a9b..bf2732106 100644
--- a/hw/bsp/ch32v307/family.mk
+++ b/hw/bsp/ch32v307/family.mk
@@ -25,6 +25,9 @@ CFLAGS += \
-fsigned-char \
-DCFG_TUSB_MCU=OPT_MCU_CH32V307 \
+# https://github.com/openwch/ch32v307/pull/90
+CFLAGS += -Wno-error=strict-prototypes
+
ifeq ($(SPEED),high)
$(info "Using USBHS driver for HighSpeed mode")
CFLAGS += -DCFG_TUD_WCH_USBIP_USBHS=1
@@ -51,6 +54,7 @@ SRC_S += \
INC += \
$(TOP)/$(BOARD_PATH) \
+ $(TOP)/$(SDK_SRC_DIR)/Core \
$(TOP)/$(SDK_SRC_DIR)/Peripheral/inc
# For freeRTOS port source
diff --git a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c b/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
deleted file mode 100644
index 667b83de3..000000000
--- a/hw/bsp/da14695_dk_usb/da14695_dk_usb.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2020 Jerzy Kasenberg
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "bsp/board_api.h"
-#include
-#include
-
-//--------------------------------------------------------------------+
-// Forward USB interrupt events to TinyUSB IRQ Handler
-//--------------------------------------------------------------------+
-void USB_IRQHandler(void)
-{
- tud_int_handler(0);
-}
-
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM
-//--------------------------------------------------------------------+
-
-#define LED_PIN 33 // P1.1
-#define LED_STATE_ON 1
-#define LED_STATE_OFF (1-LED_STATE_ON)
-
-#define BUTTON_PIN 6
-
-void UnhandledIRQ(void)
-{
- CRG_TOP->SYS_CTRL_REG = 0x80;
- __BKPT(1);
- while(1);
-}
-
-// DA146xx driver function that must be called whenever VBUS changes.
-extern void tusb_vbus_changed(bool present);
-
-void board_init(void)
-{
- // LED
- hal_gpio_init_out(LED_PIN, LED_STATE_ON);
-
- hal_gpio_init_out(1, 0);
- hal_gpio_init_out(2, 0);
- hal_gpio_init_out(3, 0);
- hal_gpio_init_out(4, 0);
- hal_gpio_init_out(5, 0);
-
- // Button
- hal_gpio_init_in(BUTTON_PIN, HAL_GPIO_PULL_DOWN);
-
- // 1ms tick timer
- SysTick_Config(SystemCoreClock / 1000);
-
-#if CFG_TUD_ENABLED
- // This board is USB powered there is no need to monitor
- // VBUS line. Notify driver that VBUS is present.
- tusb_vbus_changed(true);
-
- /* Setup USB IRQ */
- NVIC_SetPriority(USB_IRQn, 2);
- NVIC_EnableIRQ(USB_IRQn);
-
- /* Use PLL96 / 2 clock not HCLK */
- CRG_TOP->CLK_CTRL_REG &= ~CRG_TOP_CLK_CTRL_REG_USB_CLK_SRC_Msk;
-
- mcu_gpio_set_pin_function(14, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
- mcu_gpio_set_pin_function(15, MCU_GPIO_MODE_INPUT, MCU_GPIO_FUNC_USB);
-#endif
-}
-
-//--------------------------------------------------------------------+
-// Board porting API
-//--------------------------------------------------------------------+
-
-void board_led_write(bool state)
-{
- hal_gpio_write(LED_PIN, state ? LED_STATE_ON : LED_STATE_OFF);
-}
-
-uint32_t board_button_read(void)
-{
- // button is active HIGH
- return hal_gpio_read(BUTTON_PIN);
-}
-
-int board_uart_read(uint8_t* buf, int len)
-{
- (void)buf;
- (void)len;
- return 0;
-}
-
-int board_uart_write(void const * buf, int len)
-{
- (void)buf;
- (void)len;
-
- return 0;
-}
-
-#if CFG_TUSB_OS == OPT_OS_NONE
-volatile uint32_t system_ticks = 0;
-void SysTick_Handler(void)
-{
- system_ticks++;
-}
-
-uint32_t board_millis(void)
-{
- return system_ticks;
-}
-#endif
diff --git a/hw/bsp/da1469x/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/da1469x/FreeRTOSConfig/FreeRTOSConfig.h
new file mode 100644
index 000000000..4d4379a6f
--- /dev/null
+++ b/hw/bsp/da1469x/FreeRTOSConfig/FreeRTOSConfig.h
@@ -0,0 +1,150 @@
+/*
+ * FreeRTOS Kernel V10.0.0
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software. If you wish to use our Amazon
+ * FreeRTOS name, please do so in a fair use way that does not cause confusion.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+// skip if included from IAR assembler
+#ifndef __IASMARM__
+ #include "DA1469xAB.h"
+#endif
+
+/* Cortex M23/M33 port configuration. */
+#define configENABLE_MPU 0
+#define configENABLE_FPU 1
+#define configENABLE_TRUSTZONE 0
+#define configMINIMAL_SECURE_STACK_SIZE (1024)
+#define configRUN_FREERTOS_SECURE_ONLY 1
+
+#define configUSE_PREEMPTION 1
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+#define configCPU_CLOCK_HZ SystemCoreClock
+#define configTICK_RATE_HZ ( 1000 )
+#define configMAX_PRIORITIES ( 5 )
+#define configMINIMAL_STACK_SIZE ( 128 )
+#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
+#define configMAX_TASK_NAME_LEN 16
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configQUEUE_REGISTRY_SIZE 4
+#define configUSE_QUEUE_SETS 0
+#define configUSE_TIME_SLICING 0
+#define configUSE_NEWLIB_REENTRANT 0
+#define configENABLE_BACKWARD_COMPATIBILITY 1
+#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
+
+#define configSUPPORT_STATIC_ALLOCATION 1
+#define configSUPPORT_DYNAMIC_ALLOCATION 0
+
+/* Hook function related definitions. */
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 0
+#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
+#define configCHECK_FOR_STACK_OVERFLOW 2
+#define configCHECK_HANDLER_INSTALLATION 0
+
+/* Run time and task stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS 0
+#define configRECORD_STACK_HIGH_ADDRESS 1
+#define configUSE_TRACE_FACILITY 1 // legacy trace
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES 2
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
+#define configTIMER_QUEUE_LENGTH 32
+#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet 0
+#define INCLUDE_uxTaskPriorityGet 0
+#define INCLUDE_vTaskDelete 0
+#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
+#define INCLUDE_xResumeFromISR 0
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetSchedulerState 0
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 0
+#define INCLUDE_xTaskGetIdleTaskHandle 0
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
+#define INCLUDE_pcTaskGetTaskName 0
+#define INCLUDE_eTaskGetState 0
+#define INCLUDE_xEventGroupSetBitFromISR 0
+#define INCLUDE_xTimerPendFunctionCall 0
+
+/* FreeRTOS hooks to NVIC vectors */
+#define xPortPendSVHandler PendSV_Handler
+#define xPortSysTickHandler SysTick_Handler
+#define vPortSVCHandler SVC_Handler
+
+//--------------------------------------------------------------------+
+// Interrupt nesting behavior configuration.
+//--------------------------------------------------------------------+
+
+// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header
+#define configPRIO_BITS 4
+
+/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<
#include
+#define LED_STATE_OFF (1-LED_STATE_ON)
+
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
-void USB_IRQHandler(void)
-{
+void USB_IRQHandler(void) {
tud_int_handler(0);
}
-#if CFG_TUD_ENABLED
-// DA146xx driver function that must be called whenever VBUS changes
+// DA146xx driver function that must be called whenever VBUS changes.
extern void tusb_vbus_changed(bool present);
+#if defined(NEED_VBUS_MONITOR) && CFG_TUD_ENABLED
// VBUS change interrupt handler
-void VBUS_IRQHandler(void)
-{
+void VBUS_IRQHandler(void) {
bool present = (CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_VBUS_AVAILABLE_Msk) != 0;
// Clear VBUS interrupt
CRG_TOP->VBUS_IRQ_CLEAR_REG = 1;
@@ -54,22 +55,13 @@ void VBUS_IRQHandler(void)
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
-
-#define LED_PIN 33
-#define LED_STATE_ON 1
-#define LED_STATE_OFF 0
-
-#define BUTTON_PIN 6
-
-void UnhandledIRQ(void)
-{
+void UnhandledIRQ(void) {
CRG_TOP->SYS_CTRL_REG = 0x80;
__BKPT(1);
- while(1);
+ while (1);
}
-void board_init(void)
-{
+void board_init(void) {
// LED
hal_gpio_init_out(LED_PIN, LED_STATE_ON);
@@ -80,12 +72,13 @@ void board_init(void)
hal_gpio_init_out(5, 0);
// Button
- hal_gpio_init_in(BUTTON_PIN, HAL_GPIO_PULL_UP);
+ hal_gpio_init_in(BUTTON_PIN, BUTTON_STATE_ACTIVE ? HAL_GPIO_PULL_DOWN : HAL_GPIO_PULL_UP);
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
#if CFG_TUD_ENABLED
+ #ifdef NEED_VBUS_MONITOR
// Setup interrupt for both connect and disconnect
CRG_TOP->VBUS_IRQ_MASK_REG = CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_FALL_Msk |
CRG_TOP_VBUS_IRQ_MASK_REG_VBUS_IRQ_EN_RISE_Msk;
@@ -94,6 +87,10 @@ void board_init(void)
// otherwise it could go unnoticed.
NVIC_SetPendingIRQ(VBUS_IRQn);
NVIC_EnableIRQ(VBUS_IRQn);
+ #else
+ // This board is USB powered there is no need to monitor VBUS line. Notify driver that VBUS is present.
+ tusb_vbus_changed(true);
+ #endif
/* Setup USB IRQ */
NVIC_SetPriority(USB_IRQn, 2);
@@ -111,41 +108,35 @@ void board_init(void)
// Board porting API
//--------------------------------------------------------------------+
-void board_led_write(bool state)
-{
+void board_led_write(bool state) {
hal_gpio_write(LED_PIN, state ? LED_STATE_ON : LED_STATE_OFF);
}
-uint32_t board_button_read(void)
-{
- // button is active LOW
- return hal_gpio_read(BUTTON_PIN) ^ 1;
+uint32_t board_button_read(void) {
+ return BUTTON_STATE_ACTIVE == hal_gpio_read(BUTTON_PIN);
}
-int board_uart_read(uint8_t* buf, int len)
-{
- (void)buf;
- (void)len;
+int board_uart_read(uint8_t* buf, int len) {
+ (void) buf;
+ (void) len;
return 0;
}
-int board_uart_write(void const * buf, int len)
-{
- (void)buf;
- (void)len;
+int board_uart_write(void const* buf, int len) {
+ (void) buf;
+ (void) len;
return 0;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
-void SysTick_Handler(void)
-{
+
+void SysTick_Handler(void) {
system_ticks++;
}
-uint32_t board_millis(void)
-{
+uint32_t board_millis(void) {
return system_ticks;
}
#endif
diff --git a/hw/bsp/da1469x/family.cmake b/hw/bsp/da1469x/family.cmake
new file mode 100644
index 000000000..8c89141fe
--- /dev/null
+++ b/hw/bsp/da1469x/family.cmake
@@ -0,0 +1,141 @@
+include_guard()
+
+set(MCU_DIR ${TOP}/hw/mcu/dialog/da1469x)
+
+# include board specific
+include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
+
+set(CMAKE_SYSTEM_PROCESSOR cortex-m33-nodsp CACHE INTERNAL "System Processor")
+set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake)
+set(FAMILY_MCUS DA1469X CACHE INTERNAL "")
+
+#------------------------------------
+# BOARD_TARGET
+#------------------------------------
+# only need to be built ONCE for all examples
+function(add_board_target BOARD_TARGET)
+ if (TARGET ${BOARD_TARGET})
+ return()
+ endif ()
+
+ if (NOT DEFINED LD_FILE_GNU)
+ set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/da1469x.ld)
+ endif ()
+
+ if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID})
+ set(STARTUP_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gcc_startup_da1469x.S)
+ set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
+ endif ()
+
+ add_library(${BOARD_TARGET} STATIC
+ ${MCU_DIR}/src/system_da1469x.c
+ ${MCU_DIR}/src/da1469x_clock.c
+ ${MCU_DIR}/src/hal_gpio.c
+ ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
+ )
+ target_compile_options(${BOARD_TARGET} PUBLIC -mthumb-interwork)
+ target_compile_definitions(${BOARD_TARGET} PUBLIC
+ CORE_M33
+ CFG_TUD_ENDPOINT0_SIZE=8
+ )
+ target_include_directories(${BOARD_TARGET} PUBLIC
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
+ ${MCU_DIR}/include
+ ${MCU_DIR}/SDK_10.0.8.105/sdk/bsp/include
+ )
+
+ update_board(${BOARD_TARGET})
+
+ if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+ target_link_options(${BOARD_TARGET} PUBLIC
+ "LINKER:--script=${LD_FILE_GNU}"
+ -L${NRFX_DIR}/mdk
+ --specs=nosys.specs --specs=nano.specs
+ -nostartfiles
+ )
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ target_link_options(${BOARD_TARGET} PUBLIC
+ "LINKER:--script=${LD_FILE_GNU}"
+ -L${NRFX_DIR}/mdk
+ )
+ elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
+ target_link_options(${BOARD_TARGET} PUBLIC
+ "LINKER:--config=${LD_FILE_IAR}"
+ )
+ endif ()
+endfunction()
+
+
+#------------------------------------
+# Functions
+#------------------------------------
+
+function(family_flash_jlink_dialog TARGET)
+ set(JLINKEXE JLinkExe)
+ set(JLINK_IF swd)
+
+ # mkimage from sdk
+ set(MKIMAGE $ENV{HOME}/code/tinyusb-mcu-driver/dialog/SDK_10.0.8.105/binaries/mkimage)
+
+ file(GENERATE OUTPUT $/version.h
+ CONTENT "#define SW_VERSION \"v_1.0.0.1\"
+#define SW_VERSION_DATE \"2024-07-17 17:55\""
+ )
+
+ file(GENERATE OUTPUT $/${TARGET}.jlink
+ CONTENT "r
+halt
+loadfile $/${TARGET}-image.bin 0x16000000
+r
+go
+exit"
+ )
+
+ add_custom_target(${TARGET}-image
+ DEPENDS ${TARGET}
+ COMMAND ${MKIMAGE} da1469x $/${TARGET}.bin $/version.h $/${TARGET}.bin.img
+ COMMAND cp ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/product_header.dump $/${TARGET}-image.bin
+ COMMAND cat $/${TARGET}.bin.img >> $/${TARGET}-image.bin
+ )
+ add_custom_target(${TARGET}-jlink
+ DEPENDS ${TARGET}-image
+ COMMAND ${JLINKEXE} -device ${JLINK_DEVICE} -if ${JLINK_IF} -JTAGConf -1,-1 -speed auto -CommandFile $/${TARGET}.jlink
+ )
+endfunction()
+
+
+function(family_configure_example TARGET RTOS)
+ family_configure_common(${TARGET} ${RTOS})
+
+ # Board target
+ add_board_target(board_${BOARD})
+
+ #---------- Port Specific ----------
+ # These files are built for each example since it depends on example's tusb_config.h
+ target_sources(${TARGET} PUBLIC
+ # BSP
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
+ )
+ target_include_directories(${TARGET} PUBLIC
+ # family, hw, board
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD}
+ )
+
+ # Add TinyUSB target and port source
+ family_add_tinyusb(${TARGET} OPT_MCU_DA1469X ${RTOS})
+ target_sources(${TARGET}-tinyusb PUBLIC
+ ${TOP}/src/portable/dialog/da146xx/dcd_da146xx.c
+ )
+ target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD})
+
+ # Link dependencies
+ target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb)
+
+ # Flashing
+ family_add_bin_hex(${TARGET})
+ family_flash_jlink_dialog(${TARGET})
+endfunction()
diff --git a/hw/bsp/da14695_dk_usb/board.mk b/hw/bsp/da1469x/family.mk
similarity index 52%
rename from hw/bsp/da14695_dk_usb/board.mk
rename to hw/bsp/da1469x/family.mk
index 980b1a361..f35fe2cb5 100644
--- a/hw/bsp/da14695_dk_usb/board.mk
+++ b/hw/bsp/da1469x/family.mk
@@ -1,4 +1,6 @@
-MCU_FAMILY_DIR = hw/mcu/dialog/da1469x
+MCU_DIR = hw/mcu/dialog/da1469x
+
+include $(TOP)/$(BOARD_PATH)/board.mk
CFLAGS += \
-flto \
@@ -8,48 +10,52 @@ CFLAGS += \
-mcpu=cortex-m33+nodsp \
-mfloat-abi=hard \
-mfpu=fpv5-sp-d16 \
- -nostdlib \
-DCORE_M33 \
-DCFG_TUSB_MCU=OPT_MCU_DA1469X \
-DCFG_TUD_ENDPOINT0_SIZE=8\
-LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
+LDFLAGS_GCC += \
+ -nostdlib \
+ --specs=nosys.specs --specs=nano.specs
# All source paths should be relative to the top level.
-LD_FILE = hw/bsp/$(BOARD)/da1469x.ld
+LD_FILE = $(FAMILY_PATH)/linker/da1469x.ld
# While this is for da1469x chip, there is chance that da1468x chip family will also work
SRC_C += \
src/portable/dialog/da146xx/dcd_da146xx.c \
- $(MCU_FAMILY_DIR)/src/system_da1469x.c \
- $(MCU_FAMILY_DIR)/src/da1469x_clock.c \
- $(MCU_FAMILY_DIR)/src/hal_gpio.c \
+ ${MCU_DIR}/src/system_da1469x.c \
+ ${MCU_DIR}/src/da1469x_clock.c \
+ ${MCU_DIR}/src/hal_gpio.c \
-SRC_S += hw/bsp/$(BOARD)/gcc_startup_da1469x.S
+SRC_S += $(FAMILY_PATH)/gcc_startup_da1469x.S
INC += \
- $(TOP)/hw/bsp/$(BOARD) \
- $(TOP)/$(MCU_FAMILY_DIR)/include \
- $(TOP)/$(MCU_FAMILY_DIR)/SDK_10.0.8.105/sdk/bsp/include
+ $(TOP)/$(BOARD_PATH) \
+ $(TOP)/${MCU_DIR}/include \
+ $(TOP)/${MCU_DIR}/SDK_10.0.8.105/sdk/bsp/include
# For freeRTOS port source
FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure
-# For flash-jlink target
-JLINK_DEVICE = DA14695
-
# flash using jlink but with some twists
flash: flash-dialog
-flash-dialog: $(BUILD)/$(PROJECT).bin
+# SDK_BINARY_PATH is the path to the SDK binary files
+SDK_BINARY_PATH = $(HOME)/code/tinyusb-mcu-driver/dialog/SDK_10.0.8.105/binaries
+MKIMAGE = $(SDK_BINARY_PATH)/mkimage
+
+$(BUILD)/$(PROJECT)-image.bin: $(BUILD)/$(PROJECT).bin
@echo '#define SW_VERSION "v_1.0.0.1"' >$(BUILD)/version.h
- @echo '#define SW_VERSION_DATE "'`date +"%Y-%m-%d %H:%M"`'"' >>$(BUILD)/version.h
- mkimage da1469x $(BUILD)/$(PROJECT).bin $(BUILD)/version.h $^.img
- cp $(TOP)/hw/bsp/$(BOARD)/product_header.dump $(BUILD)/$(BOARD)-image.bin
- cat $^.img >> $(BUILD)/$(BOARD)-image.bin
+ @echo '#define SW_VERSION_DATE "'`date +"%Y-%m-%d %H:%M"`'"' >> $(BUILD)/version.h
+ $(MKIMAGE) da1469x $^ $(BUILD)/version.h $^.img
+ cp $(TOP)/$(FAMILY_PATH)/product_header.dump $(BUILD)/$(PROJECT)-image.bin
+ cat $^.img >> $(BUILD)/$(PROJECT)-image.bin
+
+flash-dialog: $(BUILD)/$(PROJECT)-image.bin
@echo r > $(BUILD)/$(BOARD).jlink
@echo halt >> $(BUILD)/$(BOARD).jlink
- @echo loadfile $(BUILD)/$(BOARD)-image.bin 0x16000000 >> $(BUILD)/$(BOARD).jlink
+ @echo loadfile $^ 0x16000000 >> $(BUILD)/$(BOARD).jlink
@echo r >> $(BUILD)/$(BOARD).jlink
@echo go >> $(BUILD)/$(BOARD).jlink
@echo exit >> $(BUILD)/$(BOARD).jlink
diff --git a/hw/bsp/da14695_dk_usb/gcc_startup_da1469x.S b/hw/bsp/da1469x/gcc_startup_da1469x.S
similarity index 100%
rename from hw/bsp/da14695_dk_usb/gcc_startup_da1469x.S
rename to hw/bsp/da1469x/gcc_startup_da1469x.S
diff --git a/hw/bsp/da14695_dk_usb/da1469x.ld b/hw/bsp/da1469x/linker/da1469x.ld
similarity index 100%
rename from hw/bsp/da14695_dk_usb/da1469x.ld
rename to hw/bsp/da1469x/linker/da1469x.ld
diff --git a/hw/bsp/da14695_dk_usb/product_header.dump b/hw/bsp/da1469x/product_header.dump
similarity index 100%
rename from hw/bsp/da14695_dk_usb/product_header.dump
rename to hw/bsp/da1469x/product_header.dump
diff --git a/hw/bsp/da1469x_dk_pro/board.mk b/hw/bsp/da1469x_dk_pro/board.mk
deleted file mode 100644
index 5282f93a3..000000000
--- a/hw/bsp/da1469x_dk_pro/board.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-MCU_FAMILY_DIR = hw/mcu/dialog/da1469x
-
-CFLAGS += \
- -flto \
- -mthumb \
- -mthumb-interwork \
- -mabi=aapcs \
- -mcpu=cortex-m33+nodsp \
- -mfloat-abi=hard \
- -mfpu=fpv5-sp-d16 \
- -nostdlib \
- -DCORE_M33 \
- -DCFG_TUSB_MCU=OPT_MCU_DA1469X \
- -DCFG_TUD_ENDPOINT0_SIZE=8\
-
-LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
-
-# All source paths should be relative to the top level.
-LD_FILE = hw/bsp/$(BOARD)/da1469x.ld
-
-# While this is for da1469x chip, there is chance that da1468x chip family will also work
-SRC_C += \
- src/portable/dialog/da146xx/dcd_da146xx.c \
- $(MCU_FAMILY_DIR)/src/system_da1469x.c \
- $(MCU_FAMILY_DIR)/src/da1469x_clock.c \
- $(MCU_FAMILY_DIR)/src/hal_gpio.c \
-
-SRC_S += hw/bsp/$(BOARD)/gcc_startup_da1469x.S
-
-INC += \
- $(TOP)/hw/bsp/$(BOARD) \
- $(TOP)/$(MCU_FAMILY_DIR)/include \
- $(TOP)/$(MCU_FAMILY_DIR)/SDK_10.0.8.105/sdk/bsp/include
-
-# For freeRTOS port source
-FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM33_NTZ/non_secure
-
-# For flash-jlink target
-JLINK_DEVICE = DA14699
-
-# flash using jlink but with some twists
-flash: flash-dialog
-
-flash-dialog: $(BUILD)/$(PROJECT).bin
- @echo '#define SW_VERSION "v_1.0.0.1"' >$(BUILD)/version.h
- @echo '#define SW_VERSION_DATE "'`date +"%Y-%m-%d %H:%M"`'"' >>$(BUILD)/version.h
- mkimage da1469x $(BUILD)/$(PROJECT).bin $(BUILD)/version.h $^.img
- cp $(TOP)/hw/bsp/$(BOARD)/product_header.dump $(BUILD)/$(BOARD)-image.bin
- cat $^.img >> $(BUILD)/$(BOARD)-image.bin
- @echo r > $(BUILD)/$(BOARD).jlink
- @echo halt >> $(BUILD)/$(BOARD).jlink
- @echo loadfile $(BUILD)/$(BOARD)-image.bin 0x16000000 >> $(BUILD)/$(BOARD).jlink
- @echo r >> $(BUILD)/$(BOARD).jlink
- @echo go >> $(BUILD)/$(BOARD).jlink
- @echo exit >> $(BUILD)/$(BOARD).jlink
- $(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -JTAGConf -1,-1 -speed auto -CommandFile $(BUILD)/$(BOARD).jlink
diff --git a/hw/bsp/da1469x_dk_pro/da1469x.ld b/hw/bsp/da1469x_dk_pro/da1469x.ld
deleted file mode 100644
index 8cc1d9d99..000000000
--- a/hw/bsp/da1469x_dk_pro/da1469x.ld
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-MEMORY
-{
- /*
- * Flash is remapped at 0x0 by 1st stage bootloader, but this is done with
- * an offset derived from image header thus it is safer to use remapped
- * address space at 0x0 instead of QSPI_M address space at 0x16000000.
- * Bootloader partition is 32K, but 9K is currently reserved for product
- * header (8K) and image header (1K).
- * First 512 bytes of SYSRAM are remapped at 0x0 and used as ISR vector
- * (there's no need to reallocate ISR vector) and thus cannot be used by
- * application.
- */
-
- FLASH (r) : ORIGIN = (0x00000000), LENGTH = (1024 * 1024)
- RAM (rw) : ORIGIN = (0x20000000), LENGTH = (512 * 1024)
-}
-
-OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
-
-/* Linker script to place sections and symbol values. Should be used together
- * with other linker script that defines memory regions FLASH and RAM.
- * It references following symbols, which must be defined in code:
- * Reset_Handler : Entry of reset handler
- *
- * It defines following symbols, which code can use without definition:
- * __exidx_start
- * __exidx_end
- * __etext
- * __data_start__
- * __preinit_array_start
- * __preinit_array_end
- * __init_array_start
- * __init_array_end
- * __fini_array_start
- * __fini_array_end
- * __data_end__
- * __bss_start__
- * __bss_end__
- * __HeapBase
- * __HeapLimit
- * __StackLimit
- * __StackTop
- * __stack
- * __bssnz_start__
- * __bssnz_end__
- */
-ENTRY(Reset_Handler)
-
-SECTIONS
-{
- __text = .;
-
- .text :
- {
- __isr_vector_start = .;
- KEEP(*(.isr_vector))
- /* ISR vector shall have exactly 512 bytes */
- . = __isr_vector_start + 0x200;
- __isr_vector_end = .;
-
- *(.text)
- *(.text.*)
-
- *(.libcmac.rom)
-
- KEEP(*(.init))
- KEEP(*(.fini))
-
- /* .ctors */
- *crtbegin.o(.ctors)
- *crtbegin?.o(.ctors)
- *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
- *(SORT(.ctors.*))
- *(.ctors)
-
- /* .dtors */
- *crtbegin.o(.dtors)
- *crtbegin?.o(.dtors)
- *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
- *(SORT(.dtors.*))
- *(.dtors)
-
- *(.rodata*)
-
- *(.eh_frame*)
- . = ALIGN(4);
- } > FLASH
-
- .ARM.extab :
- {
- *(.ARM.extab* .gnu.linkonce.armextab.*)
- . = ALIGN(4);
- } > FLASH
-
- __exidx_start = .;
- .ARM :
- {
- *(.ARM.exidx* .gnu.linkonce.armexidx.*)
- . = ALIGN(4);
- } > FLASH
- __exidx_end = .;
-
- .intvect :
- {
- . = ALIGN(4);
- __intvect_start__ = .;
- . = . + (__isr_vector_end - __isr_vector_start);
- . = ALIGN(4);
- } > RAM
-
- .sleep_state (NOLOAD) :
- {
- . = ALIGN(4);
- *(sleep_state)
- } > RAM
-
- /* This section will be zeroed by RTT package init */
- .rtt (NOLOAD):
- {
- . = ALIGN(4);
- *(.rtt)
- . = ALIGN(4);
- } > RAM
-
- __text_ram_addr = LOADADDR(.text_ram);
-
- .text_ram :
- {
- . = ALIGN(4);
- __text_ram_start__ = .;
- *(.text_ram*)
- . = ALIGN(4);
- __text_ram_end__ = .;
- } > RAM AT > FLASH
-
- __etext = LOADADDR(.data);
-
- .data :
- {
- __data_start__ = .;
- *(vtable)
- *(.data*)
-
- . = ALIGN(4);
- /* preinit data */
- PROVIDE_HIDDEN (__preinit_array_start = .);
- *(.preinit_array)
- PROVIDE_HIDDEN (__preinit_array_end = .);
-
- . = ALIGN(4);
- /* init data */
- PROVIDE_HIDDEN (__init_array_start = .);
- *(SORT(.init_array.*))
- *(.init_array)
- PROVIDE_HIDDEN (__init_array_end = .);
-
-
- . = ALIGN(4);
- /* finit data */
- PROVIDE_HIDDEN (__fini_array_start = .);
- *(SORT(.fini_array.*))
- *(.fini_array)
- PROVIDE_HIDDEN (__fini_array_end = .);
-
- *(.jcr)
- . = ALIGN(4);
- /* All data end */
- __data_end__ = .;
- } > RAM AT > FLASH
-
- .bssnz :
- {
- . = ALIGN(4);
- __bssnz_start__ = .;
- *(.bss.core.nz*)
- . = ALIGN(4);
- __bssnz_end__ = .;
- } > RAM
-
- .bss :
- {
- . = ALIGN(4);
- __bss_start__ = .;
- *(.bss*)
- *(COMMON)
- . = ALIGN(4);
- __bss_end__ = .;
- } > RAM
-
- .cmac (NOLOAD) :
- {
- . = ALIGN(0x400);
- *(.libcmac.ram)
- } > RAM
-
- /* Heap starts after BSS */
- . = ALIGN(8);
- __HeapBase = .;
-
- /* .stack_dummy section doesn't contains any symbols. It is only
- * used for linker to calculate size of stack sections, and assign
- * values to stack symbols later */
- .stack_dummy (COPY):
- {
- *(.stack*)
- } > RAM
-
- _ram_start = ORIGIN(RAM);
-
- /* Set stack top to end of RAM, and stack limit move down by
- * size of stack_dummy section */
- __StackTop = ORIGIN(RAM) + LENGTH(RAM);
- __StackLimit = __StackTop - SIZEOF(.stack_dummy);
- PROVIDE(__stack = __StackTop);
-
- /* Top of head is the bottom of the stack */
- __HeapLimit = __StackLimit;
- end = __HeapLimit;
-
- /* Check if data + heap + stack exceeds RAM limit */
- ASSERT(__HeapBase <= __HeapLimit, "region RAM overflowed with stack")
-
- /* Check that intvect is at the beginning of RAM */
- ASSERT(__intvect_start__ == ORIGIN(RAM), "intvect is not at beginning of RAM")
-}
diff --git a/hw/bsp/da1469x_dk_pro/gcc_startup_da1469x.S b/hw/bsp/da1469x_dk_pro/gcc_startup_da1469x.S
deleted file mode 100644
index d47fbcd97..000000000
--- a/hw/bsp/da1469x_dk_pro/gcc_startup_da1469x.S
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- #include "syscfg/syscfg.h"
-
- .syntax unified
- .arch armv7-m
-
- .section .stack
- .align 3
-#ifdef __STACK_SIZE
- .equ Stack_Size, __STACK_SIZE
-#else
- .equ Stack_Size, 0xC00
-#endif
- .equ SYS_CTRL_REG, 0x50000024
- .equ CACHE_FLASH_REG, 0x100C0040
- .equ RESET_STAT_REG, 0x500000BC
-
- .globl __StackTop
- .globl __StackLimit
-__StackLimit:
- .space Stack_Size
- .size __StackLimit, . - __StackLimit
-__StackTop:
- .size __StackTop, . - __StackTop
-
- .section .heap
- .align 3
-#ifdef __HEAP_SIZE
- .equ Heap_Size, __HEAP_SIZE
-#else
- .equ Heap_Size, 0
-#endif
- .globl __HeapBase
- .globl __HeapLimit
-__HeapBase:
- .if Heap_Size
- .space Heap_Size
- .endif
- .size __HeapBase, . - __HeapBase
-__HeapLimit:
- .size __HeapLimit, . - __HeapLimit
-
- .section .isr_vector
- .align 2
- .globl __isr_vector
-__isr_vector:
- .long __StackTop
- .long Reset_Handler
- /* Cortex-M33 interrupts */
- .long NMI_Handler
- .long HardFault_Handler
- .long MemoryManagement_Handler
- .long BusFault_Handler
- .long UsageFault_Handler
- .long SecureFault_Handler
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long SVC_Handler
- .long DebugMonitor_Handler
- .long 0 /* Reserved */
- .long PendSV_Handler
- .long SysTick_Handler
- /* DA1469x interrupts */
- .long SENSOR_NODE_IRQHandler
- .long DMA_IRQHandler
- .long CHARGER_STATE_IRQHandler
- .long CHARGER_ERROR_IRQHandler
- .long CMAC2SYS_IRQHandler
- .long UART_IRQHandler
- .long UART2_IRQHandler
- .long UART3_IRQHandler
- .long I2C_IRQHandler
- .long I2C2_IRQHandler
- .long SPI_IRQHandler
- .long SPI2_IRQHandler
- .long PCM_IRQHandler
- .long SRC_IN_IRQHandler
- .long SRC_OUT_IRQHandler
- .long USB_IRQHandler
- .long TIMER_IRQHandler
- .long TIMER2_IRQHandler
- .long RTC_IRQHandler
- .long KEY_WKUP_GPIO_IRQHandler
- .long PDC_IRQHandler
- .long VBUS_IRQHandler
- .long MRM_IRQHandler
- .long MOTOR_CONTROLLER_IRQHandler
- .long TRNG_IRQHandler
- .long DCDC_IRQHandler
- .long XTAL32M_RDY_IRQHandler
- .long ADC_IRQHandler
- .long ADC2_IRQHandler
- .long CRYPTO_IRQHandler
- .long CAPTIMER1_IRQHandler
- .long RFDIAG_IRQHandler
- .long LCD_CONTROLLER_IRQHandler
- .long PLL_LOCK_IRQHandler
- .long TIMER3_IRQHandler
- .long TIMER4_IRQHandler
- .long LRA_IRQHandler
- .long RTC_EVENT_IRQHandler
- .long GPIO_P0_IRQHandler
- .long GPIO_P1_IRQHandler
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .long 0 /* Reserved */
- .size __isr_vector, . - __isr_vector
-
- .text
- .thumb
- .thumb_func
- .align 2
- .globl Reset_Handler
- .type Reset_Handler, %function
-Reset_Handler:
- /* Make sure interrupt vector is remapped at 0x0 */
- ldr r1, =SYS_CTRL_REG
- ldrh r2, [r1, #0]
- orrs r2, r2, #8
- strh r2, [r1, #0]
-
-#if !MYNEWT_VAL(RAM_RESIDENT)
-/*
- * Flash is remapped at 0x0 with an offset, i.e. 0x0 does not correspond to
- * 0x16000000 but to start of an image on flash. This is calculated from product
- * header by 1st state bootloader and configured in CACHE_FLASH_REG. We need to
- * retrieve proper offset value for calculations later.
- */
- ldr r1, =CACHE_FLASH_REG
- ldr r4, [r1, #0]
- mov r2, r4
- mov r3, #0xFFFF
- bic r4, r4, r3 /* CACHE_FLASH_REG[FLASH_REGION_BASE] */
- mov r3, #0xFFF0
- and r2, r2, r3 /* CACHE_FLASH_REG[FLASH_REGION_OFFSET] */
- lsr r2, r2, #2
- orr r4, r4, r2
-
-/* Copy ISR vector from flash to RAM */
- ldr r1, =__isr_vector_start /* src ptr */
- ldr r2, =__isr_vector_end /* src end */
- ldr r3, =__intvect_start__ /* dst ptr */
-/* Make sure we copy from QSPIC address range, not from remapped range */
- cmp r1, r4
- itt lt
- addlt r1, r1, r4
- addlt r2, r2, r4
-.loop_isr_copy:
- cmp r1, r2
- ittt lt
- ldrlt r0, [r1], #4
- strlt r0, [r3], #4
- blt .loop_isr_copy
-
-/* Copy QSPI code from flash to RAM */
- ldr r1, =__text_ram_addr /* src ptr */
- ldr r2, =__text_ram_start__ /* ptr */
- ldr r3, =__text_ram_end__ /* dst end */
-.loop_code_text_ram_copy:
- cmp r2, r3
- ittt lt
- ldrlt r0, [r1], #4
- strlt r0, [r2], #4
- blt .loop_code_text_ram_copy
-
-/* Copy data from flash to RAM */
- ldr r1, =__etext /* src ptr */
- ldr r2, =__data_start__ /* dst ptr */
- ldr r3, =__data_end__ /* dst end */
-.loop_data_copy:
- cmp r2, r3
- ittt lt
- ldrlt r0, [r1], #4
- strlt r0, [r2], #4
- blt .loop_data_copy
-#endif
-
-/* Clear BSS */
- movs r0, 0
- ldr r1, =__bss_start__
- ldr r2, =__bss_end__
-.loop_bss_clear:
- cmp r1, r2
- itt lt
- strlt r0, [r1], #4
- blt .loop_bss_clear
-
- ldr r0, =__HeapBase
- ldr r1, =__HeapLimit
-/* Call static constructors */
- bl __libc_init_array
-
- bl SystemInit
- bl main
-
- .pool
- .size Reset_Handler, . - Reset_Handler
-
-/* Default interrupt handler */
- .type Default_Handler, %function
-Default_Handler:
- ldr r1, =SYS_CTRL_REG
- ldrh r2, [r1, #0]
- orrs r2, r2, #0x80 /* DEBUGGER_ENABLE */
- strh r2, [r1, #0]
- b .
-
- .size Default_Handler, . - Default_Handler
-
-/* Default handlers for all interrupts */
- .macro IRQ handler
- .weak \handler
- .set \handler, Default_Handler
- .endm
-
- /* Cortex-M33 interrupts */
- IRQ NMI_Handler
- IRQ HardFault_Handler
- IRQ MemoryManagement_Handler
- IRQ BusFault_Handler
- IRQ UsageFault_Handler
- IRQ SecureFault_Handler
- IRQ SVC_Handler
- IRQ DebugMonitor_Handler
- IRQ PendSV_Handler
- IRQ SysTick_Handler
- /* DA1469x interrupts */
- IRQ SENSOR_NODE_IRQHandler
- IRQ DMA_IRQHandler
- IRQ CHARGER_STATE_IRQHandler
- IRQ CHARGER_ERROR_IRQHandler
- IRQ CMAC2SYS_IRQHandler
- IRQ UART_IRQHandler
- IRQ UART2_IRQHandler
- IRQ UART3_IRQHandler
- IRQ I2C_IRQHandler
- IRQ I2C2_IRQHandler
- IRQ SPI_IRQHandler
- IRQ SPI2_IRQHandler
- IRQ PCM_IRQHandler
- IRQ SRC_IN_IRQHandler
- IRQ SRC_OUT_IRQHandler
- IRQ USB_IRQHandler
- IRQ TIMER_IRQHandler
- IRQ TIMER2_IRQHandler
- IRQ RTC_IRQHandler
- IRQ KEY_WKUP_GPIO_IRQHandler
- IRQ PDC_IRQHandler
- IRQ VBUS_IRQHandler
- IRQ MRM_IRQHandler
- IRQ MOTOR_CONTROLLER_IRQHandler
- IRQ TRNG_IRQHandler
- IRQ DCDC_IRQHandler
- IRQ XTAL32M_RDY_IRQHandler
- IRQ ADC_IRQHandler
- IRQ ADC2_IRQHandler
- IRQ CRYPTO_IRQHandler
- IRQ CAPTIMER1_IRQHandler
- IRQ RFDIAG_IRQHandler
- IRQ LCD_CONTROLLER_IRQHandler
- IRQ PLL_LOCK_IRQHandler
- IRQ TIMER3_IRQHandler
- IRQ TIMER4_IRQHandler
- IRQ LRA_IRQHandler
- IRQ RTC_EVENT_IRQHandler
- IRQ GPIO_P0_IRQHandler
- IRQ GPIO_P1_IRQHandler
- IRQ RESERVED40_IRQHandler
- IRQ RESERVED41_IRQHandler
- IRQ RESERVED42_IRQHandler
- IRQ RESERVED43_IRQHandler
- IRQ RESERVED44_IRQHandler
- IRQ RESERVED45_IRQHandler
- IRQ RESERVED46_IRQHandler
- IRQ RESERVED47_IRQHandler
-
-.end
diff --git a/hw/bsp/da1469x_dk_pro/product_header.dump b/hw/bsp/da1469x_dk_pro/product_header.dump
deleted file mode 100644
index ea4842242..000000000
Binary files a/hw/bsp/da1469x_dk_pro/product_header.dump and /dev/null differ
diff --git a/hw/bsp/espressif/boards/espressif_c6_devkitc/board.cmake b/hw/bsp/espressif/boards/espressif_c6_devkitc/board.cmake
new file mode 100644
index 000000000..50c7cb35d
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_c6_devkitc/board.cmake
@@ -0,0 +1,2 @@
+# Apply board specific content here
+set(IDF_TARGET "esp32c6")
diff --git a/hw/bsp/espressif/boards/espressif_c6_devkitc/board.h b/hw/bsp/espressif/boards/espressif_c6_devkitc/board.h
new file mode 100644
index 000000000..243dd47f6
--- /dev/null
+++ b/hw/bsp/espressif/boards/espressif_c6_devkitc/board.h
@@ -0,0 +1,51 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define NEOPIXEL_PIN 8
+
+#define BUTTON_PIN 9
+#define BUTTON_STATE_ACTIVE 0
+
+// SPI for USB host shield
+#define MAX3421_SPI_HOST SPI2_HOST
+#define MAX3421_SCK_PIN 4
+#define MAX3421_MOSI_PIN 6
+#define MAX3421_MISO_PIN 5
+#define MAX3421_CS_PIN 10
+#define MAX3421_INTR_PIN 7
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */
diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake
index 6eef5b88b..6a1e96624 100644
--- a/hw/bsp/family_support.cmake
+++ b/hw/bsp/family_support.cmake
@@ -6,6 +6,8 @@ include(CMakePrintHelpers)
set(TOP "${CMAKE_CURRENT_LIST_DIR}/../..")
get_filename_component(TOP ${TOP} ABSOLUTE)
+set(UF2CONV_PY ${TOP}/tools/uf2/utils/uf2conv.py)
+
#-------------------------------------------------------------
# Toolchain
# Can be changed via -DTOOLCHAIN=gcc|iar or -DCMAKE_C_COMPILER=
@@ -67,6 +69,10 @@ if (NOT FAMILY STREQUAL rp2040)
endif()
endif()
+if (NOT NO_WARN_RWX_SEGMENTS_SUPPORTED)
+ set(NO_WARN_RWX_SEGMENTS_SUPPORTED 1)
+endif()
+
set(WARNING_FLAGS_GNU
-Wall
-Wextra
@@ -138,7 +144,6 @@ function(family_filter RESULT DIR)
endif()
endfunction()
-
function(family_add_subdirectory DIR)
family_filter(SHOULD_ADD "${DIR}")
if (SHOULD_ADD)
@@ -146,13 +151,11 @@ function(family_add_subdirectory DIR)
endif()
endfunction()
-
function(family_get_project_name OUTPUT_NAME DIR)
get_filename_component(SHORT_NAME ${DIR} NAME)
set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE)
endfunction()
-
function(family_initialize_project PROJECT DIR)
# set output suffix to .elf (skip espressif and rp2040)
if(NOT FAMILY STREQUAL "espressif" AND NOT FAMILY STREQUAL "rp2040")
@@ -166,7 +169,6 @@ function(family_initialize_project PROJECT DIR)
endif()
endfunction()
-
#-------------------------------------------------------------
# Common Target Configure
# Most families use these settings except rp2040 and espressif
@@ -192,7 +194,6 @@ function(family_add_rtos TARGET RTOS)
endif ()
endfunction()
-
# Add common configuration to example
function(family_configure_common TARGET RTOS)
family_add_rtos(${TARGET} ${RTOS})
@@ -203,20 +204,17 @@ function(family_configure_common TARGET RTOS)
BOARD_${BOARD_UPPER}
)
- # run size after build
- find_program(SIZE_EXE ${CMAKE_SIZE})
- if(NOT ${SIZE_EXE} STREQUAL SIZE_EXE-NOTFOUND)
- add_custom_command(TARGET ${TARGET} POST_BUILD
- COMMAND ${SIZE_EXE} $
- )
- endif ()
- # Add warnings flags
+ # compile define from command line
+ if(DEFINED CFLAGS_CLI)
+ target_compile_options(${TARGET} PUBLIC ${CFLAGS_CLI})
+ endif()
+
target_compile_options(${TARGET} PUBLIC ${WARNING_FLAGS_${CMAKE_C_COMPILER_ID}})
# Generate linker map file
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${TARGET} PUBLIC "LINKER:-Map=$.map")
- if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
+ if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND NO_WARN_RWX_SEGMENTS_SUPPORTED)
target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments")
endif ()
elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang")
@@ -233,7 +231,6 @@ function(family_configure_common TARGET RTOS)
# LOGGER option
if (DEFINED LOGGER)
target_compile_definitions(${TARGET} PUBLIC LOGGER_${LOGGER})
-
# Add segger rtt to example
if(LOGGER STREQUAL "RTT" OR LOGGER STREQUAL "rtt")
if (NOT TARGET segger_rtt)
@@ -244,8 +241,15 @@ function(family_configure_common TARGET RTOS)
target_link_libraries(${TARGET} PUBLIC segger_rtt)
endif ()
endif ()
-endfunction()
+ # run size after build
+ find_program(SIZE_EXE ${CMAKE_SIZE})
+ if(NOT ${SIZE_EXE} STREQUAL SIZE_EXE-NOTFOUND)
+ add_custom_command(TARGET ${TARGET} POST_BUILD
+ COMMAND ${SIZE_EXE} $
+ )
+ endif ()
+endfunction()
# Add tinyusb to example
function(family_add_tinyusb TARGET OPT_MCU RTOS)
@@ -287,7 +291,6 @@ function(family_add_tinyusb TARGET OPT_MCU RTOS)
endfunction()
-
# Add bin/hex output
function(family_add_bin_hex TARGET)
add_custom_command(TARGET ${TARGET} POST_BUILD
@@ -296,6 +299,13 @@ function(family_add_bin_hex TARGET)
VERBATIM)
endfunction()
+# Add uf2 output
+function(family_add_uf2 TARGET FAMILY_ID)
+ set(BIN_FILE $/${TARGET}.hex)
+ add_custom_command(TARGET ${TARGET} POST_BUILD
+ COMMAND python ${UF2CONV_PY} -f ${FAMILY_ID} -c -o $/${TARGET}.uf2 ${BIN_FILE}
+ VERBATIM)
+endfunction()
#----------------------------------
# Example Target Configure (Default rule)
@@ -354,7 +364,7 @@ function(family_add_default_example_warnings TARGET)
)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
- if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0)
+ if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12.0 AND NO_WARN_RWX_SEGMENTS_SUPPORTED)
target_link_options(${TARGET} PUBLIC "LINKER:--no-warn-rwx-segments")
endif()
@@ -434,7 +444,7 @@ function(family_flash_openocd TARGET)
# note skip verify since it has issue with rp2040
add_custom_target(${TARGET}-openocd
DEPENDS ${TARGET}
- COMMAND ${OPENOCD} ${OPTION_LIST} -c "program $ reset" ${OPTION_LIST2} -c exit
+ COMMAND ${OPENOCD} ${OPTION_LIST} -c init -c halt -c "program $ reset" ${OPTION_LIST2} -c exit
VERBATIM
)
endfunction()
@@ -449,6 +459,18 @@ function(family_flash_openocd_wch TARGET)
family_flash_openocd(${TARGET})
endfunction()
+# Add flash with https://github.com/ch32-rs/wlink
+function(family_flash_wlink_rs TARGET)
+ if (NOT DEFINED WLINK_RS)
+ set(WLINK_RS wlink)
+ endif ()
+
+ add_custom_target(${TARGET}-wlink-rs
+ DEPENDS ${TARGET}
+ COMMAND ${WLINK_RS} flash $
+ )
+endfunction()
+
# Add flash pycod target
function(family_flash_pyocd TARGET)
if (NOT DEFINED PYOC)
@@ -461,6 +483,13 @@ function(family_flash_pyocd TARGET)
)
endfunction()
+# Flash with UF2
+function(family_flash_uf2 TARGET FAMILY_ID)
+ add_custom_target(${TARGET}-uf2
+ DEPENDS ${TARGET}
+ COMMAND python ${UF2CONV_PY} -f ${FAMILY_ID} --deploy $/${TARGET}.uf2
+ )
+endfunction()
# Add flash teensy_cli target
function(family_flash_teensy TARGET)
diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c
index c9c4918ef..2f305aa4d 100644
--- a/hw/bsp/imxrt/family.c
+++ b/hw/bsp/imxrt/family.c
@@ -40,6 +40,7 @@
#include "fsl_iomuxc.h"
#include "fsl_clock.h"
#include "fsl_lpuart.h"
+#include "fsl_ocotp.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
@@ -186,6 +187,29 @@ uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == GPIO_PinRead(BUTTON_PORT, BUTTON_PIN);
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ (void) max_len;
+
+ #if FSL_FEATURE_OCOTP_HAS_TIMING_CTRL
+ OCOTP_Init(OCOTP, CLOCK_GetFreq(kCLOCK_IpgClk));
+ #else
+ OCOTP_Init(OCOTP, 0u);
+ #endif
+
+ // Reads shadow registers 0x01 - 0x04 (Configuration and Manufacturing Info)
+ // into 8 bit wide destination, avoiding punning.
+ for (int i = 0; i < 4; ++i) {
+ uint32_t wr = OCOTP_ReadFuseShadowRegister(OCOTP, i + 1);
+ for (int j = 0; j < 4; j++) {
+ id[i*4+j] = wr & 0xff;
+ wr >>= 8;
+ }
+ }
+ OCOTP_Deinit(OCOTP);
+
+ return 16;
+}
+
int board_uart_read(uint8_t* buf, int len) {
int count = 0;
diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake
index f4d7378a5..d917e9777 100644
--- a/hw/bsp/imxrt/family.cmake
+++ b/hw/bsp/imxrt/family.cmake
@@ -44,6 +44,7 @@ function(add_board_target BOARD_TARGET)
${SDK_DIR}/drivers/igpio/fsl_gpio.c
${SDK_DIR}/drivers/lpspi/fsl_lpspi.c
${SDK_DIR}/drivers/lpuart/fsl_lpuart.c
+ ${SDK_DIR}/drivers/ocotp/fsl_ocotp.c
${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_VARIANT_WITH_CORE}.c
${SDK_DIR}/devices/${MCU_VARIANT}/xip/fsl_flexspi_nor_boot.c
${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c
@@ -75,6 +76,7 @@ function(add_board_target BOARD_TARGET)
${SDK_DIR}/drivers/igpio
${SDK_DIR}/drivers/lpspi
${SDK_DIR}/drivers/lpuart
+ ${SDK_DIR}/drivers/ocotp
)
update_board(${BOARD_TARGET})
diff --git a/hw/bsp/imxrt/family.mk b/hw/bsp/imxrt/family.mk
index bde4c4ba6..f00afb6a4 100644
--- a/hw/bsp/imxrt/family.mk
+++ b/hw/bsp/imxrt/family.mk
@@ -50,7 +50,8 @@ SRC_C += \
$(SDK_DIR)/drivers/common/fsl_common.c \
$(SDK_DIR)/drivers/common/fsl_common_arm.c \
$(SDK_DIR)/drivers/igpio/fsl_gpio.c \
- $(SDK_DIR)/drivers/lpuart/fsl_lpuart.c
+ $(SDK_DIR)/drivers/lpuart/fsl_lpuart.c \
+ $(SDK_DIR)/drivers/ocotp/fsl_ocotp.c \
# Optional drivers: only available for some mcus: rt1160, rt1170
ifneq (,$(wildcard ${TOP}/${MCU_DIR}/drivers/fsl_dcdc.c))
@@ -68,7 +69,8 @@ INC += \
$(TOP)/$(MCU_DIR)/drivers \
$(TOP)/$(SDK_DIR)/drivers/common \
$(TOP)/$(SDK_DIR)/drivers/igpio \
- $(TOP)/$(SDK_DIR)/drivers/lpuart
+ $(TOP)/$(SDK_DIR)/drivers/lpuart \
+ $(TOP)/$(SDK_DIR)/drivers/ocotp \
SRC_S += $(MCU_DIR)/gcc/startup_$(MCU_VARIANT_WITH_CORE).S
diff --git a/hw/bsp/lpc11/family.c b/hw/bsp/lpc11/family.c
index bff7110b8..e75bc4919 100644
--- a/hw/bsp/lpc11/family.c
+++ b/hw/bsp/lpc11/family.c
@@ -90,6 +90,13 @@ void board_led_write(bool state) {
Chip_GPIO_SetPinState(LPC_GPIO, LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON));
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ if ( max_len < 16 ) return 0;
+ uint32_t* id32 = (uint32_t*) (uintptr_t) id;
+ id32[0] = Chip_IAP_ReadUID();
+ return 4;
+}
+
uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == Chip_GPIO_GetPinState(LPC_GPIO, BUTTON_PORT, BUTTON_PIN);
}
diff --git a/hw/bsp/lpc11/family.cmake b/hw/bsp/lpc11/family.cmake
index f17a48dd7..818600656 100644
--- a/hw/bsp/lpc11/family.cmake
+++ b/hw/bsp/lpc11/family.cmake
@@ -30,6 +30,7 @@ function(add_board_target BOARD_TARGET)
${SDK_DIR}/../gcc/cr_startup_lpc${LPC_FAMILY}.c
${SDK_DIR}/src/chip_${LPC_FAMILY}.c
${SDK_DIR}/src/clock_${LPC_FAMILY}.c
+ ${SDK_DIR}/src/iap.c
${SDK_DIR}/src/iocon_${LPC_FAMILY}.c
${SDK_DIR}/src/sysinit_${LPC_FAMILY}.c
)
diff --git a/hw/bsp/lpc11/family.mk b/hw/bsp/lpc11/family.mk
index 09713fd55..a3ec33768 100644
--- a/hw/bsp/lpc11/family.mk
+++ b/hw/bsp/lpc11/family.mk
@@ -9,13 +9,18 @@ CFLAGS += \
-DCFG_TUSB_MCU=OPT_MCU_LPC11UXX \
-DCFG_TUSB_MEM_ALIGN='__attribute__((aligned(64)))'
-LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
+# mcu driver cause following warnings
+CFLAGS += \
+ -Wno-error=incompatible-pointer-types \
+
+LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs
SRC_C += \
src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c \
$(MCU_DIR)/../gcc/cr_startup_lpc$(MCU_DRV).c \
$(MCU_DIR)/src/chip_$(MCU_DRV).c \
$(MCU_DIR)/src/clock_$(MCU_DRV).c \
+ $(MCU_DIR)/src/iap.c \
$(MCU_DIR)/src/iocon_$(MCU_DRV).c \
$(MCU_DIR)/src/sysinit_$(MCU_DRV).c
diff --git a/hw/bsp/lpc55/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/lpc55/FreeRTOSConfig/FreeRTOSConfig.h
index 6f10a7ab0..d3f357576 100644
--- a/hw/bsp/lpc55/FreeRTOSConfig/FreeRTOSConfig.h
+++ b/hw/bsp/lpc55/FreeRTOSConfig/FreeRTOSConfig.h
@@ -52,6 +52,7 @@
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
#define configMINIMAL_SECURE_STACK_SIZE (1024)
+#define configRUN_FREERTOS_SECURE_ONLY 1
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c
index 9cbce7eda..075832ea7 100644
--- a/hw/bsp/lpc55/family.c
+++ b/hw/bsp/lpc55/family.c
@@ -149,12 +149,17 @@ void board_init(void) {
// Init 100 MHz clock
BOARD_BootClockPLL100M();
+#if CFG_TUSB_OS == OPT_OS_NONE
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
-#if CFG_TUSB_OS == OPT_OS_FREERTOS
+#elif CFG_TUSB_OS == OPT_OS_FREERTOS
+ // Explicitly disable systick to prevent its ISR runs before scheduler start
+ SysTick->CTRL &= ~1U;
+
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
NVIC_SetPriority(USB0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
+ NVIC_SetPriority(USB1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
#endif
// Init all GPIO ports
@@ -268,6 +273,10 @@ void board_init(void) {
// phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
// phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
// USBPHY->TX = phytx;
+
+ ARM_MPU_SetMemAttr(0, 0x44); // Normal memory, non-cacheable (inner and outer)
+ ARM_MPU_SetRegion(0, ARM_MPU_RBAR(0x40100000, ARM_MPU_SH_NON, 0, 1, 1), ARM_MPU_RLAR(0x40104000, 0));
+ ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
#endif
}
diff --git a/hw/bsp/ra/family.c b/hw/bsp/ra/family.c
index db8988a36..a8b4ebcc7 100644
--- a/hw/bsp/ra/family.c
+++ b/hw/bsp/ra/family.c
@@ -147,6 +147,13 @@ uint32_t board_button_read(void) {
return lvl == BUTTON_STATE_ACTIVE;
}
+size_t board_get_unique_id(uint8_t id[], size_t max_len) {
+ max_len = tu_min32(max_len, sizeof(bsp_unique_id_t));
+ bsp_unique_id_t const *uid = R_BSP_UniqueIdGet();
+ memcpy(id, uid->unique_id_bytes, max_len);
+ return max_len;
+}
+
int board_uart_read(uint8_t *buf, int len) {
(void) buf;
(void) len;
@@ -169,7 +176,6 @@ void SysTick_Handler(void) {
uint32_t board_millis(void) {
return system_ticks;
}
-
#endif
//--------------------------------------------------------------------+
diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake
index b41d7fbea..c81390b28 100644
--- a/hw/bsp/rp2040/family.cmake
+++ b/hw/bsp/rp2040/family.cmake
@@ -175,6 +175,11 @@ function(family_configure_target TARGET RTOS)
# export RTOS_SUFFIX to parent scope
set(RTOS_SUFFIX ${RTOS_SUFFIX} PARENT_SCOPE)
+ # compile define from command line
+ if(DEFINED CFLAGS_CLI)
+ target_compile_options(${TARGET} PUBLIC ${CFLAGS_CLI})
+ endif()
+
pico_add_extra_outputs(${TARGET})
pico_enable_stdio_uart(${TARGET} 1)
target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_board${RTOS_SUFFIX} tinyusb_additions)
diff --git a/hw/bsp/stm32f7/family.mk b/hw/bsp/stm32f7/family.mk
index e261b0467..bae7d6d5b 100644
--- a/hw/bsp/stm32f7/family.mk
+++ b/hw/bsp/stm32f7/family.mk
@@ -24,6 +24,7 @@ ifeq ($(PORT), 1)
$(info "Using OTG_HS in FullSpeed mode")
endif
else
+ CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED
$(info "Using OTG_FS")
endif
diff --git a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.cmake b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.cmake
new file mode 100644
index 000000000..d42501948
--- /dev/null
+++ b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.cmake
@@ -0,0 +1,8 @@
+set(MCU_VARIANT stm32u545xx)
+set(JLINK_DEVICE stm32u545re)
+
+function(update_board TARGET)
+ target_compile_definitions(${TARGET} PUBLIC
+ STM32U545xx
+ )
+endfunction()
diff --git a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.h b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.h
new file mode 100644
index 000000000..7f3bf462c
--- /dev/null
+++ b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.h
@@ -0,0 +1,112 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// LED GREEN
+#define LED_PORT GPIOA
+#define LED_PIN GPIO_PIN_5
+#define LED_STATE_ON 1
+
+// BUTTON
+#define BUTTON_PORT GPIOC
+#define BUTTON_PIN GPIO_PIN_13
+#define BUTTON_STATE_ACTIVE 1
+
+// UART Enable for STLink VCOM
+#define UART_DEV LPUART1
+#define UART_CLK_EN __HAL_RCC_LPUART1_CLK_ENABLE
+#define UART_GPIO_PORT GPIOA
+#define UART_GPIO_AF GPIO_AF8_LPUART1
+#define UART_TX_PIN GPIO_PIN_2
+#define UART_RX_PIN GPIO_PIN_3
+
+//--------------------------------------------------------------------+
+// RCC Clock
+//--------------------------------------------------------------------+
+
+static void SystemClock_Config(void) {
+ RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
+ RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
+
+ /* Enable Power Clock */
+ __HAL_RCC_PWR_CLK_ENABLE();
+
+ /** Configure the main internal regulator output voltage
+ */
+ HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /** Initializes the CPU, AHB and APB buses clocks
+ */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_HSI;
+ RCC_OscInitStruct.HSIState = RCC_HSI_ON;
+ RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
+ RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
+ RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;
+ RCC_OscInitStruct.PLL.PLLM = 1;
+ RCC_OscInitStruct.PLL.PLLN = 10;
+ RCC_OscInitStruct.PLL.PLLP = 2;
+ RCC_OscInitStruct.PLL.PLLQ = 2;
+ RCC_OscInitStruct.PLL.PLLR = 1;
+ RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1;
+ RCC_OscInitStruct.PLL.PLLFRACN = 0;
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
+
+ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_CLK48;
+ PeriphClkInit.IclkClockSelection = RCC_CLK48CLKSOURCE_HSI48;
+
+ HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
+
+ /** Initializes the CPU, AHB and APB buses clocks
+ */
+ RCC_ClkInitStruct.ClockType =
+ RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK3;
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
+ RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
+
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
+}
+
+static void SystemPower_Config(void) {
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BOARD_H_ */
diff --git a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk
new file mode 100644
index 000000000..072c595fb
--- /dev/null
+++ b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk
@@ -0,0 +1,11 @@
+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 922d67f83..fee56f2ba 100644
--- a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk
+++ b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk
@@ -6,5 +6,6 @@ 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 1dd157a68..c83ec3999 100644
--- a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk
+++ b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk
@@ -6,5 +6,6 @@ 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 e759cec24..4bebe3330 100644
--- a/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk
+++ b/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk
@@ -7,5 +7,6 @@ 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.c b/hw/bsp/stm32u5/family.c
index d779b5c96..3cc7cc511 100644
--- a/hw/bsp/stm32u5/family.c
+++ b/hw/bsp/stm32u5/family.c
@@ -72,7 +72,9 @@ void board_init(void) {
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
+#ifdef GPIOF
__HAL_RCC_GPIOF_CLK_ENABLE();
+#endif
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
@@ -140,6 +142,17 @@ void board_init(void) {
GPIO_InitStruct.Alternate = GPIO_AF10_USB;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+#ifdef USB_DRD_FS
+ // STM32U535/STM32U545
+
+ /* Enable USB power on Pwrctrl CR2 register */
+ HAL_PWREx_EnableVddUSB();
+
+ /* USB clock enable */
+ __HAL_RCC_USB_FS_CLK_ENABLE();
+
+#endif
+
#ifdef USB_OTG_FS
#if CFG_TUSB_OS == OPT_OS_FREERTOS
// If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
@@ -170,7 +183,9 @@ void board_init(void) {
/* USB clock enable */
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
-#else
+#endif
+
+#ifdef USB_OTG_HS
// STM59x/Ax/Fx/Gx only have 1 USB HS port
#if CFG_TUSB_OS == OPT_OS_FREERTOS
diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake
index 7402540b7..f7a7aeb33 100644
--- a/hw/bsp/stm32u5/family.cmake
+++ b/hw/bsp/stm32u5/family.cmake
@@ -102,10 +102,16 @@ function(family_configure_example TARGET RTOS)
# Add TinyUSB target and port source
family_add_tinyusb(${TARGET} OPT_MCU_STM32U5 ${RTOS})
- target_sources(${TARGET}-tinyusb PUBLIC
- ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
- #${TOP}/src/portable/st/typec/typec_stm32.c
- )
+ if ((${MCU_VARIANT} STREQUAL "stm32u535xx") OR (${MCU_VARIANT} STREQUAL "stm32u545xx"))
+ target_sources(${TARGET}-tinyusb PUBLIC
+ ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ )
+ else ()
+ target_sources(${TARGET}-tinyusb PUBLIC
+ ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
+ #${TOP}/src/portable/st/typec/typec_stm32.c
+ )
+ endif ()
target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD})
# Link dependencies
diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk
index be5809340..89193b99f 100644
--- a/hw/bsp/stm32u5/family.mk
+++ b/hw/bsp/stm32u5/family.mk
@@ -27,18 +27,28 @@ LDFLAGS_GCC += \
--specs=nosys.specs --specs=nano.specs
SRC_C += \
- src/portable/synopsys/dwc2/dcd_dwc2.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \
- $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_icache.c \
+ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_icache.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c
+ifeq ($(MCU_VARIANT),stm32u545xx)
+SRC_C += \
+ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+else ifeq ($(MCU_VARIANT),stm32u535xx)
+SRC_C += \
+ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+else
+SRC_C += \
+ src/portable/synopsys/dwc2/dcd_dwc2.c
+endif
+
INC += \
$(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
$(TOP)/$(ST_CMSIS)/Include \
diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h
index d6f3e22e2..2f97c0f23 100644
--- a/src/class/audio/audio.h
+++ b/src/class/audio/audio.h
@@ -489,7 +489,7 @@ typedef enum
AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2),
AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3),
AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4),
- AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000,
+ AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000u,
} audio_data_format_type_I_t;
/// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification
@@ -640,7 +640,7 @@ typedef enum
AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000,
AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000,
AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000,
- AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000,
+ AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000u,
} audio_channel_config_t;
/// AUDIO Channel Cluster Descriptor (4.1)
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index e82d52a5b..75bb0b883 100644
--- a/src/class/audio/audio_device.c
+++ b/src/class/audio/audio_device.c
@@ -307,19 +307,6 @@ typedef struct
uint16_t desc_length; // Length of audio function descriptor
- // Buffer for control requests
- uint8_t * ctrl_buf;
- uint8_t ctrl_buf_sz;
-
- // Current active alternate settings
- uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP!
-
- // EP Transfer buffers and FIFOs
-#if CFG_TUD_AUDIO_ENABLE_EP_OUT
-#if !CFG_TUD_AUDIO_ENABLE_DECODING
- tu_fifo_t ep_out_ff;
-#endif
-
#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
struct {
CFG_TUSB_MEM_ALIGN uint32_t send_buf;
@@ -350,17 +337,6 @@ typedef struct
} feedback;
#endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
-#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
-
-#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
- tu_fifo_t ep_in_ff;
-#endif
-
- // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74)
-#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
- CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6];
-#endif
-
// Decoding parameters - parameters are set when alternate AS interface is set by host
// Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently.
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
@@ -369,8 +345,7 @@ typedef struct
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
audio_data_format_type_I_t format_type_I_rx;
- uint8_t n_bytes_per_sampe_rx;
- uint8_t n_channels_per_ff_rx;
+ uint8_t n_bytes_per_sample_rx;
uint8_t n_ff_used_rx;
#endif
#endif
@@ -386,26 +361,57 @@ typedef struct
#if CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL)
audio_format_type_t format_type_tx;
uint8_t n_channels_tx;
- uint8_t n_bytes_per_sampe_tx;
+ uint8_t n_bytes_per_sample_tx;
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
audio_data_format_type_I_t format_type_I_tx;
- uint8_t n_channels_per_ff_tx;
uint8_t n_ff_used_tx;
#endif
#endif
+ // Buffer for control requests
+ uint8_t * ctrl_buf;
+ uint8_t ctrl_buf_sz;
+
+ // Current active alternate settings
+ uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP!
+
+ // EP Transfer buffers and FIFOs
+#if CFG_TUD_AUDIO_ENABLE_EP_OUT
+#if !CFG_TUD_AUDIO_ENABLE_DECODING
+ tu_fifo_t ep_out_ff;
+#endif
+
+
+#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
+
+#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING
+ tu_fifo_t ep_in_ff;
+#endif
+
+ // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74)
+#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
+ CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6];
+#endif
+
+
// Support FIFOs for software encoding and decoding
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
tu_fifo_t * rx_supp_ff;
uint8_t n_rx_supp_ff;
uint16_t rx_supp_ff_sz_max;
+#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
+ uint8_t n_channels_per_ff_rx;
+#endif
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING
tu_fifo_t * tx_supp_ff;
uint8_t n_tx_supp_ff;
uint16_t tx_supp_ff_sz_max;
+#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
+ uint8_t n_channels_per_ff_tx;
+#endif
#endif
// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used
@@ -847,16 +853,16 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u
if (info.len_lin != 0)
{
info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin);
- src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx];
+ src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sample_rx];
dst_end = info.ptr_lin + info.len_lin;
- src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used);
+ src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sample_rx, info.ptr_lin, dst_end, src, n_ff_used);
// Handle wrapped part of FIFO
info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap);
if (info.len_wrap != 0)
{
dst_end = info.ptr_wrap + info.len_wrap;
- audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used);
+ audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sample_rx, info.ptr_wrap, dst_end, src, n_ff_used);
}
tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap);
}
@@ -1171,7 +1177,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
// Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT!
nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, audio->ep_in_sz / n_ff_used);
// Round to full number of samples (flooring)
- uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx;
+ uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx;
nBytesPerFFToSend = (nBytesPerFFToSend / nSlotSize) * nSlotSize;
#endif
@@ -1183,7 +1189,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++)
{
- dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx];
+ dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sample_tx];
tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info);
@@ -1191,7 +1197,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
{
info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length
src_end = (uint8_t *)info.ptr_lin + info.len_lin;
- dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used);
+ dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sample_tx, info.ptr_lin, src_end, dst, n_ff_used);
// Limit up to desired length
info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap);
@@ -1200,7 +1206,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi
if (info.len_wrap != 0)
{
src_end = (uint8_t *)info.ptr_wrap + info.len_wrap;
- audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used);
+ audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sample_tx, info.ptr_wrap, src_end, dst, n_ff_used);
}
tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap);
@@ -1666,7 +1672,8 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
#endif
uint8_t const *p_desc = _audiod_fct[i].p_desc;
uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
- while (p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
{
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
{
@@ -1916,7 +1923,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN;
// p_desc starts at required interface with alternate setting zero
- while (p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
{
// Find correct interface
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt)
@@ -1926,7 +1934,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
#endif
// From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary
uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints;
- while (foundEPs < nEps && p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (foundEPs < nEps && (p_desc_end - p_desc > 0))
{
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT)
{
@@ -1955,8 +1964,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
// Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap
#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING
- const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx))
- * (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx));
+ const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx))
+ * (audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx));
for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++)
{
tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true);
@@ -1986,7 +1995,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
// Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap
#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING
- const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx;
+ const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sample_rx) * audio->n_bytes_per_sample_rx;
for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++)
{
tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true);
@@ -2584,7 +2593,8 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio
p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength;
uint8_t tmp = 0;
- while (p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
{
// We assume the number of alternate settings is increasing thus we return the index of alternate setting zero!
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0)
@@ -2637,7 +2647,8 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t *
uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc;
p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor
- while (p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
{
if (p_desc[3] == entityID) // Entity IDs are always at offset 3
{
@@ -2661,8 +2672,8 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id)
// Get pointer at beginning and end
uint8_t const *p_desc = _audiod_fct[i].p_desc;
uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN;
-
- while (p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
{
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf)
{
@@ -2690,7 +2701,8 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id)
uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc);
p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength;
- while (p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
{
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep)
{
@@ -2721,8 +2733,8 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
#endif
p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor
-
- while (p_desc < p_desc_end)
+ // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning
+ while (p_desc_end - p_desc > 0)
{
// Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished
if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break;
@@ -2771,14 +2783,14 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const *
#if CFG_TUD_AUDIO_ENABLE_EP_IN
if (as_itf == audio->ep_in_as_intf_num)
{
- audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize;
+ audio->n_bytes_per_sample_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize;
}
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING
if (as_itf == audio->ep_out_as_intf_num)
{
- audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize;
+ audio->n_bytes_per_sample_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize;
}
#endif
}
@@ -2797,7 +2809,7 @@ static bool audiod_calc_tx_packet_sz(audiod_function_t* audio)
{
TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I);
TU_VERIFY(audio->n_channels_tx);
- TU_VERIFY(audio->n_bytes_per_sampe_tx);
+ TU_VERIFY(audio->n_bytes_per_sample_tx);
TU_VERIFY(audio->interval_tx);
TU_VERIFY(audio->sample_rate_tx);
@@ -2806,9 +2818,9 @@ static bool audiod_calc_tx_packet_sz(audiod_function_t* audio)
const uint16_t sample_normimal = (uint16_t)(audio->sample_rate_tx * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
const uint16_t sample_reminder = (uint16_t)(audio->sample_rate_tx * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000));
- const uint16_t packet_sz_tx_min = (uint16_t)((sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
- const uint16_t packet_sz_tx_norm = (uint16_t)(sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
- const uint16_t packet_sz_tx_max = (uint16_t)((sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx);
+ const uint16_t packet_sz_tx_min = (uint16_t)((sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sample_tx);
+ const uint16_t packet_sz_tx_norm = (uint16_t)(sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sample_tx);
+ const uint16_t packet_sz_tx_max = (uint16_t)((sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sample_tx);
// Endpoint size must larger than packet size
TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz);
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index f36725eba..ebc408f5a 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -45,8 +45,7 @@
//--------------------------------------------------------------------+
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-typedef struct
-{
+typedef struct {
uint8_t itf_num;
uint8_t ep_notif;
uint8_t ep_in;
@@ -56,7 +55,7 @@ typedef struct
uint8_t line_state;
/*------------- From this point, data is not cleared by bus reset -------------*/
- char wanted_char;
+ char wanted_char;
TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding;
// FIFO
@@ -72,19 +71,22 @@ typedef struct
// Endpoint Transfer buffer
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE];
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE];
-
-}cdcd_interface_t;
+} cdcd_interface_t;
#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char)
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-CFG_TUD_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
+CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
+static tud_cdc_configure_fifo_t _cdcd_fifo_cfg;
-static bool _prep_out_transaction (cdcd_interface_t* p_cdc)
-{
+static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
uint8_t const rhport = 0;
+
+ // Skip if usb is not ready yet
+ TU_VERIFY(tud_ready() && p_cdc->ep_out);
+
uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff);
// Prepare for incoming data but only allow what we can store in the ring buffer.
@@ -99,14 +101,11 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc)
// fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&p_cdc->rx_ff);
- if ( available >= sizeof(p_cdc->epout_buf) )
- {
+ if ( available >= sizeof(p_cdc->epout_buf) ) {
return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
- }else
- {
+ }else {
// Release endpoint since we don't make any transfer
usbd_edpt_release(rhport, p_cdc->ep_out);
-
return false;
}
}
@@ -114,51 +113,53 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc)
//--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
-bool tud_cdc_n_connected(uint8_t itf)
-{
+
+bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg) {
+ TU_VERIFY(cfg);
+ _cdcd_fifo_cfg = (*cfg);
+ return true;
+}
+
+bool tud_cdc_n_ready(uint8_t itf) {
+ return tud_ready() && _cdcd_itf[itf].ep_in != 0 && _cdcd_itf[itf].ep_out != 0;
+}
+
+bool tud_cdc_n_connected(uint8_t itf) {
// DTR (bit 0) active is considered as connected
return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0);
}
-uint8_t tud_cdc_n_get_line_state (uint8_t itf)
-{
+uint8_t tud_cdc_n_get_line_state(uint8_t itf) {
return _cdcd_itf[itf].line_state;
}
-void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding)
-{
+void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) {
(*coding) = _cdcd_itf[itf].line_coding;
}
-void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted)
-{
+void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) {
_cdcd_itf[itf].wanted_char = wanted;
}
-
//--------------------------------------------------------------------+
// READ API
//--------------------------------------------------------------------+
-uint32_t tud_cdc_n_available(uint8_t itf)
-{
+uint32_t tud_cdc_n_available(uint8_t itf) {
return tu_fifo_count(&_cdcd_itf[itf].rx_ff);
}
-uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize)
-{
+uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
_prep_out_transaction(p_cdc);
return num_read;
}
-bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr)
-{
+bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) {
return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr);
}
-void tud_cdc_n_read_flush (uint8_t itf)
-{
+void tud_cdc_n_read_flush(uint8_t itf) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
tu_fifo_clear(&p_cdc->rx_ff);
_prep_out_transaction(p_cdc);
@@ -167,16 +168,15 @@ void tud_cdc_n_read_flush (uint8_t itf)
//--------------------------------------------------------------------+
// WRITE API
//--------------------------------------------------------------------+
-uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
-{
+uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
// flush if queue more than packet size
- if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE
- #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE
- || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size
- #endif
+ if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE
+ #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE
+ || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size
+ #endif
) {
tud_cdc_n_write_flush(itf);
}
@@ -184,30 +184,27 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize)
return ret;
}
-uint32_t tud_cdc_n_write_flush (uint8_t itf)
-{
+uint32_t tud_cdc_n_write_flush(uint8_t itf) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
// Skip if usb is not ready yet
- TU_VERIFY( tud_ready(), 0 );
+ TU_VERIFY(tud_ready(), 0);
// No data to send
- if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0;
+ if (!tu_fifo_count(&p_cdc->tx_ff)) return 0;
uint8_t const rhport = 0;
// Claim the endpoint
- TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 );
+ TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_in), 0);
// Pull data from FIFO
uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
- if ( count )
- {
- TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 );
+ if (count) {
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0);
return count;
- }else
- {
+ } else {
// Release endpoint since we don't make any transfer
// Note: data is dropped if terminal is not connected
usbd_edpt_release(rhport, p_cdc->ep_in);
@@ -215,33 +212,30 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf)
}
}
-uint32_t tud_cdc_n_write_available (uint8_t itf)
-{
+uint32_t tud_cdc_n_write_available(uint8_t itf) {
return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff);
}
-bool tud_cdc_n_write_clear (uint8_t itf)
-{
+bool tud_cdc_n_write_clear(uint8_t itf) {
return tu_fifo_clear(&_cdcd_itf[itf].tx_ff);
}
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
-void cdcd_init(void)
-{
+void cdcd_init(void) {
tu_memclr(_cdcd_itf, sizeof(_cdcd_itf));
+ tu_memclr(&_cdcd_fifo_cfg, sizeof(_cdcd_fifo_cfg));
- for(uint8_t i=0; iwanted_char = (char) -1;
// default line coding is : stop bit = 1, parity = none, data bits = 8
- p_cdc->line_coding.bit_rate = 115200;
+ p_cdc->line_coding.bit_rate = 115200;
p_cdc->line_coding.stop_bits = 0;
- p_cdc->line_coding.parity = 0;
+ p_cdc->line_coding.parity = 0;
p_cdc->line_coding.data_bits = 8;
// Config RX fifo
@@ -285,35 +279,28 @@ bool cdcd_deinit(void) {
return true;
}
-void cdcd_reset(uint8_t rhport)
-{
+void cdcd_reset(uint8_t rhport) {
(void) rhport;
- for(uint8_t i=0; irx_ff);
- #if !CFG_TUD_CDC_PERSISTENT_TX_BUFF
- tu_fifo_clear(&p_cdc->tx_ff);
- #endif
+ if (!_cdcd_fifo_cfg.rx_persistent) tu_fifo_clear(&p_cdc->rx_ff);
+ if (!_cdcd_fifo_cfg.tx_persistent) tu_fifo_clear(&p_cdc->tx_ff);
tu_fifo_set_overwritable(&p_cdc->tx_ff, true);
}
}
-uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
-{
+uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
// Only support ACM subclass
TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0);
// Find available interface
- cdcd_interface_t * p_cdc = NULL;
- for(uint8_t cdc_id=0; cdc_iditf_num = itf_desc->bInterfaceNumber;
uint16_t drv_len = sizeof(tusb_desc_interface_t);
- uint8_t const * p_desc = tu_desc_next( itf_desc );
+ uint8_t const* p_desc = tu_desc_next(itf_desc);
// Communication Functional Descriptors
- while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
- {
+ while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) {
drv_len += tu_desc_len(p_desc);
- p_desc = tu_desc_next(p_desc);
+ p_desc = tu_desc_next(p_desc);
}
- if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
- {
+ if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) {
// notification endpoint
- tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc;
- TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 );
+ TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
p_cdc->ep_notif = desc_ep->bEndpointAddress;
drv_len += tu_desc_len(p_desc);
- p_desc = tu_desc_next(p_desc);
+ p_desc = tu_desc_next(p_desc);
}
//------------- Data Interface (if any) -------------//
- if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
- (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
- {
+ if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
+ (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) {
// next to endpoint descriptor
drv_len += tu_desc_len(p_desc);
- p_desc = tu_desc_next(p_desc);
+ p_desc = tu_desc_next(p_desc);
// Open endpoint pair
- TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 );
+ TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0);
- drv_len += 2*sizeof(tusb_desc_endpoint_t);
+ drv_len += 2 * sizeof(tusb_desc_endpoint_t);
}
// Prepare for incoming data
@@ -368,8 +352,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
+bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
// Handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
@@ -377,42 +360,33 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
cdcd_interface_t* p_cdc = _cdcd_itf;
// Identify which interface to use
- for ( ; ; itf++, p_cdc++)
- {
+ for (;; itf++, p_cdc++) {
if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
- if ( p_cdc->itf_num == request->wIndex ) break;
+ if (p_cdc->itf_num == request->wIndex) break;
}
- switch ( request->bRequest )
- {
+ switch (request->bRequest) {
case CDC_REQUEST_SET_LINE_CODING:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_LOG_DRV(" Set Line Coding\r\n");
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
+ } else if (stage == CONTROL_STAGE_ACK) {
+ if (tud_cdc_line_coding_cb) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
}
- else if ( stage == CONTROL_STAGE_ACK)
- {
- if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
- }
- break;
+ break;
case CDC_REQUEST_GET_LINE_CODING:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
TU_LOG_DRV(" Get Line Coding\r\n");
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
}
- break;
+ break;
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
- if (stage == CONTROL_STAGE_SETUP)
- {
+ if (stage == CONTROL_STAGE_SETUP) {
tud_control_status(rhport, request);
- }
- else if (stage == CONTROL_STAGE_ACK)
- {
+ } else if (stage == CONTROL_STAGE_ACK) {
// CDC PSTN v1.2 section 6.3.12
// Bit 0: Indicates if DTE is present or not.
// This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready)
@@ -429,61 +403,54 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
// Invoke callback
- if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts);
+ if (tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts);
}
- break;
- case CDC_REQUEST_SEND_BREAK:
- if (stage == CONTROL_STAGE_SETUP)
- {
- tud_control_status(rhport, request);
- }
- else if (stage == CONTROL_STAGE_ACK)
- {
- TU_LOG_DRV(" Send Break\r\n");
- if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue);
- }
- break;
+ break;
- default: return false; // stall unsupported request
+ case CDC_REQUEST_SEND_BREAK:
+ if (stage == CONTROL_STAGE_SETUP) {
+ tud_control_status(rhport, request);
+ } else if (stage == CONTROL_STAGE_ACK) {
+ TU_LOG_DRV(" Send Break\r\n");
+ if (tud_cdc_send_break_cb) tud_cdc_send_break_cb(itf, request->wValue);
+ }
+ break;
+
+ default:
+ return false; // stall unsupported request
}
return true;
}
-bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
+bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
(void) result;
uint8_t itf;
cdcd_interface_t* p_cdc;
// Identify which interface to use
- for (itf = 0; itf < CFG_TUD_CDC; itf++)
- {
+ for (itf = 0; itf < CFG_TUD_CDC; itf++) {
p_cdc = &_cdcd_itf[itf];
- if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break;
+ if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in)) break;
}
TU_ASSERT(itf < CFG_TUD_CDC);
// Received new data
- if ( ep_addr == p_cdc->ep_out )
- {
+ if (ep_addr == p_cdc->ep_out) {
tu_fifo_write_n(&p_cdc->rx_ff, p_cdc->epout_buf, (uint16_t) xferred_bytes);
// Check for wanted char and invoke callback if needed
- if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) )
- {
- for ( uint32_t i = 0; i < xferred_bytes; i++ )
- {
- if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) )
- {
+ if (tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1)) {
+ for (uint32_t i = 0; i < xferred_bytes; i++) {
+ if ((p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) {
tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
}
}
}
// invoke receive callback (if there is still data)
- if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
+ if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) tud_cdc_rx_cb(itf);
// prepare for OUT transaction
_prep_out_transaction(p_cdc);
@@ -492,19 +459,15 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// Data sent to host, we continue to fetch from tx fifo to send.
// Note: This will cause incorrect baudrate set in line coding.
// Though maybe the baudrate is not really important !!!
- if ( ep_addr == p_cdc->ep_in )
- {
+ if (ep_addr == p_cdc->ep_in) {
// invoke transmit callback to possibly refill tx fifo
- if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf);
+ if (tud_cdc_tx_complete_cb) tud_cdc_tx_complete_cb(itf);
- if ( 0 == tud_cdc_n_write_flush(itf) )
- {
+ if (0 == tud_cdc_n_write_flush(itf)) {
// If there is no data left, a ZLP should be sent if
// xferred_bytes is multiple of EP Packet size and not zero
- if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) )
- {
- if ( usbd_edpt_claim(rhport, p_cdc->ep_in) )
- {
+ if (!tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) {
+ if (usbd_edpt_claim(rhport, p_cdc->ep_in)) {
usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0);
}
}
diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h
index db709b3bc..3ad7c8baf 100644
--- a/src/class/cdc/cdc_device.h
+++ b/src/class/cdc/cdc_device.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_CDC_DEVICE_H_
-#define _TUSB_CDC_DEVICE_H_
+#ifndef TUSB_CDC_DEVICE_H_
+#define TUSB_CDC_DEVICE_H_
#include "cdc.h"
@@ -41,94 +41,148 @@
#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#endif
-// By default the TX fifo buffer is cleared on connect / bus reset.
-// Enable this to persist any data in the fifo instead.
-#ifndef CFG_TUD_CDC_PERSISTENT_TX_BUFF
- #define CFG_TUD_CDC_PERSISTENT_TX_BUFF (0)
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
-/** \addtogroup CDC_Serial Serial
- * @{
- * \defgroup CDC_Serial_Device Device
- * @{ */
+//--------------------------------------------------------------------+
+// Driver Configuration
+//--------------------------------------------------------------------+
+
+typedef struct TU_ATTR_PACKED {
+ uint8_t rx_persistent : 1; // keep rx fifo on bus reset or disconnect
+ uint8_t tx_persistent : 1; // keep tx fifo on bus reset or disconnect
+} tud_cdc_configure_fifo_t;
+
+// Configure CDC FIFOs behavior
+bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg);
//--------------------------------------------------------------------+
-// Application API (Multiple Ports)
-// CFG_TUD_CDC > 1
+// Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1
//--------------------------------------------------------------------+
+// Check if interface is ready
+bool tud_cdc_n_ready(uint8_t itf);
+
// Check if terminal is connected to this port
-bool tud_cdc_n_connected (uint8_t itf);
+bool tud_cdc_n_connected(uint8_t itf);
// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send)
-uint8_t tud_cdc_n_get_line_state (uint8_t itf);
+uint8_t tud_cdc_n_get_line_state(uint8_t itf);
// Get current line encoding: bit rate, stop bits parity etc ..
-void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding);
+void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding);
// Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving
-void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted);
+void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted);
// Get the number of bytes available for reading
-uint32_t tud_cdc_n_available (uint8_t itf);
+uint32_t tud_cdc_n_available(uint8_t itf);
// Read received bytes
-uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize);
+uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize);
// Read a byte, return -1 if there is none
-static inline
-int32_t tud_cdc_n_read_char (uint8_t itf);
+TU_ATTR_ALWAYS_INLINE static inline int32_t tud_cdc_n_read_char(uint8_t itf) {
+ uint8_t ch;
+ return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1;
+}
// Clear the received FIFO
-void tud_cdc_n_read_flush (uint8_t itf);
+void tud_cdc_n_read_flush(uint8_t itf);
// Get a byte from FIFO without removing it
-bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8);
+bool tud_cdc_n_peek(uint8_t itf, uint8_t* ui8);
// Write bytes to TX FIFO, data may remain in the FIFO for a while
-uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize);
+uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize);
// Write a byte
-static inline
-uint32_t tud_cdc_n_write_char (uint8_t itf, char ch);
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) {
+ return tud_cdc_n_write(itf, &ch, 1);
+}
// Write a null-terminated string
-static inline
-uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str);
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_n_write_str(uint8_t itf, char const* str) {
+ return tud_cdc_n_write(itf, str, strlen(str));
+}
// Force sending data if possible, return number of forced bytes
-uint32_t tud_cdc_n_write_flush (uint8_t itf);
+uint32_t tud_cdc_n_write_flush(uint8_t itf);
// Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation.
-uint32_t tud_cdc_n_write_available (uint8_t itf);
+uint32_t tud_cdc_n_write_available(uint8_t itf);
// Clear the transmit FIFO
-bool tud_cdc_n_write_clear (uint8_t itf);
+bool tud_cdc_n_write_clear(uint8_t itf);
//--------------------------------------------------------------------+
// Application API (Single Port)
//--------------------------------------------------------------------+
-static inline bool tud_cdc_connected (void);
-static inline uint8_t tud_cdc_get_line_state (void);
-static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding);
-static inline void tud_cdc_set_wanted_char (char wanted);
-static inline uint32_t tud_cdc_available (void);
-static inline int32_t tud_cdc_read_char (void);
-static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize);
-static inline void tud_cdc_read_flush (void);
-static inline bool tud_cdc_peek (uint8_t* ui8);
+TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_ready(void) {
+ return tud_cdc_n_ready(0);
+}
-static inline uint32_t tud_cdc_write_char (char ch);
-static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize);
-static inline uint32_t tud_cdc_write_str (char const* str);
-static inline uint32_t tud_cdc_write_flush (void);
-static inline uint32_t tud_cdc_write_available (void);
-static inline bool tud_cdc_write_clear (void);
+TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_connected(void) {
+ return tud_cdc_n_connected(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_cdc_get_line_state(void) {
+ return tud_cdc_n_get_line_state(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_get_line_coding(cdc_line_coding_t* coding) {
+ tud_cdc_n_get_line_coding(0, coding);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_set_wanted_char(char wanted) {
+ tud_cdc_n_set_wanted_char(0, wanted);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_available(void) {
+ return tud_cdc_n_available(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline int32_t tud_cdc_read_char(void) {
+ return tud_cdc_n_read_char(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_read(void* buffer, uint32_t bufsize) {
+ return tud_cdc_n_read(0, buffer, bufsize);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_read_flush(void) {
+ tud_cdc_n_read_flush(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_peek(uint8_t* ui8) {
+ return tud_cdc_n_peek(0, ui8);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_char(char ch) {
+ return tud_cdc_n_write_char(0, ch);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write(void const* buffer, uint32_t bufsize) {
+ return tud_cdc_n_write(0, buffer, bufsize);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_str(char const* str) {
+ return tud_cdc_n_write_str(0, str);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_flush(void) {
+ return tud_cdc_n_write_flush(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_available(void) {
+ return tud_cdc_n_write_available(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_write_clear(void) {
+ return tud_cdc_n_write_clear(0);
+}
//--------------------------------------------------------------------+
// Application Callback API (weak is optional)
@@ -152,103 +206,6 @@ TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p
// Invoked when received send break
TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms);
-//--------------------------------------------------------------------+
-// Inline Functions
-//--------------------------------------------------------------------+
-static inline int32_t tud_cdc_n_read_char (uint8_t itf)
-{
- uint8_t ch;
- return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1;
-}
-
-static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch)
-{
- return tud_cdc_n_write(itf, &ch, 1);
-}
-
-static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str)
-{
- return tud_cdc_n_write(itf, str, strlen(str));
-}
-
-static inline bool tud_cdc_connected (void)
-{
- return tud_cdc_n_connected(0);
-}
-
-static inline uint8_t tud_cdc_get_line_state (void)
-{
- return tud_cdc_n_get_line_state(0);
-}
-
-static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding)
-{
- tud_cdc_n_get_line_coding(0, coding);
-}
-
-static inline void tud_cdc_set_wanted_char (char wanted)
-{
- tud_cdc_n_set_wanted_char(0, wanted);
-}
-
-static inline uint32_t tud_cdc_available (void)
-{
- return tud_cdc_n_available(0);
-}
-
-static inline int32_t tud_cdc_read_char (void)
-{
- return tud_cdc_n_read_char(0);
-}
-
-static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize)
-{
- return tud_cdc_n_read(0, buffer, bufsize);
-}
-
-static inline void tud_cdc_read_flush (void)
-{
- tud_cdc_n_read_flush(0);
-}
-
-static inline bool tud_cdc_peek (uint8_t* ui8)
-{
- return tud_cdc_n_peek(0, ui8);
-}
-
-static inline uint32_t tud_cdc_write_char (char ch)
-{
- return tud_cdc_n_write_char(0, ch);
-}
-
-static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize)
-{
- return tud_cdc_n_write(0, buffer, bufsize);
-}
-
-static inline uint32_t tud_cdc_write_str (char const* str)
-{
- return tud_cdc_n_write_str(0, str);
-}
-
-static inline uint32_t tud_cdc_write_flush (void)
-{
- return tud_cdc_n_write_flush(0);
-}
-
-static inline uint32_t tud_cdc_write_available(void)
-{
- return tud_cdc_n_write_available(0);
-}
-
-static inline bool tud_cdc_write_clear(void)
-{
- return tud_cdc_n_write_clear(0);
-}
-
-/** @} */
-/** @} */
-
//--------------------------------------------------------------------+
// INTERNAL USBD-CLASS DRIVER API
//--------------------------------------------------------------------+
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index 2fe922136..c2b5a8a48 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -762,7 +762,7 @@ enum {
HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14,
HID_USAGE_PAGE_MEDICAL = 0x40,
HID_USAGE_PAGE_LIGHTING_AND_ILLUMINATION = 0x59,
- HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83
+ HID_USAGE_PAGE_MONITOR = 0x80, // 0x80 - 0x83
HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87
HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c,
HID_USAGE_PAGE_SCALE = 0x8d,
@@ -770,7 +770,7 @@ enum {
HID_USAGE_PAGE_CAMERA = 0x90,
HID_USAGE_PAGE_ARCADE = 0x91,
HID_USAGE_PAGE_FIDO = 0xF1D0, // FIDO alliance HID usage page
- HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF
+ HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF
};
/// HID Usage Table - Table 6: Generic Desktop Page
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index ada01582e..00f6fc474 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -46,43 +46,68 @@ typedef struct {
uint8_t itf_protocol; // Boot mouse or keyboard
uint16_t report_desc_len;
- CFG_TUSB_MEM_ALIGN uint8_t protocol_mode; // Boot (0) or Report protocol (1)
- CFG_TUSB_MEM_ALIGN uint8_t idle_rate; // up to application to handle idle rate
-
- CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE];
- CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE];
- CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_HID_EP_BUFSIZE];
+ uint8_t protocol_mode; // Boot (0) or Report protocol (1)
+ uint8_t idle_rate; // up to application to handle idle rate
// TODO save hid descriptor since host can specifically request this after enumeration
// Note: HID descriptor may be not available from application after enumeration
tusb_hid_descriptor_hid_t const *hid_descriptor;
+
+ uint8_t ctrl_buf[CFG_TUD_HID_EP_BUFSIZE];
+ CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE];
+ CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE];
} hidd_interface_t;
CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID];
/*------------- Helpers -------------*/
-static inline uint8_t get_index_by_itfnum(uint8_t itf_num)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t get_index_by_itfnum(uint8_t itf_num) {
for (uint8_t i = 0; i < CFG_TUD_HID; i++) {
- if (itf_num == _hidd_itf[i].itf_num)
+ if (itf_num == _hidd_itf[i].itf_num) {
return i;
+ }
}
-
return 0xFF;
}
+//--------------------------------------------------------------------+
+// Weak stubs: invoked if no strong implementation is available
+//--------------------------------------------------------------------+
+TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) {
+ (void) instance;
+ (void) protocol;
+}
+
+TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate) {
+ (void) instance;
+ (void) idle_rate;
+ return true;
+}
+
+TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) {
+ (void) instance;
+ (void) report;
+ (void) len;
+}
+
+// Invoked when a transfer wasn't successful
+TU_ATTR_WEAK void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, uint8_t const* report, uint16_t xferred_bytes) {
+ (void) instance;
+ (void) report_type;
+ (void) report;
+ (void) xferred_bytes;
+}
+
//--------------------------------------------------------------------+
// APPLICATION API
//--------------------------------------------------------------------+
-bool tud_hid_n_ready(uint8_t instance)
-{
+bool tud_hid_n_ready(uint8_t instance) {
uint8_t const rhport = 0;
uint8_t const ep_in = _hidd_itf[instance].ep_in;
return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(rhport, ep_in);
}
-bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len)
-{
+bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len) {
uint8_t const rhport = 0;
hidd_interface_t *p_hid = &_hidd_itf[instance];
@@ -101,14 +126,16 @@ bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, u
return usbd_edpt_xfer(rhport, p_hid->ep_in, p_hid->epin_buf, len);
}
-uint8_t tud_hid_n_interface_protocol(uint8_t instance) { return _hidd_itf[instance].itf_protocol; }
+uint8_t tud_hid_n_interface_protocol(uint8_t instance) {
+ return _hidd_itf[instance].itf_protocol;
+}
-uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].protocol_mode; }
+uint8_t tud_hid_n_get_protocol(uint8_t instance) {
+ return _hidd_itf[instance].protocol_mode;
+}
-bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6])
-{
+bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) {
hid_keyboard_report_t report;
-
report.modifier = modifier;
report.reserved = 0;
@@ -121,8 +148,8 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
}
-bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
-{
+bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id,
+ uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) {
hid_mouse_report_t report = {
.buttons = buttons,
.x = x,
@@ -134,8 +161,8 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
}
-bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal)
-{
+bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id,
+ uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
hid_abs_mouse_report_t report = {
.buttons = buttons,
.x = x,
@@ -146,8 +173,8 @@ bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t but
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
}
-bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons)
-{
+bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id,
+ int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) {
hid_gamepad_report_t report = {
.x = x,
.y = y,
@@ -165,28 +192,25 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int
//--------------------------------------------------------------------+
// USBD-CLASS API
//--------------------------------------------------------------------+
-void hidd_init(void)
-{
+void hidd_init(void) {
hidd_reset(0);
}
-bool hidd_deinit(void)
-{
+bool hidd_deinit(void) {
return true;
}
-void hidd_reset(uint8_t rhport)
-{
+void hidd_reset(uint8_t rhport) {
(void)rhport;
tu_memclr(_hidd_itf, sizeof(_hidd_itf));
}
-uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
-{
+uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len) {
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0);
// len = interface + hid + n*endpoints
- uint16_t const drv_len = (uint16_t)(sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
+ uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) +
+ desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
TU_ASSERT(max_len >= drv_len, 0);
// Find available interface
@@ -211,8 +235,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16
p_desc = tu_desc_next(p_desc);
TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0);
- if (desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT)
+ if (desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT) {
p_hid->itf_protocol = desc_itf->bInterfaceProtocol;
+ }
p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode
p_hid->itf_num = desc_itf->bInterfaceNumber;
@@ -234,8 +259,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
-bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
-{
+bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) {
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
uint8_t const hid_itf = get_index_by_itfnum((uint8_t)request->wIndex);
@@ -262,90 +286,82 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
} else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
//------------- Class Specific Request -------------//
switch (request->bRequest) {
- case HID_REQ_CONTROL_GET_REPORT:
- if (stage == CONTROL_STAGE_SETUP) {
- uint8_t const report_type = tu_u16_high(request->wValue);
- uint8_t const report_id = tu_u16_low(request->wValue);
+ case HID_REQ_CONTROL_GET_REPORT:
+ if (stage == CONTROL_STAGE_SETUP) {
+ uint8_t const report_type = tu_u16_high(request->wValue);
+ uint8_t const report_id = tu_u16_low(request->wValue);
- uint8_t *report_buf = p_hid->ctrl_buf;
- uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
+ uint8_t* report_buf = p_hid->ctrl_buf;
+ uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
+ uint16_t xferlen = 0;
- uint16_t xferlen = 0;
+ // If host request a specific Report ID, add ID to as 1 byte of response
+ if ((report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1)) {
+ *report_buf++ = report_id;
+ req_len--;
+ xferlen++;
+ }
- // If host request a specific Report ID, add ID to as 1 byte of response
- if ((report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1)) {
- *report_buf++ = report_id;
- req_len--;
+ xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len);
+ TU_ASSERT(xferlen > 0);
- xferlen++;
+ tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen);
}
+ break;
- xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t)report_type, report_buf, req_len);
- TU_ASSERT(xferlen > 0);
+ case HID_REQ_CONTROL_SET_REPORT:
+ if (stage == CONTROL_STAGE_SETUP) {
+ TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf));
+ tud_control_xfer(rhport, request, p_hid->ctrl_buf, request->wLength);
+ } else if (stage == CONTROL_STAGE_ACK) {
+ uint8_t const report_type = tu_u16_high(request->wValue);
+ uint8_t const report_id = tu_u16_low(request->wValue);
- tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen);
- }
- break;
+ uint8_t const* report_buf = p_hid->ctrl_buf;
+ uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
- case HID_REQ_CONTROL_SET_REPORT:
- if (stage == CONTROL_STAGE_SETUP) {
- TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf));
- tud_control_xfer(rhport, request, p_hid->ctrl_buf, request->wLength);
- } else if (stage == CONTROL_STAGE_ACK) {
- uint8_t const report_type = tu_u16_high(request->wValue);
- uint8_t const report_id = tu_u16_low(request->wValue);
+ // If host request a specific Report ID, extract report ID in buffer before invoking callback
+ if ((report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0])) {
+ report_buf++;
+ report_len--;
+ }
- uint8_t const *report_buf = p_hid->ctrl_buf;
- uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
-
- // If host request a specific Report ID, extract report ID in buffer before invoking callback
- if ((report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0])) {
- report_buf++;
- report_len--;
+ tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len);
}
+ break;
- tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t)report_type, report_buf, report_len);
- }
- break;
-
- case HID_REQ_CONTROL_SET_IDLE:
- if (stage == CONTROL_STAGE_SETUP) {
- p_hid->idle_rate = tu_u16_high(request->wValue);
- if (tud_hid_set_idle_cb) {
- // stall request if callback return false
- TU_VERIFY(tud_hid_set_idle_cb(hid_itf, p_hid->idle_rate));
+ case HID_REQ_CONTROL_SET_IDLE:
+ if (stage == CONTROL_STAGE_SETUP) {
+ p_hid->idle_rate = tu_u16_high(request->wValue);
+ TU_VERIFY(tud_hid_set_idle_cb(hid_itf, p_hid->idle_rate)); // stall if false
+ tud_control_status(rhport, request);
}
+ break;
- tud_control_status(rhport, request);
- }
- break;
+ case HID_REQ_CONTROL_GET_IDLE:
+ if (stage == CONTROL_STAGE_SETUP) {
+ // TODO idle rate of report
+ tud_control_xfer(rhport, request, &p_hid->idle_rate, 1);
+ }
+ break;
- case HID_REQ_CONTROL_GET_IDLE:
- if (stage == CONTROL_STAGE_SETUP) {
- // TODO idle rate of report
- tud_control_xfer(rhport, request, &p_hid->idle_rate, 1);
- }
- break;
+ case HID_REQ_CONTROL_GET_PROTOCOL:
+ if (stage == CONTROL_STAGE_SETUP) {
+ tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1);
+ }
+ break;
- case HID_REQ_CONTROL_GET_PROTOCOL:
- if (stage == CONTROL_STAGE_SETUP) {
- tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1);
- }
- break;
-
- case HID_REQ_CONTROL_SET_PROTOCOL:
- if (stage == CONTROL_STAGE_SETUP) {
- tud_control_status(rhport, request);
- } else if (stage == CONTROL_STAGE_ACK) {
- p_hid->protocol_mode = (uint8_t)request->wValue;
- if (tud_hid_set_protocol_cb) {
+ case HID_REQ_CONTROL_SET_PROTOCOL:
+ if (stage == CONTROL_STAGE_SETUP) {
+ tud_control_status(rhport, request);
+ } else if (stage == CONTROL_STAGE_ACK) {
+ p_hid->protocol_mode = (uint8_t) request->wValue;
tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode);
}
- }
- break;
+ break;
- default:
- return false; // stall unsupported request
+ default:
+ return false; // stall unsupported request
}
} else {
return false; // stall unsupported request
@@ -354,45 +370,35 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
return true;
}
-bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
-{
- (void)result;
-
+bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
uint8_t instance = 0;
hidd_interface_t *p_hid = _hidd_itf;
// Identify which interface to use
for (instance = 0; instance < CFG_TUD_HID; instance++) {
p_hid = &_hidd_itf[instance];
- if ((ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in))
+ if ((ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in)) {
break;
+ }
}
TU_ASSERT(instance < CFG_TUD_HID);
- // Check if there was a problem
- if (XFER_RESULT_SUCCESS != result) { // Inform application about the issue
- if (tud_hid_report_fail_cb) {
- tud_hid_report_fail_cb(instance, ep_addr, (uint16_t)xferred_bytes);
- }
-
- // Allow a new transfer to be received if issue happened on an OUT endpoint
- if (ep_addr == p_hid->ep_out) {
- // Prepare the OUT endpoint to be able to receive a new transfer
- TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
- }
-
- return true;
- }
-
- // Sent report successfully
if (ep_addr == p_hid->ep_in) {
- if (tud_hid_report_complete_cb) {
- tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t)xferred_bytes);
+ // Input report
+ if (XFER_RESULT_SUCCESS == result) {
+ tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes);
+ } else {
+ tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_INPUT, p_hid->epin_buf, (uint16_t) xferred_bytes);
}
- }
- // Received report successfully
- else if (ep_addr == p_hid->ep_out) {
- tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t)xferred_bytes);
+ } else {
+ // Output report
+ if (XFER_RESULT_SUCCESS == result) {
+ tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t)xferred_bytes);
+ } else {
+ tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t) xferred_bytes);
+ }
+
+ // prepare for new transfer
TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
}
diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h
index fcbf161c4..89c28e061 100644
--- a/src/class/hid/hid_device.h
+++ b/src/class/hid/hid_device.h
@@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef _TUSB_HID_DEVICE_H_
-#define _TUSB_HID_DEVICE_H_
+#ifndef TUSB_HID_DEVICE_H_
+#define TUSB_HID_DEVICE_H_
#include "hid.h"
@@ -48,8 +48,7 @@
#endif
//--------------------------------------------------------------------+
-// Application API (Multiple Instances)
-// CFG_TUD_HID > 1
+// Application API (Multiple Instances) i.e. CFG_TUD_HID > 1
//--------------------------------------------------------------------+
// Check if the interface is ready to use
@@ -76,12 +75,6 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons
// use template layout report as defined by hid_abs_mouse_report_t
bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal);
-
-static inline bool tud_hid_abs_mouse_report(uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal)
-{
- return tud_hid_n_abs_mouse_report(0, report_id, buttons, x, y, vertical, horizontal);
-}
-
// Gamepad: convenient helper to send gamepad report if application
// use template layout report TUD_HID_REPORT_DESC_GAMEPAD
bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons);
@@ -89,16 +82,40 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int
//--------------------------------------------------------------------+
// Application API (Single Port)
//--------------------------------------------------------------------+
-static inline bool tud_hid_ready(void);
-static inline uint8_t tud_hid_interface_protocol(void);
-static inline uint8_t tud_hid_get_protocol(void);
-static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len);
-static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]);
-static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal);
-static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons);
+TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_ready(void) {
+ return tud_hid_n_ready(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_hid_interface_protocol(void) {
+ return tud_hid_n_interface_protocol(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_hid_get_protocol(void) {
+ return tud_hid_n_get_protocol(0);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) {
+ return tud_hid_n_report(0, report_id, report, len);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) {
+ return tud_hid_n_keyboard_report(0, report_id, modifier, keycode);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) {
+ return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_abs_mouse_report(uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
+ return tud_hid_n_abs_mouse_report(0, report_id, buttons, x, y, vertical, horizontal);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) {
+ return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons);
+}
//--------------------------------------------------------------------+
-// Callbacks (Weak is optional)
+// Application Callbacks
//--------------------------------------------------------------------+
// Invoked when received GET HID REPORT DESCRIPTOR request
@@ -111,63 +128,25 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance);
uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen);
// Invoked when received SET_REPORT control request or
-// received data on OUT endpoint ( Report ID = 0, Type = 0 )
+// received data on OUT endpoint (Report ID = 0, Type = OUTPUT)
void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize);
// Invoked when received SET_PROTOCOL request
// protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
-TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol);
+void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol);
// Invoked when received SET_IDLE request. return false will stall the request
-// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication
+// - Idle Rate = 0 : only send report if there is changes, i.e. skip duplication
// - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms).
-TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate);
+bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate);
// Invoked when sent REPORT successfully to host
// Application can use this to send the next report
// Note: For composite reports, report[0] is report ID
-TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len);
+void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len);
// Invoked when a transfer wasn't successful
-TU_ATTR_WEAK void tud_hid_report_fail_cb(uint8_t instance, uint8_t ep_addr, uint16_t len);
-
-//--------------------------------------------------------------------+
-// Inline Functions
-//--------------------------------------------------------------------+
-static inline bool tud_hid_ready(void)
-{
- return tud_hid_n_ready(0);
-}
-
-static inline uint8_t tud_hid_interface_protocol(void)
-{
- return tud_hid_n_interface_protocol(0);
-}
-
-static inline uint8_t tud_hid_get_protocol(void)
-{
- return tud_hid_n_get_protocol(0);
-}
-
-static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len)
-{
- return tud_hid_n_report(0, report_id, report, len);
-}
-
-static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6])
-{
- return tud_hid_n_keyboard_report(0, report_id, modifier, keycode);
-}
-
-static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
-{
- return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal);
-}
-
-static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons)
-{
- return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons);
-}
+void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, uint8_t const* report, uint16_t xferred_bytes);
/* --------------------------------------------------------------------+
* HID Report Descriptor Template
@@ -645,9 +624,8 @@ uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf
bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
-
#ifdef __cplusplus
}
#endif
-#endif /* _TUSB_HID_DEVICE_H_ */
+#endif
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index 115a8a4df..7639a8fc6 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -657,7 +657,9 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr,
uint8_t const data8 = desc_report[0];
TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size);
- for (uint32_t i = 0; i < size; i++) TU_LOG(3, "%02X ", desc_report[i]);
+ for (uint32_t i = 0; i < size; i++) {
+ TU_LOG(3, "%02X ", desc_report[i]);
+ }
TU_LOG(3, "\r\n");
switch (type) {
diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c
index 64aba011a..90d747185 100644
--- a/src/class/net/ncm_device.c
+++ b/src/class/net/ncm_device.c
@@ -3,6 +3,8 @@
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
* Copyright (c) 2024 Hardy Griech
+ * Copyright (c) 2020 Jacob Berg Potter
+ * Copyright (c) 2020 Peter Lawrence
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h
index c66996c4f..637281bfc 100644
--- a/src/common/tusb_mcu.h
+++ b/src/common/tusb_mcu.h
@@ -195,7 +195,6 @@
#elif TU_CHECK_MCU(OPT_MCU_STM32F4)
#define TUP_USBIP_DWC2
#define TUP_USBIP_DWC2_STM32
- #define TUP_USBIP_DWC2_TEST_MODE
// For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9
#define TUP_DCD_ENDPOINT_MAX 6
@@ -210,7 +209,6 @@
// MCU with on-chip HS Phy
#if defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F733xx)
#define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS
- #define TUP_USBIP_DWC2_TEST_MODE
#endif
#elif TU_CHECK_MCU(OPT_MCU_STM32H7)
@@ -271,17 +269,23 @@
#define TUP_DCD_ENDPOINT_MAX 8
#elif TU_CHECK_MCU(OPT_MCU_STM32U5)
- #define TUP_USBIP_DWC2
- #define TUP_USBIP_DWC2_STM32
+ #if defined (STM32U535xx) || defined (STM32U545xx)
+ #define TUP_USBIP_FSDEV
+ #define TUP_USBIP_FSDEV_STM32
+ #define TUP_DCD_ENDPOINT_MAX 8
- // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY
- #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \
- defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx)
- #define TUP_DCD_ENDPOINT_MAX 9
- #define TUP_RHPORT_HIGHSPEED 1
- #define TUP_USBIP_DWC2_TEST_MODE
#else
- #define TUP_DCD_ENDPOINT_MAX 6
+ #define TUP_USBIP_DWC2
+ #define TUP_USBIP_DWC2_STM32
+
+ // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY
+ #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \
+ defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx)
+ #define TUP_DCD_ENDPOINT_MAX 9
+ #define TUP_RHPORT_HIGHSPEED 1
+ #else
+ #define TUP_DCD_ENDPOINT_MAX 6
+ #endif
#endif
#elif TU_CHECK_MCU(OPT_MCU_STM32L5)
@@ -420,6 +424,15 @@
#define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS
#define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8)
+#elif TU_CHECK_MCU(OPT_MCU_CH32V103)
+ #define TUP_USBIP_WCH_USBFS
+
+ #if !defined(CFG_TUD_WCH_USBIP_USBFS)
+ #define CFG_TUD_WCH_USBIP_USBFS 1
+ #endif
+
+ #define TUP_DCD_ENDPOINT_MAX 8
+
#elif TU_CHECK_MCU(OPT_MCU_CH32V20X)
// v20x support both FSDEV (USBD) and USBFS, default to FSDEV
#define TUP_USBIP_WCH_USBFS
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index b571f9b72..1501a5af6 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -214,6 +214,15 @@ enum {
#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2)
+// USB 2.0 Spec Table 9-7: Test Mode Selectors
+typedef enum {
+ TUSB_FEATURE_TEST_J = 1,
+ TUSB_FEATURE_TEST_K,
+ TUSB_FEATURE_TEST_SE0_NAK,
+ TUSB_FEATURE_TEST_PACKET,
+ TUSB_FEATURE_TEST_FORCE_ENABLE,
+} tusb_feature_test_mode_t;
+
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h
index dde0550d3..4344575b7 100644
--- a/src/common/tusb_verify.h
+++ b/src/common/tusb_verify.h
@@ -56,8 +56,8 @@
* #define TU_VERIFY(cond) if(cond) return false;
* #define TU_VERIFY(cond,ret) if(cond) return ret;
*
- * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;}
- * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;}
+ * #define TU_ASSERT(cond) if(cond) {TU_MESS_FAILED(); TU_BREAKPOINT(), return false;}
+ * #define TU_ASSERT(cond,ret) if(cond) {TU_MESS_FAILED(); TU_BREAKPOINT(), return ret;}
*------------------------------------------------------------------*/
#ifdef __cplusplus
@@ -70,9 +70,9 @@
#if CFG_TUSB_DEBUG
#include
- #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__)
+ #define TU_MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__)
#else
- #define _MESS_FAILED() do {} while (0)
+ #define TU_MESS_FAILED() do {} while (0)
#endif
// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33. M55
@@ -119,7 +119,7 @@
*------------------------------------------------------------------*/
#define TU_ASSERT_DEFINE(_cond, _ret) \
do { \
- if ( !(_cond) ) { _MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
+ if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
} while(0)
#define TU_ASSERT_1ARGS(_cond) TU_ASSERT_DEFINE(_cond, false)
diff --git a/src/device/dcd.h b/src/device/dcd.h
index f6735b077..5356e9be1 100644
--- a/src/device/dcd.h
+++ b/src/device/dcd.h
@@ -89,14 +89,6 @@ typedef struct TU_ATTR_ALIGNED(4) {
};
} dcd_event_t;
-typedef enum {
- TEST_J = 1,
- TEST_K,
- TEST_SE0_NAK,
- TEST_PACKET,
- TEST_FORCE_ENABLE,
-} test_mode_t;
-
//TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct");
//--------------------------------------------------------------------+
@@ -150,11 +142,8 @@ void dcd_disconnect(uint8_t rhport);
void dcd_sof_enable(uint8_t rhport, bool en);
#if CFG_TUD_TEST_MODE
-// Check if the test mode is supported, returns true is test mode selector is supported
-bool dcd_check_test_mode_support(test_mode_t test_selector) TU_ATTR_WEAK;
-
// Put device into a test mode (needs power cycle to quit)
-void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) TU_ATTR_WEAK;
+void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector);
#endif
//--------------------------------------------------------------------+
// Endpoint API
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 800d9c824..b93216006 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -46,13 +46,46 @@
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
- (void)rhport;
- (void)eventid;
- (void)in_isr;
+ (void) rhport;
+ (void) eventid;
+ (void) in_isr;
}
TU_ATTR_WEAK void tud_sof_cb(uint32_t frame_count) {
- (void)frame_count;
+ (void) frame_count;
+}
+
+TU_ATTR_WEAK uint8_t const* tud_descriptor_bos_cb(void) {
+ return NULL;
+}
+
+TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void) {
+ return NULL;
+}
+
+TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
+ (void) index;
+ return NULL;
+}
+
+TU_ATTR_WEAK void tud_mount_cb(void) {
+}
+
+TU_ATTR_WEAK void tud_umount_cb(void) {
+}
+
+TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en) {
+ (void) remote_wakeup_en;
+}
+
+TU_ATTR_WEAK void tud_resume_cb(void) {
+}
+
+TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
+ (void) rhport;
+ (void) stage;
+ (void) request;
+ return false;
}
TU_ATTR_WEAK bool dcd_deinit(uint8_t rhport) {
@@ -321,9 +354,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event,
static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
static bool process_set_config(uint8_t rhport, uint8_t cfg_num);
static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request);
+
#if CFG_TUD_TEST_MODE
-static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
+static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) {
+ TU_VERIFY(CONTROL_STAGE_ACK == stage);
+ uint8_t const selector = tu_u16_high(request->wIndex);
+ TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector);
+ dcd_enter_test_mode(rhport, (tusb_feature_test_mode_t) selector);
+ return true;
+}
#endif
+
// from usbd_control.c
void usbd_control_reset(void);
void usbd_control_set_request(tusb_control_request_t const *request);
@@ -549,7 +590,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
case DCD_EVENT_UNPLUGGED:
TU_LOG_USBD("\r\n");
usbd_reset(event.rhport);
- if (tud_umount_cb) tud_umount_cb();
+ tud_umount_cb();
break;
case DCD_EVENT_SETUP_RECEIVED:
@@ -609,7 +650,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
// e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected
if (_usbd_dev.connected) {
TU_LOG_USBD(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en);
- if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en);
+ tud_suspend_cb(_usbd_dev.remote_wakeup_en);
} else {
TU_LOG_USBD(" Skipped\r\n");
}
@@ -618,7 +659,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
case DCD_EVENT_RESUME:
if (_usbd_dev.connected) {
TU_LOG_USBD("\r\n");
- if (tud_resume_cb) tud_resume_cb();
+ tud_resume_cb();
} else {
TU_LOG_USBD(" Skipped\r\n");
}
@@ -667,8 +708,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Vendor request
if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) {
- TU_VERIFY(tud_vendor_control_xfer_cb);
-
usbd_control_set_complete_callback(tud_vendor_control_xfer_cb);
return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request);
}
@@ -695,7 +734,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
}
if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) {
- // Non standard request is not supported
+ // Non-standard request is not supported
TU_BREAKPOINT();
return false;
}
@@ -739,17 +778,23 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
_usbd_dev.speed = speed; // restore speed
}
+ _usbd_dev.cfg_num = cfg_num;
+
// Handle the new configuration and execute the corresponding callback
if ( cfg_num ) {
// switch to new configuration if not zero
- TU_ASSERT( process_set_config(rhport, cfg_num) );
- if ( tud_mount_cb ) tud_mount_cb();
+ if (!process_set_config(rhport, cfg_num)) {
+ TU_MESS_FAILED();
+ TU_BREAKPOINT();
+ _usbd_dev.cfg_num = 0;
+ return false;
+ }
+ tud_mount_cb();
} else {
- if ( tud_umount_cb ) tud_umount_cb();
+ tud_umount_cb();
}
}
- _usbd_dev.cfg_num = cfg_num;
tud_control_status(rhport, p_request);
}
break;
@@ -759,43 +804,27 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
break;
case TUSB_REQ_SET_FEATURE:
- // Handle the feature selector
- switch(p_request->wValue)
- {
- // Support for remote wakeup
+ switch(p_request->wValue) {
case TUSB_REQ_FEATURE_REMOTE_WAKEUP:
TU_LOG_USBD(" Enable Remote Wakeup\r\n");
-
// Host may enable remote wake up before suspending especially HID device
_usbd_dev.remote_wakeup_en = true;
tud_control_status(rhport, p_request);
break;
-#if CFG_TUD_TEST_MODE
- // Support for TEST_MODE
+ #if CFG_TUD_TEST_MODE
case TUSB_REQ_FEATURE_TEST_MODE: {
// Only handle the test mode if supported and valid
- TU_VERIFY(dcd_enter_test_mode && dcd_check_test_mode_support && 0 == tu_u16_low(p_request->wIndex));
+ TU_VERIFY(0 == tu_u16_low(p_request->wIndex));
- uint8_t selector = tu_u16_high(p_request->wIndex);
-
- // Stall request if the selected test mode isn't supported
- if (!dcd_check_test_mode_support((test_mode_t)selector))
- {
- TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector);
-
- return false;
- }
-
- // Acknowledge request
- tud_control_status(rhport, p_request);
-
- TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector);
+ uint8_t const selector = tu_u16_high(p_request->wIndex);
+ TU_VERIFY(TUSB_FEATURE_TEST_J <= selector && selector <= TUSB_FEATURE_TEST_FORCE_ENABLE);
usbd_control_set_complete_callback(process_test_mode_cb);
+ tud_control_status(rhport, p_request);
break;
}
-#endif /* CFG_TUD_TEST_MODE */
+ #endif /* CFG_TUD_TEST_MODE */
// Stall unsupported feature selector
default: return false;
@@ -1029,39 +1058,34 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
switch(desc_type)
{
- case TUSB_DESC_DEVICE:
- {
+ case TUSB_DESC_DEVICE: {
TU_LOG_USBD(" Device\r\n");
void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb();
+ TU_ASSERT(desc_device);
// Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has.
// This only happens with the very first get device descriptor and EP0 size = 8 or 16.
if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed &&
- ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t))
- {
+ ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) {
// Hack here: we modify the request length to prevent usbd_control response with zlp
// since we are responding with 1 packet & less data than wLength.
tusb_control_request_t mod_request = *p_request;
mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE;
return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE);
- }else
- {
+ }else {
return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t));
}
}
// break; // unreachable
- case TUSB_DESC_BOS:
- {
+ case TUSB_DESC_BOS: {
TU_LOG_USBD(" BOS\r\n");
// requested by host if USB > 2.0 ( i.e 2.1 or 3.x )
- if (!tud_descriptor_bos_cb) return false;
-
uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb();
- TU_ASSERT(desc_bos);
+ TU_VERIFY(desc_bos);
// Use offsetof to avoid pointer to the odd/misaligned address
uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) );
@@ -1071,24 +1095,20 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
// break; // unreachable
case TUSB_DESC_CONFIGURATION:
- case TUSB_DESC_OTHER_SPEED_CONFIG:
- {
+ case TUSB_DESC_OTHER_SPEED_CONFIG: {
uintptr_t desc_config;
- if ( desc_type == TUSB_DESC_CONFIGURATION )
- {
+ if ( desc_type == TUSB_DESC_CONFIGURATION ) {
TU_LOG_USBD(" Configuration[%u]\r\n", desc_index);
desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index);
- }else
- {
+ TU_ASSERT(desc_config);
+ }else {
// Host only request this after getting Device Qualifier descriptor
TU_LOG_USBD(" Other Speed Configuration\r\n");
- TU_VERIFY( tud_descriptor_other_speed_configuration_cb );
desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index);
+ TU_VERIFY(desc_config);
}
- TU_ASSERT(desc_config);
-
// Use offsetof to avoid pointer to the odd/misaligned address
uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) );
@@ -1109,16 +1129,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
}
// break; // unreachable
- case TUSB_DESC_DEVICE_QUALIFIER:
- {
+ case TUSB_DESC_DEVICE_QUALIFIER: {
TU_LOG_USBD(" Device Qualifier\r\n");
-
- TU_VERIFY( tud_descriptor_device_qualifier_cb );
-
uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb();
TU_VERIFY(desc_qualifier);
-
- // first byte of descriptor is its size
return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier));
}
// break; // unreachable
@@ -1127,20 +1141,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
}
}
-#if CFG_TUD_TEST_MODE
-static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
-{
- // At this point it should already be ensured that dcd_enter_test_mode() is defined
-
- // Only enter the test mode after the request for it has completed
- TU_VERIFY(CONTROL_STAGE_ACK == stage);
-
- dcd_enter_test_mode(rhport, (test_mode_t)tu_u16_high(request->wIndex));
-
- return true;
-}
-#endif /* CFG_TUD_TEST_MODE */
-
//--------------------------------------------------------------------+
// DCD Event Handler
//--------------------------------------------------------------------+
diff --git a/src/device/usbd.h b/src/device/usbd.h
index 26e857d36..7913096e3 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -109,7 +109,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo
bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request);
//--------------------------------------------------------------------+
-// Application Callbacks (WEAK is optional)
+// Application Callbacks
//--------------------------------------------------------------------+
// Invoked when received GET DEVICE DESCRIPTOR request
@@ -126,31 +126,31 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid);
// Invoked when received GET BOS DESCRIPTOR request
// Application return pointer to descriptor
-TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void);
+uint8_t const * tud_descriptor_bos_cb(void);
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
// device_qualifier descriptor describes information about a high-speed capable device that would
// change if the device were operating at the other speed. If not highspeed capable stall this request.
-TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void);
+uint8_t const* tud_descriptor_device_qualifier_cb(void);
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
-TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index);
+uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index);
// Invoked when device is mounted (configured)
-TU_ATTR_WEAK void tud_mount_cb(void);
+void tud_mount_cb(void);
// Invoked when device is unmounted
-TU_ATTR_WEAK void tud_umount_cb(void);
+void tud_umount_cb(void);
// Invoked when usb bus is suspended
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
-TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en);
+void tud_suspend_cb(bool remote_wakeup_en);
// Invoked when usb bus is resumed
-TU_ATTR_WEAK void tud_resume_cb(void);
+void tud_resume_cb(void);
// Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext()
void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr);
@@ -159,7 +159,7 @@ void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr);
void tud_sof_cb(uint32_t frame_count);
// Invoked when received control request with VENDOR TYPE
-TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
+bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
//--------------------------------------------------------------------+
// Binary Device Object Store (BOS) Descriptor Templates
diff --git a/src/host/usbh.c b/src/host/usbh.c
index 7a47f5056..8c488aaa2 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -1113,7 +1113,7 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt,
TU_LOG_USBH("Set Interface %u Alternate %u\r\n", itf_num, itf_alt);
tusb_control_request_t const request = {
.bmRequestType_bit = {
- .recipient = TUSB_REQ_RCPT_DEVICE,
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_STANDARD,
.direction = TUSB_DIR_OUT
},
@@ -1421,6 +1421,9 @@ static void process_enumeration(tuh_xfer_t* xfer) {
break;
case ENUM_GET_DEVICE_DESC: {
+ // Allow 2ms for address recovery time, Ref USB Spec 9.2.6.3
+ osal_task_delay(2);
+
uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue);
usbh_device_t* new_dev = get_device(new_addr);
diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h
index f1f05f353..a3a0f3a3f 100644
--- a/src/osal/osal_freertos.h
+++ b/src/osal/osal_freertos.h
@@ -78,7 +78,7 @@ typedef struct
// _int_set is not used with an RTOS
#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \
static _type _name##_##buf[_depth];\
- osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, _OSAL_Q_NAME(_name) };
+ osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, _OSAL_Q_NAME(_name) }
//--------------------------------------------------------------------+
// TASK API
diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c
index abce35245..1cc5c1836 100644
--- a/src/portable/nordic/nrf5x/dcd_nrf5x.c
+++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c
@@ -907,9 +907,9 @@ void tusb_hal_nrf_power_event(uint32_t event) {
USB_EVT_READY = 2
};
-#if CFG_TUSB_DEBUG >= 2
+#if CFG_TUSB_DEBUG >= 3
const char* const power_evt_str[] = {"Detected", "Removed", "Ready"};
- TU_LOG(2, "Power USB event: %s\r\n", power_evt_str[event]);
+ TU_LOG(3, "Power USB event: %s\r\n", power_evt_str[event]);
#endif
switch (event) {
diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c
index dc71117b3..ef61146aa 100644
--- a/src/portable/nxp/khci/dcd_khci.c
+++ b/src/portable/nxp/khci/dcd_khci.c
@@ -540,7 +540,7 @@ void dcd_int_handler(uint8_t rhport)
}
if (is & USB_ISTAT_SLEEP_MASK) {
- // TU_LOG2("Suspend: "); TU_LOG2_HEX(is);
+ // TU_LOG3("Suspend: "); TU_LOG2_HEX(is);
// Note Host usually has extra delay after bus reset (without SOF), which could falsely
// detected as Sleep event. Though usbd has debouncing logic so we are good
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c
index 1ca711c77..43f48da39 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.c
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c
@@ -53,6 +53,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void) {
//--------------------------------------------------------------------+
// Implementation
//--------------------------------------------------------------------+
+// Provide own byte by byte memcpy as not all copies are aligned
+static void unaligned_memcpy(void *dst, const void *src, size_t n) {
+ uint8_t *dst_byte = (uint8_t*)dst;
+ const uint8_t *src_byte = (const uint8_t*)src;
+ while (n--) {
+ *dst_byte++ = *src_byte++;
+ }
+}
void rp2040_usb_init(void) {
// Reset usb controller
@@ -67,7 +75,6 @@ void rp2040_usb_init(void) {
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#endif
- memset(usb_hw, 0, sizeof(*usb_hw));
memset(usb_dpram, 0, sizeof(*usb_dpram));
#ifdef __GNUC__
#pragma GCC diagnostic pop
@@ -125,7 +132,7 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep,
if (!ep->rx) {
// Copy data from user buffer to hw buffer
- memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen);
+ unaligned_memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen);
ep->user_buf += buflen;
// Mark as full
@@ -230,7 +237,7 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uin
// we have received AFTER we have copied it to the user buffer at the appropriate offset
assert(buf_ctrl & USB_BUF_CTRL_FULL);
- memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes);
+ unaligned_memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes);
ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes);
ep->user_buf += xferred_bytes;
}
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 9ce37f992..39f33bc34 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -37,14 +37,20 @@
* It also should work with minimal changes for any ST MCU with an "USB A"/"PCD"/"HCD" peripheral. This
* covers:
*
- * F04x, F072, F078, 070x6/B 1024 byte buffer
+ * F04x, F072, F078, F070x6/B 1024 byte buffer
* F102, F103 512 byte buffer; no internal D+ pull-up (maybe many more changes?)
* F302xB/C, F303xB/C, F373 512 byte buffer; no internal D+ pull-up
* F302x6/8, F302xD/E2, F303xD/E 1024 byte buffer; no internal D+ pull-up
+ * G0 2048 byte buffer; 32-bit bus; host mode
+ * G4 1024 byte buffer
+ * H5 2048 byte buffer; 32-bit bus; host mode
* L0x2, L0x3 1024 byte buffer
* L1 512 byte buffer
* L4x2, L4x3 1024 byte buffer
- * G0 2048 byte buffer
+ * L5 1024 byte buffer
+ * U0 1024 byte buffer; 32-bit bus
+ * U535, U545 2048 byte buffer; 32-bit bus; host mode
+ * WB35, WB55 1024 byte buffer
*
* To use this driver, you must:
* - If you are using a device with crystal-less USB, set up the clock recovery system (CRS)
@@ -215,24 +221,24 @@ void dcd_init(uint8_t rhport)
/* The RM mentions to use a special ordering of PDWN and FRES, but this isn't done in HAL.
* Here, the RM is followed. */
- for (uint32_t i = 0; i < 200; i++) { // should be a few us
+ for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
asm("NOP");
}
// Perform USB peripheral reset
USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN;
- for (uint32_t i = 0; i < 200; i++) { // should be a few us
+ for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
asm("NOP");
}
USB->CNTR &= ~USB_CNTR_PDWN;
// Wait startup time, for F042 and F070, this is <= 1 us.
- for (uint32_t i = 0; i < 200; i++) { // should be a few us
+ for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
asm("NOP");
}
USB->CNTR = 0; // Enable USB
-#if !defined(STM32G0) && !defined(STM32H5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address
+#if !defined(STM32G0) && !defined(STM32H5) && !defined(STM32U5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address
USB->BTABLE = DCD_STM32_BTABLE_BASE;
#endif
USB->ISTR = 0; // Clear pending interrupts
@@ -998,7 +1004,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui
srcVal++;
}
- if (wNBytes) {
+ if (wNBytes & 0x01) {
temp1 = (uint16_t) *srcVal;
*pdwVal = temp1;
}
diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h
index 85fe3266c..f63a80d56 100644
--- a/src/portable/st/stm32_fsdev/fsdev_ch32.h
+++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h
@@ -36,11 +36,21 @@
#include "common/tusb_compiler.h"
-#if CFG_TUSB_MCU == OPT_MCU_CH32V20X
- #include
+// https://github.com/openwch/ch32v307/pull/90
+// https://github.com/openwch/ch32v20x/pull/12
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
-#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
+#if CFG_TUSB_MCU == OPT_MCU_CH32F20X
#include
+#elif CFG_TUSB_MCU == OPT_MCU_CH32V20X
+ #include
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
#endif
#define FSDEV_PMA_SIZE (512u)
diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h
index af5d8afab..e8a6af8cb 100644
--- a/src/portable/st/stm32_fsdev/fsdev_common.h
+++ b/src/portable/st/stm32_fsdev/fsdev_common.h
@@ -295,18 +295,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, u
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPTX_DTOGMASK;
-
- /* toggle first bit ? */
- if((USB_EPTX_DTOG1 & (wState))!= 0U)
- {
- regVal ^= USB_EPTX_DTOG1;
- }
- /* toggle second bit ? */
- if((USB_EPTX_DTOG2 & ((uint32_t)(wState)))!= 0U)
- {
- regVal ^= USB_EPTX_DTOG2;
- }
-
+ regVal ^= wState;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
@@ -322,16 +311,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx
TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) {
uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx);
regVal &= USB_EPRX_DTOGMASK;
-
- /* toggle first bit ? */
- if((USB_EPRX_DTOG1 & wState)!= 0U) {
- regVal ^= USB_EPRX_DTOG1;
- }
- /* toggle second bit ? */
- if((USB_EPRX_DTOG2 & wState)!= 0U) {
- regVal ^= USB_EPRX_DTOG2;
- }
-
+ regVal ^= wState;
regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX;
pcd_set_endpoint(USBx, bEpIdx, regVal);
}
diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h
index b3fa11b88..a8f61a35f 100644
--- a/src/portable/st/stm32_fsdev/fsdev_stm32.h
+++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h
@@ -159,9 +159,38 @@
#define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS))
#endif
+#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
+ #include "stm32u5xx.h"
+ #define FSDEV_BUS_32BIT
+
+ #define FSDEV_PMA_SIZE (2048u)
+ #undef USB_PMAADDR
+ #define USB_PMAADDR USB_DRD_PMAADDR
+ #define USB_TypeDef USB_DRD_TypeDef
+ #define EP0R CHEP0R
+ #define USB_EP_CTR_RX USB_EP_VTRX
+ #define USB_EP_CTR_TX USB_EP_VTTX
+ #define USB_EP_T_FIELD USB_CHEP_UTYPE
+ #define USB_EPREG_MASK USB_CHEP_REG_MASK
+ #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK
+ #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK
+ #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1
+ #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2
+ #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1
+ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2
+ #define USB_EPRX_STAT USB_CH_RX_VALID
+ #define USB_EPKIND_MASK USB_EP_KIND_MASK
+ #define USB USB_DRD_FS
+ #define USB_CNTR_FRES USB_CNTR_USBRST
+ #define USB_CNTR_RESUME USB_CNTR_L2RES
+ #define USB_ISTR_EP_ID USB_ISTR_IDN
+ #define USB_EPADDR_FIELD USB_CHEP_ADDR
+ #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY
+ #define USB_CNTR_FSUSP USB_CNTR_SUSPEN
+
#else
#error You are using an untested or unimplemented STM32 variant. Please update the driver.
- // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4
+ // This includes U0
#endif
// This checks if the device has "LPM"
@@ -211,6 +240,8 @@ static const IRQn_Type fsdev_irq[] = {
#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
USB_HP_IRQn,
USB_LP_IRQn,
+ #elif CFG_TUSB_MCU == OPT_MCU_STM32U5
+ USB_IRQn,
#else
#error Unknown arch in USB driver
#endif
diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c
index dbcd586c5..9a38b46dc 100644
--- a/src/portable/synopsys/dwc2/dcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/dcd_dwc2.c
@@ -1195,25 +1195,13 @@ void dcd_int_handler(uint8_t rhport) {
// }
}
-#if defined(TUP_USBIP_DWC2_TEST_MODE) && CFG_TUD_TEST_MODE
-
-bool dcd_check_test_mode_support(test_mode_t test_selector) {
- // Check if test mode selector is unsupported
- if (TEST_FORCE_ENABLE < test_selector || TEST_J > test_selector) {
- return false;
- }
-
- return true;
-}
-
-void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) {
- // Get port address...
+#if CFG_TUD_TEST_MODE
+void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
// Enable the test mode
- dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (test_selector << DCTL_TCTL_Pos);
+ dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (((uint8_t) test_selector) << DCTL_TCTL_Pos);
}
-
-#endif /* TUP_USBIP_DWC2_TEST_MODE && CFG_TUD_TEST_MODE */
+#endif
#endif
diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h
index c50dd66b8..932f52f40 100644
--- a/src/portable/synopsys/dwc2/dwc2_esp32.h
+++ b/src/portable/synopsys/dwc2/dwc2_esp32.h
@@ -35,6 +35,7 @@
#include "esp_intr_alloc.h"
#include "soc/periph_defs.h"
//#include "soc/usb_periph.h"
+#include "freertos/task.h"
#define DWC2_REG_BASE 0x60080000UL
#define DWC2_EP_MAX 6 // USB_OUT_EP_NUM. TODO ESP32Sx only has 5 tx fifo (5 endpoint IN)
diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h
index 0a50a6169..68be64f5e 100644
--- a/src/portable/wch/ch32_usbfs_reg.h
+++ b/src/portable/wch/ch32_usbfs_reg.h
@@ -28,15 +28,79 @@
#ifndef USB_CH32_USBFS_REG_H
#define USB_CH32_USBFS_REG_H
-#if CFG_TUSB_MCU == OPT_MCU_CH32V307
- #include
- #define USBHD_IRQn OTG_FS_IRQn
+// https://github.com/openwch/ch32v307/pull/90
+// https://github.com/openwch/ch32v20x/pull/12
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+#if CFG_TUSB_MCU == OPT_MCU_CH32F20X
+ #include
+#elif CFG_TUSB_MCU == OPT_MCU_CH32V103
+ #include
+ typedef struct
+ {
+ __IO uint8_t BASE_CTRL;
+ __IO uint8_t UDEV_CTRL;
+ __IO uint8_t INT_EN;
+ __IO uint8_t DEV_ADDR;
+ __IO uint8_t Reserve0;
+ __IO uint8_t MIS_ST;
+ __IO uint8_t INT_FG;
+ __IO uint8_t INT_ST;
+ __IO uint32_t RX_LEN;
+ __IO uint8_t UEP4_1_MOD;
+ __IO uint8_t UEP2_3_MOD;
+ __IO uint8_t UEP5_6_MOD;
+ __IO uint8_t UEP7_MOD;
+ __IO uint32_t UEP0_DMA;
+ __IO uint32_t UEP1_DMA;
+ __IO uint32_t UEP2_DMA;
+ __IO uint32_t UEP3_DMA;
+ __IO uint32_t UEP4_DMA;
+ __IO uint32_t UEP5_DMA;
+ __IO uint32_t UEP6_DMA;
+ __IO uint32_t UEP7_DMA;
+ __IO uint16_t UEP0_TX_LEN;
+ __IO uint8_t UEP0_TX_CTRL;
+ __IO uint8_t UEP0_RX_CTRL;
+ __IO uint16_t UEP1_TX_LEN;
+ __IO uint8_t UEP1_TX_CTRL;
+ __IO uint8_t UEP1_RX_CTRL;
+ __IO uint16_t UEP2_TX_LEN;
+ __IO uint8_t UEP2_TX_CTRL;
+ __IO uint8_t UEP2_RX_CTRL;
+ __IO uint16_t UEP3_TX_LEN;
+ __IO uint8_t UEP3_TX_CTRL;
+ __IO uint8_t UEP3_RX_CTRL;
+ __IO uint16_t UEP4_TX_LEN;
+ __IO uint8_t UEP4_TX_CTRL;
+ __IO uint8_t UEP4_RX_CTRL;
+ __IO uint16_t UEP5_TX_LEN;
+ __IO uint8_t UEP5_TX_CTRL;
+ __IO uint8_t UEP5_RX_CTRL;
+ __IO uint16_t UEP6_TX_LEN;
+ __IO uint8_t UEP6_TX_CTRL;
+ __IO uint8_t UEP6_RX_CTRL;
+ __IO uint16_t UEP7_TX_LEN;
+ __IO uint8_t UEP7_TX_CTRL;
+ __IO uint8_t UEP7_RX_CTRL;
+ __IO uint32_t Reserve1;
+ __IO uint32_t OTG_CR;
+ __IO uint32_t OTG_SR;
+ } USBOTG_FS_TypeDef;
+
+ #define USBOTG_FS ((USBOTG_FS_TypeDef *) 0x40023400)
#elif CFG_TUSB_MCU == OPT_MCU_CH32V20X
#include
+#elif CFG_TUSB_MCU == OPT_MCU_CH32V307
+ #include
+ #define USBHD_IRQn OTG_FS_IRQn
+#endif
-#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
- #include
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
#endif
// CTRL
diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h
index 130e4f223..87300b497 100644
--- a/src/portable/wch/ch32_usbhs_reg.h
+++ b/src/portable/wch/ch32_usbhs_reg.h
@@ -28,12 +28,24 @@
#ifndef USB_CH32_USBHS_REG_H
#define USB_CH32_USBHS_REG_H
+// https://github.com/openwch/ch32v307/pull/90
+// https://github.com/openwch/ch32v20x/pull/12
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#endif
+
#if CFG_TUSB_MCU == OPT_MCU_CH32V307
#include
#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
#include
#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+
/******************* GLOBAL ******************/
// USB CONTROL
diff --git a/src/tusb.c b/src/tusb.c
index 0092267a1..860e8ac35 100644
--- a/src/tusb.c
+++ b/src/tusb.c
@@ -398,7 +398,7 @@ static void dump_str_line(uint8_t const* buf, uint16_t count) {
tu_printf(" |");
// each line is 16 bytes
for (uint16_t i = 0; i < count; i++) {
- const char ch = buf[i];
+ int ch = buf[i];
tu_printf("%c", isprint(ch) ? ch : '.');
}
tu_printf("|\r\n");
diff --git a/src/tusb_option.h b/src/tusb_option.h
index db8b94580..f2cc284dc 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -182,7 +182,7 @@
#define OPT_MCU_CH32V307 2200 ///< WCH CH32V307
#define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x
#define OPT_MCU_CH32V20X 2220 ///< WCH CH32V20X
-
+#define OPT_MCU_CH32V103 2230 ///< WCH CH32V103
// NXP LPC MCX
#define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series
@@ -381,7 +381,7 @@
#error "CFG_TUD_ENDPPOINT_MAX must be less than or equal to TUP_DCD_ENDPOINT_MAX"
#endif
-// USB 2.0 compliance test mode support
+// USB 2.0 7.1.20: compliance test mode support
#ifndef CFG_TUD_TEST_MODE
#define CFG_TUD_TEST_MODE 0
#endif
diff --git a/src/typec/tcd.h b/src/typec/tcd.h
index 86499c951..bcbdab8ed 100644
--- a/src/typec/tcd.h
+++ b/src/typec/tcd.h
@@ -63,7 +63,7 @@ typedef struct TU_ATTR_PACKED {
} xfer_complete;
};
-} tcd_event_t;;
+} tcd_event_t;
//--------------------------------------------------------------------+
//
diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py
index c2699cc6f..158841687 100644
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -114,11 +114,10 @@ def read_disk_file(id, fname):
# Flashing firmware
# -------------------------------------------------------------
def run_cmd(cmd):
- # print(cmd)
+ #print(cmd)
r = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- title = 'command error'
if r.returncode != 0:
- # print build output if failed
+ title = 'command error'
if os.getenv('CI'):
print(f"::group::{title}")
print(r.stdout.decode("utf-8"))
@@ -156,23 +155,23 @@ def flash_esptool(board, firmware):
return ret
-def doublereset_with_rpi_gpio(board):
+def doublereset_with_rpi_gpio(pin):
# Off = 0 = Reset
- led = gpiozero.LED(board["flasher_reset_pin"])
+ nrst = gpiozero.LED(pin)
- led.off()
+ nrst.off()
time.sleep(0.1)
- led.on()
+ nrst.on()
time.sleep(0.1)
- led.off()
+ nrst.off()
time.sleep(0.1)
- led.on()
+ nrst.on()
def flash_bossac(board, firmware):
# double reset to enter bootloader
if platform.machine() == 'aarch64':
- doublereset_with_rpi_gpio(board)
+ doublereset_with_rpi_gpio(board["flasher_reset_pin"])
port = get_serial_dev(board["uid"], board["flashser_vendor"], board["flasher_product"], 0)
timeout = ENUM_TIMEOUT
@@ -330,13 +329,19 @@ def main():
config_file = args.config_file
boards = args.board
- config_file = os.path.join(os.path.dirname(__file__), config_file)
+ # if config file is not found, try to find it in the same directory as this script
+ if not os.path.exists(config_file):
+ config_file = os.path.join(os.path.dirname(__file__), config_file)
with open(config_file) as f:
config = json.load(f)
- # all possible tests
+ # all possible tests: board_test is added last to disable board's usb
all_tests = [
- 'cdc_dual_ports', 'cdc_msc', 'dfu', 'dfu_runtime', 'hid_boot_interface',
+ 'cdc_dual_ports',
+ 'cdc_msc', 'cdc_msc_freertos',
+ 'dfu', 'dfu_runtime',
+ 'hid_boot_interface',
+ 'board_test'
]
if len(boards) == 0:
@@ -351,12 +356,9 @@ def main():
# default to all tests
if 'tests' in item:
- test_list = item['tests']
+ test_list = item['tests'] + ['board_test']
else:
- test_list = all_tests
-
- # board_test is added last to disable board's usb
- test_list.append('board_test')
+ test_list = list(all_tests)
# remove skip_tests
if 'tests_skip' in item:
@@ -365,9 +367,16 @@ def main():
test_list.remove(skip)
for test in test_list:
- fw_name = f'cmake-build/cmake-build-{name}/device/{test}/{test}'
+ fw_dir = f'cmake-build/cmake-build-{name}/device/{test}'
+ if not os.path.exists(fw_dir):
+ fw_dir = f'examples/cmake-build-{name}/device/{test}'
+ fw_name = f'{fw_dir}/{test}'
print(f' {test} ...', end='')
+ if not os.path.exists(fw_dir):
+ print('Skip')
+ continue
+
# flash firmware. It may fail randomly, retry a few times
for i in range(3):
ret = globals()[f'flash_{flasher}'](item, fw_name)
diff --git a/test/hil/pi4.json b/test/hil/pi4.json
deleted file mode 100644
index bdb8a5fa5..000000000
--- a/test/hil/pi4.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "boards": [
- {
- "name": "raspberry_pi_pico",
- "uid": "E6614C311B764A37",
- "flasher": "openocd",
- "flasher_sn": "E6614103E72C1D2F",
- "flasher_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\""
- },
- {
- "name": "feather_nrf52840_express",
- "uid": "1F0479CD0F764471",
- "flasher": "jlink",
- "flasher_sn": "000682804350",
- "flasher_args": "-device nrf52840_xxaa"
- },
- {
- "name": "itsybitsy_m4",
- "uid": "D784B28C5338533335202020FF044726",
- "flasher": "bossac",
- "flashser_vendor": "Adafruit Industries",
- "flasher_product": "ItsyBitsy M4 Express",
- "flasher_reset_pin": "2",
- "flasher_args": "--offset 0x4000"
- },
- {
- "name": "espressif_s3_devkitm",
- "uid": "84F703C084E4",
- "tests": [
- "cdc_msc_freertos", "hid_composite_freertos"
- ],
- "flasher": "esptool",
- "flasher_sn": "3ea619acd1cdeb11a0a0b806e93fd3f1",
- "flasher_args": "-b 1500000"
- }
- ]
-}
diff --git a/test/hil/rpi.json b/test/hil/rpi.json
new file mode 100644
index 000000000..dae3094b5
--- /dev/null
+++ b/test/hil/rpi.json
@@ -0,0 +1,58 @@
+{
+ "boards": [
+ {
+ "name": "raspberry_pi_pico",
+ "uid": "E6614C311B764A37",
+ "flasher": "openocd",
+ "flasher_sn": "E6614103E72C1D2F",
+ "flasher_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\""
+ },
+ {
+ "name": "feather_nrf52840_express",
+ "uid": "1F0479CD0F764471",
+ "flasher": "jlink",
+ "flasher_sn": "000682804350",
+ "flasher_args": "-device nrf52840_xxaa"
+ },
+ {
+ "name": "itsybitsy_m4",
+ "uid": "D784B28C5338533335202020FF044726",
+ "flasher": "openocd",
+ "flasher_sn": "E6614C311B597D32",
+ "flasher_args": "-f interface/cmsis-dap.cfg -f target/atsame5x.cfg -c \"adapter speed 5000\""
+ },
+ {
+ "name": "espressif_s3_devkitm",
+ "uid": "84F703C084E4",
+ "tests": [
+ "cdc_msc_freertos", "hid_composite_freertos"
+ ],
+ "flasher": "esptool",
+ "flasher_sn": "3ea619acd1cdeb11a0a0b806e93fd3f1",
+ "flasher_args": "-b 921600"
+ },
+ {
+ "name": "metro_m7_1011",
+ "uid": "9CE8715DD71137363E00005002004200",
+ "flasher": "jlink",
+ "flasher_sn": "000611000000",
+ "flasher_args": "-device MIMXRT1011xxx5A"
+ },
+ {
+ "name": "ra4m1_ek",
+ "uid": "152E163038303131393346E46F26574B",
+ "tests_skip": ["cdc_msc", "cdc_msc_freertos"],
+ "comment": "MSC is slow to enumerated #2602",
+ "flasher": "jlink",
+ "flasher_sn": "000831174392",
+ "flasher_args": "-device R7FA4M1AB"
+ },
+ {
+ "name": "lpcxpresso11u37",
+ "uid": "17121919",
+ "flasher": "jlink",
+ "flasher_sn": "000724441579",
+ "flasher_args": "-device LPC11U37/401"
+ }
+ ]
+}
diff --git a/tools/get_deps.py b/tools/get_deps.py
index cf15126b3..7fbde0e02 100644
--- a/tools/get_deps.py
+++ b/tools/get_deps.py
@@ -14,7 +14,7 @@ deps_mandatory = {
'159e31b689577dbf69cf0683bbaffbd71fa5ee10',
'all'],
'tools/uf2': ['https://github.com/microsoft/uf2.git',
- '19615407727073e36d81bf239c52108ba92e7660',
+ 'c594542b2faa01cc33a2b97c9fbebc38549df80a',
'all'],
}
@@ -49,7 +49,7 @@ deps_optional = {
'2204191ec76283371419fbcec207da02e1bc22fa',
'nuc'],
'hw/mcu/nxp/lpcopen': ['https://github.com/hathach/nxp_lpcopen.git',
- '04bfe7a5f6ee74a89a28ad618d3367dcfcfb7d83',
+ 'b41cf930e65c734d8ec6de04f1d57d46787c76ae',
'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43'],
'hw/mcu/nxp/mcux-sdk': ['https://github.com/hathach/mcux-sdk.git',
'144f1eb7ea8c06512e12f12b27383601c0272410',
@@ -168,11 +168,14 @@ deps_optional = {
'hw/mcu/ti': ['https://github.com/hathach/ti_driver.git',
'143ed6cc20a7615d042b03b21e070197d473e6e5',
'msp430 msp432e4 tm4c'],
+ 'hw/mcu/wch/ch32v103': ['https://github.com/openwch/ch32v103.git',
+ '7578cae0b21f86dd053a1f781b2fc6ab99d0ec17',
+ 'ch32v10x'],
'hw/mcu/wch/ch32v20x': ['https://github.com/openwch/ch32v20x.git',
- 'de6d68c654340d7f27b00cebbfc9aa2740a1abc2',
+ 'c4c38f507e258a4e69b059ccc2dc27dde33cea1b',
'ch32v20x'],
'hw/mcu/wch/ch32v307': ['https://github.com/openwch/ch32v307.git',
- '17761f5cf9dbbf2dcf665b7c04934188add20082',
+ '184f21b852cb95eed58e86e901837bc9fff68775',
'ch32v307'],
'hw/mcu/wch/ch32f20x': ['https://github.com/openwch/ch32f20x.git',
'77c4095087e5ed2c548ec9058e655d0b8757663b',