Merge branch 'master' of https://github.com/hathach/tinyusb into rx_fb

This commit is contained in:
HiFiPhile 2024-07-28 11:59:52 +02:00
commit f48a4567a6
160 changed files with 4439 additions and 2919 deletions

View File

@ -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

View File

@ -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]

View File

@ -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 }}

View File

@ -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"],
}

View File

@ -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 }}

60
.gitignore vendored
View File

@ -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

26
.idea/cmake.xml generated
View File

@ -3,6 +3,7 @@
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="pico" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=raspberry_pi_pico -DLOG=1" />
<configuration PROFILE_NAME="pico pio-host" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=raspberry_pi_pico -DLOG=1 -DCFLAGS_CLI=&quot;-DCFG_TUH_RPI_PIO_USB=1&quot;" />
<configuration PROFILE_NAME="feather_rp2040" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pico_sdk -DPICO_BOARD=adafruit_feather_rp2040 -DLOG=2" />
<configuration PROFILE_NAME="feather_rp2040_max3421" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_rp2040_max3421 -DLOG=2" />
<configuration PROFILE_NAME="metro_rp2040" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pico_sdk -DPICO_BOARD=adafruit_metro_rp2040 -DLOG=2 -DMAX3421_HOST=1" />
@ -65,14 +66,14 @@
<configuration PROFILE_NAME="feather_m0_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_m0_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="metro_m0_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m0_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="feather_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_m4_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="metro_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="itsybitsy_m4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=itsybitsy_m4 -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="metro_m4_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m4_express" />
<configuration PROFILE_NAME="itsybitsy_m4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=itsybitsy_m4" />
<configuration PROFILE_NAME="same54_xplained" ENABLED="false" GENERATION_OPTIONS="-DBOARD=same54_xplained -DLOG=2 -DLOGGER=RTT" />
<configuration PROFILE_NAME="feather_nrf52840_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_nrf52840_express -DLOG=3 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="feather_nrf52840_express" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=feather_nrf52840_express -DLOG=1 -DLOGGER=RTT -DMAX3421_HOST=1" />
<configuration PROFILE_NAME="pca10056" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10056 -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" />
<configuration PROFILE_NAME="pca10095" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=pca10095 -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" />
<configuration PROFILE_NAME="metro m7 1011 sd" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m7_1011_sd -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" />
<configuration PROFILE_NAME="metro m7 1011" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m7_1011 -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="metro_m7_1011" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=metro_m7_1011 -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="rt1010 evk" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=mimxrt1010_evk -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="rt1060 evk" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=mimxrt1060_evk -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="rt1170 evkb" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=mimxrt1170_evkb -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" />
@ -105,17 +106,18 @@
<configuration PROFILE_NAME="stm32u575nucleo" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32u575nucleo -DLOG=2 -DLOGGER=RTT" />
<configuration PROFILE_NAME="stm32u5a5nucleo" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=stm32u5a5nucleo -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="stm32wb55nucleo" ENABLED="false" GENERATION_OPTIONS="-DBOARD=stm32wb55nucleo" />
<configuration PROFILE_NAME="ra2a1" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra2a1_ek -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="ra4m1" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra4m1_ek -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="ra6m1" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m1_ek -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="ra6m5" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m5_ek -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" />
<configuration PROFILE_NAME="ra6m5 PORT0" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m5_ek -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1 -DPORT=0" />
<configuration PROFILE_NAME="ra2a1_ek" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra2a1_ek -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="ra4m1_ek" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra4m1_ek -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="ra6m1_ek" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m1_ek -DLOG=3 -DLOGGER=RTT" />
<configuration PROFILE_NAME="ra6m5_ek" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m5_ek -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1" />
<configuration PROFILE_NAME="ra6m5_ek PORT0" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ra6m5_ek -DLOG=3 -DLOGGER=RTT -DTRACE_ETM=1 -DPORT=0" />
<configuration PROFILE_NAME="uno_r4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=uno_r4 -DLOG=4 -DLOGGER=RTT" />
<configuration PROFILE_NAME="portenta_c33" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=portenta_c33 -DLOG=3" />
<configuration PROFILE_NAME="msp430f5529" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=msp_exp430f5529lp" />
<configuration PROFILE_NAME="raspberrypi_zero" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=raspberrypi_zero -DLOG=2" />
<configuration PROFILE_NAME="raspberrypi_cm4" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=raspberrypi_cm4 -DLOG=2" />
<configuration PROFILE_NAME="raspberrypi_zero2" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=raspberrypi_zero2 -DLOG=2" />
<configuration PROFILE_NAME="lpcxpresso11u37" ENABLED="false" GENERATION_OPTIONS="-DBOARD=lpcxpresso11u37" />
<configuration PROFILE_NAME="lpcxpresso11u68" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=lpcxpresso11u68 -DLOG=2 -DLOGGER=RTT" />
<configuration PROFILE_NAME="lpcxpresso1347" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=lpcxpresso1347 -DLOG=2 -DLOGGER=RTT" />
<configuration PROFILE_NAME="lpcxpresso1549" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=lpcxpresso1549 -DLOG=2 -DLOGGER=RTT" />
@ -131,10 +133,12 @@
<configuration PROFILE_NAME="fomu" ENABLED="false" GENERATION_OPTIONS="-DBOARD=fomu" />
<configuration PROFILE_NAME="sipeed_longan_nano" ENABLED="false" GENERATION_OPTIONS="-DBOARD=sipeed_longan_nano" />
<configuration PROFILE_NAME="nanoch32v203" ENABLED="false" GENERATION_OPTIONS="-DBOARD=nanoch32v203" />
<configuration PROFILE_NAME="ch32v203_r0_1v0" ENABLED="false" CONFIG_NAME="MinSizeRel" GENERATION_OPTIONS="-DBOARD=ch32v203_r0_1v0" />
<configuration PROFILE_NAME="ch32v203_r0_1v0 USBFS" ENABLED="false" CONFIG_NAME="MinSizeRel" GENERATION_OPTIONS="-DBOARD=ch32v203_r0_1v0 -DPORT=1" />
<configuration PROFILE_NAME="ch32v203c_r0_1v0" ENABLED="false" CONFIG_NAME="MinSizeRel" GENERATION_OPTIONS="-DBOARD=ch32v203c_r0_1v0" />
<configuration PROFILE_NAME="ch32v203c_r0_1v0 USBFS" ENABLED="false" CONFIG_NAME="MinSizeRel" GENERATION_OPTIONS="-DBOARD=ch32v203c_r0_1v0 -DPORT=1" />
<configuration PROFILE_NAME="ch32v203g_r0_1v0" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=ch32v203g_r0_1v0" />
<configuration PROFILE_NAME="ch32v307v_r1_1v0" ENABLED="false" GENERATION_OPTIONS="-DBOARD=ch32v307v_r1_1v0 -DLOG=2" />
<configuration PROFILE_NAME="ch32v307v_r1_1v0 USBFS" ENABLED="false" GENERATION_OPTIONS="-DBOARD=ch32v307v_r1_1v0 -DSPEED=full" />
<configuration PROFILE_NAME="da14695_dk_usb" ENABLED="false" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DBOARD=da14695_dk_usb" />
</configurations>
</component>
</project>

View File

@ -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 |
+--------------+------------------------------------------------------------+

View File

@ -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
================

View File

@ -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 ()

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,4 @@
mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56

View File

@ -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

View File

@ -1,3 +1,4 @@
mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56

View File

@ -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

View File

@ -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
//--------------------------------------------------------------------+

View File

@ -1,2 +1,3 @@
mcu:SAMD11
family:espressif
board:ch32v203g_r0_1v0

View File

@ -1,3 +1,4 @@
mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56

View File

@ -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

View File

@ -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)

View File

@ -1,2 +1,3 @@
mcu:SAMD11
family:espressif
board:ch32v203g_r0_1v0

View File

@ -1,3 +1,4 @@
mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:CXD56

View File

@ -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

View File

@ -5,7 +5,14 @@ include(${CMAKE_CURRENT_LIST_DIR}/../../../hw/bsp/family_support.cmake)
# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
# 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()

View File

@ -1,3 +1,4 @@
mcu:CH32V103
mcu:CH32V20X
mcu:LPC11UXX
mcu:LPC13XX

View File

@ -1,3 +1,4 @@
mcu:CH32V103
mcu:CH32V20X
mcu:MSP430x5xx
mcu:NUC121

View File

@ -2,6 +2,7 @@ mcu:MSP430x5xx
mcu:NUC121
mcu:SAMD11
mcu:GD32VF103
mcu:CH32V103
mcu:CH32V20X
mcu:CH32V307
mcu:STM32L0

View File

@ -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 ()

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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. <BOARD>-<DIR_NAME>)
family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
project(${PROJECT} C CXX ASM)
# Checks this example is valid for the family and initializes the project
family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
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
)

View File

@ -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

View File

@ -0,0 +1,6 @@
board:mimxrt1060_evk
board:mimxrt1064_evk
board:mcb1800
mcu:RP2040
mcu:ra6m5
mcu:MAX3421

View File

@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -23,10 +23,6 @@
*
*/
/* This example current worked and tested with following controller
* - Sony DualShock 4 [CUH-ZCT2x] VID = 0x054c, PID = 0x09cc
*/
#include <stdlib.h>
#include <stdio.h>

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#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);
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -1,5 +1,3 @@
set(MCU_VARIANT D6)
set(LD_FLASH_SIZE 64K)
set(LD_RAM_SIZE 20K)

View File

@ -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

View File

@ -0,0 +1,5 @@
CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY
LDFLAGS += \
-Wl,--defsym=__FLASH_SIZE=64K \
-Wl,--defsym=__RAM_SIZE=20K \

View File

@ -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 */

View File

@ -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 */

148
hw/bsp/ch32v10x/family.c Normal file
View File

@ -0,0 +1,148 @@
#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 "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;
}

View File

@ -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()

53
hw/bsp/ch32v10x/family.mk Normal file
View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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 */

View File

@ -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"

View File

@ -1,7 +0,0 @@
MCU_VARIANT = D6
CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY
LDFLAGS += \
-Wl,--defsym=__flash_size=64K \
-Wl,--defsym=__ram_size=20K \

View File

@ -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()

View File

@ -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

View File

@ -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 \

View File

@ -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()

View File

@ -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

View File

@ -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 \

View File

@ -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()

View File

@ -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
}

View File

@ -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 \

View File

@ -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

View File

@ -1,6 +1,18 @@
#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 "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
//--------------------------------------------------------------------

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -25,8 +25,17 @@
*/
#include "debug_uart.h"
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif
#include <ch32v30x.h>
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#define UART_RINGBUFFER_SIZE_TX 128
#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)

View File

@ -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"

View File

@ -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}
)

View File

@ -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

View File

@ -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 <hal/hal_gpio.h>
#include <mcu/mcu.h>
//--------------------------------------------------------------------+
// 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

View File

@ -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<<configPRIO_BITS) - 1)
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#endif

View File

@ -0,0 +1,4 @@
set(JLINK_DEVICE DA14695)
function(update_board TARGET)
endfunction()

View File

@ -0,0 +1,10 @@
#ifndef BOARD_H
#define BOARD_H
#define LED_PIN 33 // P1.1
#define LED_STATE_ON 1
#define BUTTON_PIN 6
#define BUTTON_STATE_ACTIVE 1
#endif

View File

@ -0,0 +1 @@
JLINK_DEVICE = DA14695

View File

@ -0,0 +1,4 @@
set(JLINK_DEVICE DA14699)
function(update_board TARGET)
endfunction()

View File

@ -0,0 +1,12 @@
#ifndef BOARD_H
#define BOARD_H
#define LED_PIN 33
#define LED_STATE_ON 1
#define BUTTON_PIN 6
#define BUTTON_STATE_ACTIVE 0
#define NEED_VBUS_MONITOR
#endif

View File

@ -0,0 +1,2 @@
# For flash-jlink target
JLINK_DEVICE = DA14699

View File

@ -25,24 +25,25 @@
*/
#include "bsp/board_api.h"
#include "board.h"
#include <hal/hal_gpio.h>
#include <mcu/mcu.h>
#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

141
hw/bsp/da1469x/family.cmake Normal file
View File

@ -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 $<TARGET_FILE_DIR:${TARGET}>/version.h
CONTENT "#define SW_VERSION \"v_1.0.0.1\"
#define SW_VERSION_DATE \"2024-07-17 17:55\""
)
file(GENERATE OUTPUT $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.jlink
CONTENT "r
halt
loadfile $<TARGET_FILE_DIR:${TARGET}>/${TARGET}-image.bin 0x16000000
r
go
exit"
)
add_custom_target(${TARGET}-image
DEPENDS ${TARGET}
COMMAND ${MKIMAGE} da1469x $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin $<TARGET_FILE_DIR:${TARGET}>/version.h $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin.img
COMMAND cp ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/product_header.dump $<TARGET_FILE_DIR:${TARGET}>/${TARGET}-image.bin
COMMAND cat $<TARGET_FILE_DIR:${TARGET}>/${TARGET}.bin.img >> $<TARGET_FILE_DIR:${TARGET}>/${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_FILE_DIR:${TARGET}>/${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()

View File

@ -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

View File

@ -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

View File

@ -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")
}

Some files were not shown because too many files have changed in this diff Show More